"Fossies" - the Fresh Open Source Software Archive

Member "TeXmacs-2.1.2-src/src/Plugins/Qt/QTMSockets.cpp" (5 May 2022, 12855 Bytes) of package /linux/misc/TeXmacs-2.1.2-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 
    2 /******************************************************************************
    3 * MODULE     : QTMsockets.cpp
    4 * DESCRIPTION: QT TeXmacs sockets manager
    5 * COPYRIGHT  : (C) 2015 Denis RAUX
    6 *******************************************************************************
    7 * This software falls under the GNU general public license version 3 or later.
    8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
    9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
   10 ******************************************************************************/
   11 
   12 #include "QTMSockets.hpp"
   13 #include "scheme.hpp"
   14 #include "iterator.hpp"
   15 #include "analyze.hpp"
   16 
   17 #ifndef OS_MINGW
   18 
   19 #include <errno.h>
   20 #include <unistd.h>
   21 #include <sys/types.h>
   22 #include <sys/socket.h>
   23 #include <netinet/in.h>
   24 #include <netdb.h>
   25 #include <stdint.h>
   26 #include <fcntl.h>
   27 #include <arpa/inet.h>
   28 
   29 #define CONNECT ::connect
   30 #define CLOSE(a) close(a)
   31 #define WRITE(a, b, c) ::write(a, b, c)
   32 #define ERRNO errno
   33 #define ERRSOC(a) a 
   34 #define GETADDRINFO getaddrinfo
   35 #define FREEADDRINFO freeaddrinfo
   36 #define ADDRINFO addrinfo
   37 #define SOCKET socket
   38 #define RECV recv
   39 #define GAI_STRERROR gai_strerror
   40 #define BIND bind
   41 #define LISTEN listen
   42 #define ACCEPT accept
   43 #define INET_NTOP inet_ntop
   44 
   45 #else
   46 
   47 #define CONNECT wsoc::connect
   48 #define CLOSE(a) wsoc::closesocket(a)
   49 #define WRITE(a, b, c) wsoc::send(a, b, c, 0) 
   50 #define ERRNO wsoc::WSAGetLastError()
   51 #define ERRSOC(a) WSA##a 
   52 #define GETADDRINFO wsoc::getaddrinfo 
   53 #define FREEADDRINFO wsoc::freeaddrinfo
   54 #define ADDRINFO wsoc::addrinfo
   55 #define SOCKET wsoc::socket
   56 #define RECV wsoc::recv
   57 #define GAI_STRERROR wsoc::gai_strerror
   58 #define BIND wsoc::bind
   59 #define LISTEN wsoc::listen
   60 #define ACCEPT wsoc::accept
   61 #define INET_NTOP wsoc::inet_ntop
   62 
   63 #endif
   64 
   65 unsigned qtmsocket_debug_count;
   66 
   67 int socket_basic::count= 0;
   68 
   69 #ifdef OS_MINGW
   70 wsoc::WSADATA socket_basic::wsadata;
   71 #endif
   72 
   73 static string
   74 string_from_socket_address (SOCKADDR_STORAGE* sock) {
   75   static char tmp[128];
   76   if (sock->ss_family == AF_INET) {
   77 #ifdef OS_MINGW
   78     return wsoc::inet_ntoa (((SOCKADDR_IN*) sock)->sin_addr);
   79 #else
   80     if (inet_ntop (AF_INET, &(((sockaddr_in*) sock)->sin_addr),
   81            tmp, sizeof(tmp)) == NULL)
   82       return "";
   83     return tmp;
   84 #endif
   85   }
   86   if (sock->ss_family == AF_INET6) {
   87 #if !defined (OS_MINGW) || (_WIN32_WINNT >= 0x0600)
   88     if (INET_NTOP (AF_INET6, &(((SOCKADDR_IN6*) sock)->sin6_addr),
   89            tmp, sizeof(tmp)) == NULL)
   90       return "";
   91 #else
   92     return "";
   93 #endif
   94     return tmp;
   95   }
   96   return "";
   97 }
   98 
   99 socket_basic::socket_basic (): st (ST_VOID) {
  100 #ifdef OS_MINGW
  101   if (!count) {
  102     using namespace wsoc;
  103     err= WSAStartup (MAKEWORD (2,0), &wsadata);
  104     if (err) {st= ST_WSA; return;}
  105   }
  106 #endif
  107   count++;
  108 };
  109 
  110 socket_basic::~socket_basic () {
  111   if (count > 0) --count;
  112 #ifdef OS_MINGW
  113   if (!count) wsoc::WSACleanup ();
  114 #endif
  115 };
  116 
  117 socket_link::socket_link (int s, SOCKADDR_STORAGE* addr) {
  118   id++; sock= s; qsnr= NULL; qsnw= NULL;
  119   if (st != ST_VOID) return;
  120   memcpy (&add, addr, sizeof(add));
  121   qsnr= tm_new<QSocketNotifier> (s, QSocketNotifier::Read);
  122   qsnw= tm_new<QSocketNotifier> (s, QSocketNotifier::Write);
  123   if (!qsnr || !qsnw) { err= ERRNO; st= ST_NOTIF; return; }
  124   QObject::connect (qsnr, SIGNAL(activated(int)),
  125             this, SLOT(data_set_ready(int)));
  126   QObject::connect (qsnw, SIGNAL(activated(int)),
  127             this, SLOT(ready_to_send(int)));
  128   DBG_IO ("Socket created with fd= " << sock);
  129   st= ST_OK;
  130 }
  131 
  132 socket_link::socket_link (string host, unsigned short port) {
  133   ++id; qsnr= NULL; qsnw= NULL;
  134   if (st != ST_VOID) return;
  135   string host_tmp= host;
  136   if (starts (host, "[") && ends (host, "]"))
  137     host_tmp = host(1, N(host)-1);
  138   c_string _host (host_tmp);
  139   c_string _port (as_string (port));
  140   struct ADDRINFO hints;
  141   struct ADDRINFO *result, *rp;
  142   memset(&hints, 0, sizeof(hints));
  143   hints.ai_family = AF_UNSPEC;
  144   hints.ai_socktype = SOCK_STREAM;
  145   hints.ai_flags = AI_PASSIVE;
  146   hints.ai_protocol = 0;
  147   hints.ai_canonname = NULL;
  148   hints.ai_addr = NULL;
  149   hints.ai_next = NULL;
  150   int x = GETADDRINFO (_host, _port, &hints, &result);
  151   if (x != 0) { err= ERRNO; st= ST_GETHOST; return; };
  152   for (rp = result; rp != NULL; rp = rp->ai_next) {
  153     sock= SOCKET (rp->ai_family, rp->ai_socktype,
  154           rp->ai_protocol);
  155     if (sock < 0)
  156       continue;
  157     if (CONNECT (sock, rp->ai_addr, rp->ai_addrlen) != -1)
  158       break;
  159     CLOSE (sock);
  160   }
  161   if (rp == NULL) { err= ERRNO; st= ST_CONNECTION; return; }
  162   FREEADDRINFO (result);
  163 #ifndef OS_MINGW
  164   if (fcntl (sock, F_SETFL, O_NONBLOCK) == -1) {
  165     err= errno; st= ST_FCNTL; return; }
  166 #else
  167   {
  168     using namespace wsoc;
  169     u_long flags = -1;
  170     if (ioctlsocket (sock, FIONBIO, &flags) == SOCKET_ERROR) {
  171       err= ERRNO; st= ST_FCNTL; return; }
  172   }
  173 #endif
  174   qsnr= tm_new<QSocketNotifier> (sock, QSocketNotifier::Read);
  175   qsnw= tm_new<QSocketNotifier> (sock, QSocketNotifier::Write);
  176   if (!qsnr || !qsnw) { err= ERRNO; st= ST_NOTIF; return; }
  177   QObject::connect (qsnr, SIGNAL (activated(int)),
  178             this, SLOT (data_set_ready(int)));
  179   qsnw->setEnabled (false);
  180   QObject::connect (qsnw, SIGNAL (activated(int)),
  181             this, SLOT (ready_to_send(int)));
  182   DBG_IO ("Socket created with fd= " << sock);
  183   st= ST_OK;
  184 }
  185 
  186 socket_link::~socket_link() {
  187   DBG_IO ("Closing socket for fd= " << sock);
  188   if (qsnr) { qsnr->disconnect (SIGNAL(activated(int))); tm_delete (qsnr); }
  189   if (qsnw) { qsnw->disconnect (SIGNAL(activated(int))); tm_delete (qsnw); }
  190   if (sock != -1) { CLOSE (sock); sock=-1;}
  191   st= ST_CLOSED;
  192 }
  193 
  194 string
  195 socket_link::start () {
  196   string ret;
  197   switch(st) {
  198   case ST_OK:         return ""; break;
  199   case ST_VOID:       ret= "Socket not initialised"; break;
  200   case ST_SOCKET:     ret= "Error in opening socket"; break;
  201   case ST_FCNTL:      ret= "Error in setting blocking mode"; break;
  202   case ST_BIND:       ret= "Error during bind"; break;
  203   case ST_LISTEN:     ret= "Error during listen"; break;
  204   case ST_CONNECTION: ret= "Error during connect"; break;
  205   case ST_GETHOST:    ret= "Error in getting host"; break;
  206   case ST_NOTIF:      ret= "Error in setting notifier"; break;
  207   default:            ret= "No error message";
  208   }
  209   return ret * " errno: " * strerror(err);
  210 }
  211 
  212 string&
  213 socket_link::watch (int channel) {
  214   static string empty_string= "";
  215   if (channel == LINK_OUT) return inbuf;
  216   else return empty_string;
  217 }
  218 
  219 string
  220 socket_link::read (int channel) {
  221   DBG_IO ("Socket read size= " << N(inbuf));
  222   if (channel == LINK_OUT && N(inbuf)) {
  223     string r= inbuf;
  224     inbuf= "";
  225     return r;
  226   }
  227   else return "";
  228 }
  229 
  230 void
  231 socket_link::stop () {
  232   st= ST_HALTED;
  233   emit disconnection (this);
  234 }
  235 
  236 void
  237 socket_link::data_set_ready (int s) {
  238   char data[2048];
  239   qsnr->setEnabled (false);
  240   int lgdata= RECV(s, data, sizeof(data), 0);
  241   DBG_IO ("Socket incoming code= " << lgdata);
  242   if (lgdata == 0) {
  243     DBG_IO ("Client disconnected");   
  244     stop ();
  245   }
  246   else if (lgdata == -1) {
  247     switch (ERRNO) {
  248     case ERRSOC(EWOULDBLOCK):
  249     case ERRSOC(ECONNRESET):
  250     case ERRSOC(ECONNABORTED): DBG_IO("Client disconnected"); break;
  251     default: DBG_IO("Receiving error: " << ERRNO);
  252     }
  253     stop ();
  254   }
  255   else {
  256     inbuf << string (data, lgdata);
  257     if (DEBUG_IO) {
  258       string s (data, lgdata);
  259       bool ok= true;
  260       for (int i= 0; i < N(s); i++)
  261         if (((int) (unsigned char) s[i]) >= 128 ||
  262             (((int) (unsigned char) s[i]) < 32 &&
  263              s[i] != '\n' && s[i] != '\t')) ok= false;
  264       if (ok) { DBG_IO("Data received: " << s); }
  265       else { DBG_IO("Binary data received size= " << N(s)); }
  266     }
  267     qsnr->setEnabled (true);
  268   }
  269 }
  270 
  271 void
  272 socket_link::ready_to_send (int s) {
  273 #ifdef OS_MINGW
  274   using namespace wsoc;
  275 #endif
  276   qsnw->setEnabled (false);
  277   int sz= N(outbuf);
  278   if (sz) {
  279     char* buf= as_charp (outbuf);
  280     int ret= WRITE(s, buf, sz);
  281     DBG_IO ("Socket outcoming code= " << ret);
  282     if (ret >0) {
  283       if (ret == sz) outbuf= ""; else outbuf= outbuf (ret, sz);
  284       sz -= ret;
  285       if (sz) qsnw->setEnabled (true);
  286     }
  287     else if (ret <0) {
  288       DBG_IO ("Sending error: " << strerror (ERRNO));
  289       stop ();
  290     }
  291     else qsnw->setEnabled (true);
  292   }
  293 }
  294 
  295 void
  296 socket_link::listen (int msecs) {
  297 #ifdef OS_MINGW
  298   using namespace wsoc;
  299 #endif
  300   if (!alive ()) return;
  301   ready_to_send (sock);
  302   fd_set rfds;
  303   FD_ZERO (&rfds);
  304   FD_SET (sock, &rfds);
  305   struct timeval tv;
  306   tv.tv_sec = msecs / 1000;
  307   tv.tv_usec= 1000 * (msecs % 1000);
  308   int nr= select (sock+1, &rfds, NULL, NULL, &tv);
  309   if (nr == 1) data_set_ready (sock);
  310   DBG_IO ("Listenning result: " << nr);
  311   if (nr == -1) stop();
  312 }
  313 
  314 void
  315 socket_link::write (string s, int channel) {
  316   DBG_IO ("Socket write size= " << N(s));
  317   if ((!alive ()) || (channel != LINK_IN) || !N(s)) return;
  318   outbuf << s;
  319   qsnw->setEnabled(true);
  320 }
  321 
  322 socket_server::socket_server (string host, unsigned short port) {
  323   c_string _port (as_string (port));
  324   c_string _host (host);
  325   struct ADDRINFO hints;
  326   struct ADDRINFO *result, *rp;
  327   memset(&hints, 0, sizeof(struct ADDRINFO));
  328   hints.ai_family = AF_UNSPEC;
  329   hints.ai_socktype = SOCK_STREAM;
  330   hints.ai_flags = AI_PASSIVE;
  331   hints.ai_protocol = 0;
  332   hints.ai_canonname = NULL;
  333   hints.ai_addr = NULL;
  334   hints.ai_next = NULL;
  335   int x = GETADDRINFO (host == "" ? (char*) NULL : (char*)_host,
  336                _port, &hints, &result);
  337   if (x != 0)  {
  338     DBG_IO(GAI_STRERROR(x));
  339     err= ERRNO;
  340     st= ST_GETHOST;
  341     return;
  342   }
  343   sock = -1;
  344   for (rp = result; rp != NULL; rp = rp->ai_next) {
  345     DBG_IO ("Serving at " *
  346         string_from_socket_address ((SOCKADDR_STORAGE*) rp->ai_addr));
  347     sock= SOCKET (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  348     if (sock < 0)
  349       continue;
  350 #ifndef OS_MINGW
  351     if (fcntl (sock, F_SETFL, O_NONBLOCK) == -1) 
  352       continue;
  353 #else 
  354     { using namespace wsoc;
  355       u_long flags = -1;
  356       if (ioctlsocket (sock, FIONBIO, &flags) == SOCKET_ERROR)
  357     continue;
  358     }
  359 #endif
  360     if (BIND (sock, rp->ai_addr, rp->ai_addrlen) == 0)
  361       break;
  362     DBG_IO (strerror (errno));
  363     DBG_IO ("Socket bind failed");
  364     CLOSE (sock);
  365     sock = -1;
  366   }
  367   FREEADDRINFO (result); 
  368   if (sock == -1) {
  369     DBG_IO ("Cannot find socket binding for server");
  370     err= ERRNO;
  371     st= ST_BIND;
  372     return; 
  373   } 
  374   if (LISTEN (sock, 10) != 0) {
  375     DBG_IO ("Cannot listen on server socket");
  376     err= ERRNO;
  377     st= ST_LISTEN;
  378     return;
  379   }
  380   qsnc= tm_new<QSocketNotifier> (sock, QSocketNotifier::Read);
  381   QObject::connect (qsnc, SIGNAL (activated(int)), this, SLOT (connection(int)));
  382   DBG_IO ("Wait for connection");
  383 }
  384 
  385 void
  386 socket_server::connection (int s) {
  387   int sclt; socket_link* clt;
  388   SOCKADDR_STORAGE cltadd;
  389   socklen_t sz= sizeof (cltadd);
  390   if (!qsnc->isEnabled ()) return;
  391   sclt= ACCEPT (s, (SOCKADDR*) &cltadd, &sz);
  392   if (sclt > 0) {
  393     clt= tm_new<socket_link> (sclt, &cltadd);
  394     if (clt) {
  395       if (clt->alive ()) {
  396         connect (clt, SIGNAL (disconnection(socket_link*)), this,
  397          SLOT (disconnection (socket_link*)));
  398         clts->insert ((pointer) clt);
  399         call ("server-add", object (clt->getid ()));
  400         DBG_IO ("Client Connected from "
  401             << string_from_socket_address (&cltadd)
  402             << ", with id: " << clt->getid ());
  403       }
  404       else tm_delete (clt);
  405     }
  406   }
  407   else switch (ERRNO) {
  408     case ERRSOC (EWOULDBLOCK):
  409     case ERRSOC (ECONNABORTED): break;
  410     default: err= ERRNO; qsnc->setEnabled (false); st= ST_CONNECTION;
  411     }
  412 }
  413 
  414 void 
  415 socket_server::disconnection (class socket_link* clt) {
  416   call ("server-remove", object (clt->getid()));
  417   clts->remove ((pointer) clt);
  418   tm_delete (clt);
  419 }
  420 
  421 string
  422 socket_server::read (int id) {
  423   socket_link *clt= find_client (id);
  424   if (!clt) return "";
  425   bool success;
  426   string back= clt->read_packet (LINK_OUT, 0, success);
  427   return back;
  428 }
  429 
  430 void
  431 socket_server::write (int id, string s) {
  432   socket_link *clt= find_client (id);
  433   if (clt) clt->write_packet(s, LINK_IN);
  434 }
  435 
  436 socket_link *
  437 socket_server::find_client (int id) {
  438   iterator<pointer> it= iterate (clts);
  439   while (it->busy ()) {
  440     socket_link* clt= (socket_link*) it->next ();
  441     if (clt->getid() == id) return clt;
  442   }
  443   array<int> ids;
  444   it= iterate (clts);
  445   while (it->busy ()) {
  446     socket_link* clt= (socket_link*) it->next ();
  447     ids << clt->getid();
  448   }
  449   DBG_IO ("Client not found, id= " << id << ", among= " << ids);
  450   return NULL;
  451 }
  452 
  453 socket_server::~socket_server () {
  454   iterator<pointer> it= iterate (clts);
  455   while (it->busy ()) {
  456     socket_link* clt= (socket_link*) it->next ();
  457     disconnection (clt);
  458   }
  459 }
  460 
  461 string
  462 debug_io_string (string s) {
  463   int i, n= N(s);
  464   string r;
  465   for (i=0; i<n; i++) {
  466     unsigned char c= (unsigned char) s[i];
  467     if (c == DATA_BEGIN) r << "[BEGIN]";
  468     else if (c == DATA_END) r << "[END]";
  469     else if (c == DATA_COMMAND) r << "[COMMAND]";
  470     else if (c == DATA_ESCAPE) r << "[ESCAPE]";
  471     else r << s[i];
  472   }
  473   return r;
  474 }