modified: myjupyterlab.sh
[GalaxyCodeBases.git] / etc / Windows / vlmcsd_old_vancepym / network.c
blob69cdcbec7a71d9721d40caf1801957b12118543f
1 #ifndef CONFIG
2 #define CONFIG "config.h"
3 #endif // CONFIG
4 #include CONFIG
6 #ifndef USE_MSRPC
8 #ifndef _GNU_SOURCE
9 #define _GNU_SOURCE
10 #endif
12 #include <string.h>
13 #ifndef _WIN32
14 #include <signal.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <netinet/in.h>
19 #endif // WIN32
21 #include "network.h"
22 #include "endian.h"
23 #include "output.h"
24 #include "helpers.h"
25 #include "shared_globals.h"
26 #include "rpc.h"
29 #ifndef _WIN32
30 typedef ssize_t (*sendrecv_t)(int, void*, size_t, int);
31 #else
32 typedef int (WINAPI *sendrecv_t)(SOCKET, void*, int, int);
33 #endif
36 // Send or receive a fixed number of bytes regardless if received in one or more chunks
37 int_fast8_t sendrecv(SOCKET sock, BYTE *data, int len, int_fast8_t do_send)
39 int n;
40 sendrecv_t f = do_send
41 ? (sendrecv_t) send
42 : (sendrecv_t) recv;
46 n = f(sock, data, len, 0);
48 while (
49 ( n < 0 && socket_errno == VLMCSD_EINTR ) || ( n > 0 && ( data += n, (len -= n) > 0 ) ));
51 return ! len;
55 static int_fast8_t ip2str(char *restrict result, const size_t resultLength, const struct sockaddr *const restrict socketAddress, const socklen_t socketLength)
57 static const char *const fIPv4 = "%s:%s";
58 static const char *const fIPv6 = "[%s]:%s";
59 char ipAddress[64], portNumber[8];
61 if (getnameinfo
63 socketAddress,
64 socketLength,
65 ipAddress,
66 sizeof(ipAddress),
67 portNumber,
68 sizeof(portNumber),
69 NI_NUMERICHOST | NI_NUMERICSERV
72 return FALSE;
75 if ((unsigned int)snprintf(result, resultLength, socketAddress->sa_family == AF_INET6 ? fIPv6 : fIPv4, ipAddress, portNumber) > resultLength) return FALSE;
76 return TRUE;
80 static int_fast8_t getSocketList(struct addrinfo **saList, const char *const addr, const int flags, const int AddressFamily)
82 int status;
83 char *szHost, *szPort;
84 size_t len = strlen(addr) + 1;
86 // Don't alloca too much
87 if (len > 264) return FALSE;
89 char *addrcopy = (char*)alloca(len);
90 memcpy(addrcopy, addr, len);
92 parseAddress(addrcopy, &szHost, &szPort);
94 struct addrinfo hints;
96 memset(&hints, 0, sizeof(struct addrinfo));
98 hints.ai_family = AddressFamily;
99 hints.ai_socktype = SOCK_STREAM;
100 hints.ai_protocol = IPPROTO_TCP;
101 hints.ai_flags = flags;
103 if ((status = getaddrinfo(szHost, szPort, &hints, saList)))
105 printerrorf("Warning: %s: %s\n", addr, gai_strerror(status));
106 return FALSE;
109 return TRUE;
113 static int_fast8_t setBlockingEnabled(SOCKET fd, int_fast8_t blocking)
115 if (fd == INVALID_SOCKET) return FALSE;
117 #ifdef _WIN32
119 unsigned long mode = blocking ? 0 : 1;
120 return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? TRUE : FALSE;
122 #else // POSIX
124 int flags = fcntl(fd, F_GETFL, 0);
126 if (flags < 0) return FALSE;
128 flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
129 return (fcntl(fd, F_SETFL, flags) == 0) ? TRUE : FALSE;
131 #endif // POSIX
135 int_fast8_t isDisconnected(const SOCKET s)
137 char buffer[1];
139 if (!setBlockingEnabled(s, FALSE)) return TRUE;
141 int n = recv(s, buffer, 1, MSG_PEEK);
143 if (!setBlockingEnabled(s, TRUE)) return TRUE;
144 if (n == 0) return TRUE;
146 return FALSE;
150 // Connect to TCP address addr (e.g. "kms.example.com:1688") and return an
151 // open socket for the connection if successful or INVALID_SOCKET otherwise
152 SOCKET connectToAddress(const char *const addr, const int AddressFamily, int_fast8_t showHostName)
154 struct addrinfo *saList, *sa;
155 SOCKET s = INVALID_SOCKET;
156 char szAddr[128];
158 if (!getSocketList(&saList, addr, 0, AddressFamily)) return INVALID_SOCKET;
160 for (sa = saList; sa; sa = sa->ai_next)
162 // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
163 // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
165 if (ip2str(szAddr, sizeof(szAddr), sa->ai_addr, sa->ai_addrlen))
167 if (showHostName)
168 printf("Connecting to %s (%s) ... ", addr, szAddr);
169 else
170 printf("Connecting to %s ... ", szAddr);
172 fflush(stdout);
175 s = socket(sa->ai_family, SOCK_STREAM, IPPROTO_TCP);
177 # if !defined(NO_TIMEOUT) && !__minix__
178 # ifndef _WIN32 // Standard Posix timeout structure
180 struct timeval to;
181 to.tv_sec = 10;
182 to.tv_usec = 0;
184 # else // Windows requires a DWORD with milliseconds
186 DWORD to = 10000;
188 # endif // _WIN32
190 setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
191 setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
192 # endif // !defined(NO_TIMEOUT) && !__minix__
194 if (!connect(s, sa->ai_addr, sa->ai_addrlen))
196 printf("successful\n");
197 break;
200 errorout("%s\n", socket_errno == VLMCSD_EINPROGRESS ? "Timed out" : vlmcsd_strerror(socket_errno));
202 socketclose(s);
203 s = INVALID_SOCKET;
206 freeaddrinfo(saList);
207 return s;
211 #ifndef NO_SOCKETS
213 // Create a Listening socket for addrinfo sa and return socket s
214 // szHost and szPort are for logging only
215 static int listenOnAddress(const struct addrinfo *const ai, SOCKET *s)
217 int error;
218 char ipstr[64];
220 ip2str(ipstr, sizeof(ipstr), ai->ai_addr, ai->ai_addrlen);
222 //*s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
223 *s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
225 if (*s == INVALID_SOCKET)
227 error = socket_errno;
228 printerrorf("Warning: %s error. %s\n", ai->ai_family == AF_INET6 ? cIPv6 : cIPv4, vlmcsd_strerror(error));
229 return error;
232 # if !defined(_WIN32) && !defined(NO_SIGHUP)
234 int flags = fcntl(*s, F_GETFD, 0);
236 if (flags != -1)
238 flags |= FD_CLOEXEC;
239 fcntl(*s, F_SETFD, flags);
241 # ifdef _PEDANTIC
242 else
244 printerrorf("Warning: Could not set FD_CLOEXEC flag on %s: %s\n", ipstr, vlmcsd_strerror(errno));
246 # endif // _PEDANTIC
248 # endif // !defined(_WIN32) && !defined(NO_SIGHUP)
250 BOOL socketOption = TRUE;
252 // fix for lame tomato toolchain
253 # ifndef IPV6_V6ONLY
254 # ifdef __linux__
255 # define IPV6_V6ONLY (26)
256 # endif // __linux__
257 # endif // IPV6_V6ONLY
259 # ifdef IPV6_V6ONLY
260 if (ai->ai_family == AF_INET6) setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&socketOption, sizeof(socketOption));
261 # endif
263 # ifndef _WIN32
264 setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption));
265 # endif
267 if (bind(*s, ai->ai_addr, ai->ai_addrlen) || listen(*s, SOMAXCONN))
269 error = socket_errno;
270 printerrorf("Warning: %s: %s\n", ipstr, vlmcsd_strerror(error));
271 socketclose(*s);
272 return error;
275 # ifndef NO_LOG
276 logger("Listening on %s\n", ipstr);
277 # endif
279 return 0;
283 // Adds a listening socket for an address string,
284 // e.g. 127.0.0.1:1688 or [2001:db8:dead:beef::1]:1688
285 BOOL addListeningSocket(const char *const addr)
287 struct addrinfo *aiList, *ai;
288 int result = FALSE;
289 SOCKET *s = SocketList + numsockets;
291 if (getSocketList(&aiList, addr, AI_PASSIVE | AI_NUMERICHOST, AF_UNSPEC))
293 for (ai = aiList; ai; ai = ai->ai_next)
295 // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
296 // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
298 if (numsockets >= FD_SETSIZE)
300 #ifdef _PEDANTIC // Do not report this error in normal builds to keep file size low
301 printerrorf("Warning: Cannot listen on %s. Your OS only supports %u listening sockets in an FD_SET.\n", addr, FD_SETSIZE);
302 #endif
303 break;
306 if (!listenOnAddress(ai, s))
308 numsockets++;
309 result = TRUE;
313 freeaddrinfo(aiList);
315 return result;
319 // Just create some dummy sockets to see if we have a specific protocol (IPv4 or IPv6)
320 __pure int_fast8_t checkProtocolStack(const int addressfamily)
322 SOCKET s; // = INVALID_SOCKET;
324 s = socket(addressfamily, SOCK_STREAM, 0);
325 int_fast8_t success = (s != INVALID_SOCKET);
327 socketclose(s);
328 return success;
332 // Build an fd_set of all listening socket then use select to wait for an incoming connection
333 static SOCKET network_accept_any()
335 fd_set ListeningSocketsList;
336 SOCKET maxSocket, sock;
337 int i;
338 int status;
340 FD_ZERO(&ListeningSocketsList);
341 maxSocket = 0;
343 for (i = 0; i < numsockets; i++)
345 FD_SET(SocketList[i], &ListeningSocketsList);
346 if (SocketList[i] > maxSocket) maxSocket = SocketList[i];
349 status = select(maxSocket + 1, &ListeningSocketsList, NULL, NULL, NULL);
351 if (status < 0) return INVALID_SOCKET;
353 sock = INVALID_SOCKET;
355 for (i = 0; i < numsockets; i++)
357 if (FD_ISSET(SocketList[i], &ListeningSocketsList))
359 sock = SocketList[i];
360 break;
364 if (sock == INVALID_SOCKET)
365 return INVALID_SOCKET;
366 else
367 return accept(sock, NULL, NULL);
371 void closeAllListeningSockets()
373 int i;
375 for (i = 0; i < numsockets; i++)
377 shutdown(SocketList[i], VLMCSD_SHUT_RDWR);
378 socketclose(SocketList[i]);
381 #endif // NO_SOCKETS
384 static void serveClient(const SOCKET s_client, const DWORD RpcAssocGroup)
386 # if !defined(NO_TIMEOUT) && !__minix__
388 # ifndef _WIN32 // Standard Posix timeout structure
390 struct timeval to;
391 to.tv_sec = ServerTimeout;
392 to.tv_usec = 0;
394 #else // Windows requires a DWORD with milliseconds
396 DWORD to = ServerTimeout * 1000;
398 # endif // _WIN32
400 # if !defined(NO_LOG) && defined(_PEDANTIC)
402 int result =
403 setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to)) ||
404 setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
406 if (result) logger("Warning: Set timeout failed: %s\n", vlmcsd_strerror(socket_errno));
408 # else // !(!defined(NO_LOG) && defined(_PEDANTIC))
410 setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
411 setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
413 # endif // !(!defined(NO_LOG) && defined(_PEDANTIC))
415 # endif // !defined(NO_TIMEOUT) && !__minix__
417 char ipstr[64];
418 socklen_t len;
419 struct sockaddr_storage addr;
421 len = sizeof addr;
423 if (getpeername(s_client, (struct sockaddr*)&addr, &len) ||
424 !ip2str(ipstr, sizeof(ipstr), (struct sockaddr*)&addr, len))
426 # if !defined(NO_LOG) && defined(_PEDANTIC)
427 logger("Fatal: Cannot determine client's IP address: %s\n", vlmcsd_strerror(errno));
428 # endif // !defined(NO_LOG) && defined(_PEDANTIC)
429 socketclose(s_client);
430 return;
434 # ifndef NO_LOG
435 const char *const connection_type = addr.ss_family == AF_INET6 ? cIPv6 : cIPv4;
436 static const char *const cAccepted = "accepted";
437 static const char *const cClosed = "closed";
438 static const char *const fIP = "%s connection %s: %s.\n";
440 logger(fIP, connection_type, cAccepted, ipstr);
441 #endif // NO_LOG
443 rpcServer(s_client, RpcAssocGroup, ipstr);
445 # ifndef NO_LOG
446 logger(fIP, connection_type, cClosed, ipstr);
447 # endif // NO_LOG
449 socketclose(s_client);
453 #ifndef NO_SOCKETS
454 static void post_sem(void)
456 #if !defined(NO_LIMIT) && !__minix__
457 if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
459 semaphore_post(Semaphore);
461 #endif // !defined(NO_LIMIT) && !__minix__
465 static void wait_sem(void)
467 #if !defined(NO_LIMIT) && !__minix__
468 if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
470 semaphore_wait(Semaphore);
472 #endif // !defined(NO_LIMIT) && !__minix__
474 #endif // NO_SOCKETS
476 #if defined(USE_THREADS) && !defined(NO_SOCKETS)
478 #if defined(_WIN32) || defined(__CYGWIN__) // Win32 Threads
479 static DWORD WINAPI serveClientThreadProc(PCLDATA clData)
480 #else // Posix threads
481 static void *serveClientThreadProc (PCLDATA clData)
482 #endif // Thread proc is identical in WIN32 and Posix threads
484 serveClient(clData->socket, clData->RpcAssocGroup);
485 free(clData);
486 post_sem();
488 return 0;
491 #endif // USE_THREADS
494 #ifndef NO_SOCKETS
496 #if defined(USE_THREADS) && (defined(_WIN32) || defined(__CYGWIN__)) // Windows Threads
497 static int serveClientAsyncWinThreads(const PCLDATA thr_CLData)
499 wait_sem();
501 HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)serveClientThreadProc, thr_CLData, 0, NULL);
503 if (h)
504 CloseHandle(h);
505 else
507 socketclose(thr_CLData->socket);
508 free(thr_CLData);
509 post_sem();
510 return GetLastError();
513 return NO_ERROR;
515 #endif // defined(USE_THREADS) && defined(_WIN32) // Windows Threads
518 #if defined(USE_THREADS) && !defined(_WIN32) && !defined(__CYGWIN__) // Posix Threads
519 static int ServeClientAsyncPosixThreads(const PCLDATA thr_CLData)
521 pthread_t p_thr;
522 pthread_attr_t attr;
524 wait_sem();
526 // Must set detached state to avoid memory leak
527 if (pthread_attr_init(&attr) ||
528 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ||
529 pthread_create(&p_thr, &attr, (void * (*)(void *))serveClientThreadProc, thr_CLData))
531 socketclose(thr_CLData->socket);
532 free(thr_CLData);
533 post_sem();
534 return !0;
537 return 0;
539 #endif // defined(USE_THREADS) && !defined(_WIN32) // Posix Threads
541 #ifndef USE_THREADS // fork() implementation
542 static void ChildSignalHandler(const int signal)
544 if (signal == SIGHUP) return;
546 post_sem();
548 #ifndef NO_LOG
549 logger("Warning: Child killed/crashed by %s\n", strsignal(signal));
550 #endif // NO_LOG
552 exit(!0);
555 static int ServeClientAsyncFork(const SOCKET s_client, const DWORD RpcAssocGroup)
557 int pid;
558 wait_sem();
560 if ((pid = fork()) < 0)
562 return errno;
564 else if ( pid )
566 // Parent process
567 socketclose(s_client);
568 return 0;
570 else
572 // Child process
574 // Setup a Child Handler for most common termination signals
575 struct sigaction sa;
577 sa.sa_flags = 0;
578 sa.sa_handler = ChildSignalHandler;
580 static int signallist[] = { SIGHUP, SIGINT, SIGTERM, SIGSEGV, SIGILL, SIGFPE, SIGBUS };
582 if (!sigemptyset(&sa.sa_mask))
584 uint_fast8_t i;
586 for (i = 0; i < _countof(signallist); i++)
588 sigaction(signallist[i], &sa, NULL);
592 serveClient(s_client, RpcAssocGroup);
593 post_sem();
594 exit(0);
597 #endif
600 int serveClientAsync(const SOCKET s_client, const DWORD RpcAssocGroup)
602 #ifndef USE_THREADS // fork() implementation
604 return ServeClientAsyncFork(s_client, RpcAssocGroup);
606 #else // threads implementation
608 PCLDATA thr_CLData = (PCLDATA)vlmcsd_malloc(sizeof(CLDATA));
609 thr_CLData->socket = s_client;
610 thr_CLData->RpcAssocGroup = RpcAssocGroup;
612 #if defined(_WIN32) || defined (__CYGWIN__) // Windows threads
614 return serveClientAsyncWinThreads(thr_CLData);
616 #else // Posix Threads
618 return ServeClientAsyncPosixThreads(thr_CLData);
620 #endif // Posix Threads
622 #endif // USE_THREADS
625 #endif // NO_SOCKETS
628 int runServer()
630 DWORD RpcAssocGroup = rand32();
632 // If compiled for inetd-only mode just serve the stdin socket
633 #ifdef NO_SOCKETS
634 serveClient(STDIN_FILENO, RpcAssocGroup);
635 return 0;
636 #else
637 // In inetd mode just handle the stdin socket
638 if (InetdMode)
640 serveClient(STDIN_FILENO, RpcAssocGroup);
641 return 0;
644 // Standalone mode
645 for (;;)
647 int error;
648 SOCKET s_client;
650 if ( (s_client = network_accept_any()) == INVALID_SOCKET )
652 error = socket_errno;
654 if (error == VLMCSD_EINTR || error == VLMCSD_ECONNABORTED) continue;
656 #ifdef _NTSERVICE
657 if (ServiceShutdown) return 0;
658 #endif
660 #ifndef NO_LOG
661 logger("Fatal: %s\n",vlmcsd_strerror(error));
662 #endif
664 return error;
667 RpcAssocGroup++;
668 serveClientAsync(s_client, RpcAssocGroup);
670 #endif // NO_SOCKETS
672 return 0;
675 #endif // USE_MSRPC