"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. For more information about "QTMSockets.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.1_vs_2.1.2.

    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 }