"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 }