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