1 /********************************************************************/
2 /*                                                                  */
3 /*  soc_rtl.c     Primitive actions for the socket type.            */
4 /*  Copyright (C) 1989 - 2015, 2018 - 2021  Thomas Mertes           */
5 /*                                                                  */
6 /*  This file is part of the Seed7 Runtime Library.                 */
7 /*                                                                  */
8 /*  The Seed7 Runtime Library is free software; you can             */
9 /*  redistribute it and/or modify it under the terms of the GNU     */
10 /*  Lesser General Public License as published by the Free Software */
11 /*  Foundation; either version 2.1 of the License, or (at your      */
12 /*  option) any later version.                                      */
13 /*                                                                  */
14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
18 /*  details.                                                        */
19 /*                                                                  */
20 /*  You should have received a copy of the GNU Lesser General       */
21 /*  Public License along with this program; if not, write to the    */
22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
24 /*                                                                  */
25 /*  Module: Seed7 Runtime Library                                   */
26 /*  File: seed7/src/soc_rtl.c                                       */
27 /*  Changes: 2007, 2011, 2013 - 2015, 2018 - 2020  Thomas Mertes    */
28 /*  Content: Primitive actions for the socket type.                 */
29 /*                                                                  */
30 /********************************************************************/
31 
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34 
35 #include "version.h"
36 
37 #if SOCKET_LIB == UNIX_SOCKETS || SOCKET_LIB == WINSOCK_SOCKETS
38 #include "stdlib.h"
39 #include "stdio.h"
40 #include "string.h"
41 #include "limits.h"
42 
43 #if SOCKET_LIB == UNIX_SOCKETS
44 
45 #include "sys/types.h"
46 #include "sys/socket.h"
47 #include "netdb.h"
48 #include "netinet/in.h"
49 #if HAS_SELECT
50 #include "sys/select.h"
51 #endif
52 #if HAS_POLL
53 #include "poll.h"
54 #endif
55 
56 #elif SOCKET_LIB == WINSOCK_SOCKETS
57 
58 #define FD_SETSIZE 16384
59 #include "winsock2.h"
60 #if HAS_GETADDRINFO
61 #include "ws2tcpip.h"
62 #endif
63 
64 #endif
65 
66 #include "errno.h"
67 
68 #if UNISTD_H_PRESENT
69 #include "unistd.h"
70 #endif
71 
72 #include "common.h"
73 #include "data_rtl.h"
74 #include "heaputl.h"
75 #include "striutl.h"
76 #include "os_decls.h"
77 #include "int_rtl.h"
78 #include "rtl_err.h"
79 
80 #undef EXTERN
81 #define EXTERN
82 #include "soc_rtl.h"
83 
84 
85 #if SOCKET_LIB == UNIX_SOCKETS
86 
87 typedef socklen_t sockLenType;
88 #define check_initialization(err_result)
89 #define cast_send_recv_data(data_ptr) ((void *) (data_ptr))
90 #define cast_buffer_len(len)          len
91 #define SOCKLEN_NEGATIVE(len) 0
92 #define INVALID_SOCKET (-1)
93 
94 #elif SOCKET_LIB == WINSOCK_SOCKETS
95 
96 typedef int sockLenType;
97 static boolType initialized = FALSE;
98 #define check_initialization(err_result) \
99     if (unlikely(!initialized)) {if (init_winsock()) {return err_result;}}
100 #define cast_send_recv_data(data_ptr) ((char *) (data_ptr))
101 #define cast_buffer_len(len)          ((int) (len))
102 #define SOCKLEN_NEGATIVE(len) (len) < 0
103 #ifndef SHUT_RDWR
104 #define SHUT_RDWR SD_BOTH
105 #endif
106 
107 #endif
108 
109 #define BUFFER_SIZE                4096
110 #define GETS_DEFAULT_SIZE       1048576
111 #define READ_STRI_INIT_SIZE         256
112 #define READ_STRI_SIZE_DELTA       2048
113 #define MAX_ADDRESS_SIZE           1024
114 #define MAX_HOSTNAME_LENGTH        1024
115 #define ERROR_MESSAGE_BUFFER_SIZE  1024
116 
117 #define MAX_SOCK_ADDRESS_LEN \
118     STRLEN("[01:23:45:67:89:ab:cd:ef]:65535") + NULL_TERMINATION_LEN
119 
120 
121 
122 #if ANY_LOG_ACTIVE
socAddressCStri(const const_bstriType address)123 static const_cstriType socAddressCStri (const const_bstriType address)
124 
125   {
126     const struct sockaddr *addr;
127     static char buffer[MAX_SOCK_ADDRESS_LEN];
128     cstriType result;
129 
130   /* socAddressCStri */
131     if (unlikely(address == NULL)) {
132       result = " *NULL_ADDRESS* ";
133     } else if (unlikely(address->size == 0)) {
134       result = " *EMPTY_ADDRESS* ";
135     } else if (unlikely(address->size < sizeof(struct sockaddr))) {
136       result = " ** Size of address too small ** ";
137     } else {
138       addr = (const struct sockaddr *) address->mem;
139       switch (addr->sa_family) {
140         case AF_INET:
141           if (unlikely(address->size != sizeof(struct sockaddr_in))) {
142             result = " ** Size of address wrong for AF_INET ** ";
143           } else {
144             const struct sockaddr_in *inet_address = (const struct sockaddr_in *) address->mem;
145             uint32Type ip4_address = ntohl(inet_address->sin_addr.s_addr);
146             int port;
147             port = ntohs(inet_address->sin_port);       /* short, network byte order */
148 
149             sprintf(buffer, "%d.%d.%d.%d:%d",
150                 (ip4_address >> 24) & 255,
151                 (ip4_address >> 16) & 255,
152                 (ip4_address >>  8) & 255,
153                  ip4_address        & 255, port);
154             result = buffer;
155           } /* if */
156           break;
157 #if HAS_GETADDRINFO || defined INET6_SERVER_ADDRESS
158         case AF_INET6:
159           if (unlikely(address->size != sizeof(struct sockaddr_in6))) {
160             result = " ** Size of address wrong for AF_INET6 ** ";
161           } else {
162             const struct sockaddr_in6 *inet6_address =
163                 (const struct sockaddr_in6 *) address->mem;
164             unsigned int digitGroup[8];
165             int pos;
166             int port;
167 
168             for (pos = 0; pos <= 7; pos++) {
169               digitGroup[pos] =
170                   (unsigned int) (inet6_address->sin6_addr.s6_addr[pos << 1]) << 8 |
171                   (unsigned int) (inet6_address->sin6_addr.s6_addr[(pos << 1) + 1]);
172             } /* for */
173             port = ntohs(inet6_address->sin6_port);     /* short, network byte order */
174 
175             sprintf(buffer, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
176                 digitGroup[0], digitGroup[1], digitGroup[2], digitGroup[3],
177                 digitGroup[4], digitGroup[5], digitGroup[6], digitGroup[7], port);
178             result = buffer;
179           } /* if */
180           break;
181 #endif
182         default:
183           result = " ** Address neither AF_INET nor AF_INET6 ** ";
184           break;
185       } /* switch */
186     } /* if */
187     return result;
188   } /* socAddressCStri */
189 #endif
190 
191 
192 
193 #if SOCKET_LIB == WINSOCK_SOCKETS
init_winsock(void)194 static int init_winsock (void)
195 
196   {
197     WORD wVersionRequested;
198     WSADATA wsaData;
199     int err;
200     int result;
201 
202   /* init_winsock */
203     wVersionRequested = MAKEWORD(2, 2);
204     err = WSAStartup(wVersionRequested, &wsaData);
205     if (err != 0) {
206       logError(printf("init_winsock: WSAStartup() failed:\n"
207                       "%s=%d\nerror: %s\n",
208                       ERROR_INFORMATION););
209       raise_error(FILE_ERROR);
210       result = -1;
211     } else {
212       if (LOBYTE(wsaData.wVersion) != 2 ||
213           HIBYTE(wsaData.wVersion) != 2) {
214         WSACleanup();
215         logError(printf("init_winsock: WSAStartup() "
216                         "did not return the requested version:\n"););
217         raise_error(FILE_ERROR);
218         result = -1;
219       } else {
220         initialized = TRUE;
221         result = 0;
222       } /* if */
223     } /* if */
224     return result;
225   } /* init_winsock */
226 
227 
228 
wsaErrorMessage(void)229 const_cstriType wsaErrorMessage (void)
230 
231   {
232     static char buffer[ERROR_MESSAGE_BUFFER_SIZE];
233     const_cstriType errorMessage = buffer;
234 
235   /* wsaErrorMessage */
236     if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
237                        NULL, WSAGetLastError(),
238                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
239                        buffer, ERROR_MESSAGE_BUFFER_SIZE, NULL) == 0) {
240       errorMessage = "Unable to get error message.";
241     } /* if */
242     return errorMessage;
243   } /* wsaErrorMessage */
244 #endif
245 
246 
247 
248 #if HAS_GETADDRINFO
select_addrinfo(struct addrinfo * addrinfo_list,int addr_family1,int addr_family2)249 static struct addrinfo *select_addrinfo (struct addrinfo *addrinfo_list,
250     int addr_family1, int addr_family2)
251 
252   {
253     struct addrinfo *current_addrinfo;
254     struct addrinfo *inet_addrinfo = NULL;
255     struct addrinfo *inet6_addrinfo = NULL;
256     struct addrinfo *alternate_inet_addrinfo = NULL;
257     struct addrinfo *result_addrinfo = NULL;
258 
259   /* select_addrinfo */
260     current_addrinfo = addrinfo_list;
261     while (current_addrinfo != NULL) {
262       if (current_addrinfo->ai_addr->sa_family == AF_INET) {
263         if (inet_addrinfo == NULL) {
264           struct sockaddr_in *inet_address = (struct sockaddr_in *) current_addrinfo->ai_addr;
265           uint32Type ip4_address = ntohl(inet_address->sin_addr.s_addr);
266           /* printf("ip4=%d.%d.%d.%d\n",
267               ip4_address >> 24, (ip4_address >> 16) & 255,
268               (ip4_address >> 8) & 255, ip4_address & 255); */
269           if ((ip4_address & (127 << 24)) == (127 << 24)) {
270             alternate_inet_addrinfo = current_addrinfo;
271           } else {
272             inet_addrinfo = current_addrinfo;
273           } /* if */
274         } /* if */
275       } else if (current_addrinfo->ai_addr->sa_family == AF_INET6) {
276         if (inet6_addrinfo == NULL) {
277           inet6_addrinfo = current_addrinfo;
278         } /* if */
279       } /* if */
280       current_addrinfo = current_addrinfo->ai_next;
281     } /* while */
282     if (inet_addrinfo == NULL) {
283       inet_addrinfo = alternate_inet_addrinfo;
284     } /* if */
285     if (addr_family1 == AF_INET && inet_addrinfo != NULL) {
286       result_addrinfo = inet_addrinfo;
287     } else if (addr_family1 == AF_INET6 && inet6_addrinfo != NULL) {
288       result_addrinfo = inet6_addrinfo;
289     } /* if */
290     if (result_addrinfo == NULL) {
291       if (addr_family2 == AF_INET && inet_addrinfo != NULL) {
292         result_addrinfo = inet_addrinfo;
293       } else if (addr_family2 == AF_INET6 && inet6_addrinfo != NULL) {
294         result_addrinfo = inet6_addrinfo;
295       } /* if */
296       if (result_addrinfo == NULL) {
297         /* No addr_family1 and addr_family2 present: Take first address */
298         result_addrinfo = addrinfo_list;
299       } /* if */
300     } /* if */
301     return result_addrinfo;
302   } /* select_addrinfo */
303 #endif
304 
305 
306 
307 #ifdef DUMP_ADDRINFO
dump_addrinfo(struct addrinfo * addrinfo_list)308 static void dump_addrinfo (struct addrinfo *addrinfo_list)
309 
310   {
311     struct addrinfo *addr;
312 
313   /* dump_addrinfo */
314     addr = addrinfo_list;
315     do {
316       printf("ai_flags=%d\n",    addr->ai_flags);
317       printf("ai_family=%d (%s)\n", addr->ai_family,
318           addr->ai_family == AF_INET ? "AF_INET" :
319           (addr->ai_family == AF_INET6 ? "AF_INET6" :
320           (addr->ai_family == AF_UNSPEC ? "AF_UNSPEC" : "UNKNOWN")));
321       printf("ai_socktype=%d\n", addr->ai_socktype);
322       printf("ai_protocol=%d\n", addr->ai_protocol);
323       printf("ai_addrlen=%d\n", addr->ai_addrlen);
324       printf("sa_family=%d (%s)\n", addr->ai_addr->sa_family,
325           addr->ai_addr->sa_family == AF_INET ? "AF_INET" :
326           (addr->ai_addr->sa_family == AF_INET6 ? "AF_INET6" :
327           (addr->ai_addr->sa_family == AF_UNSPEC ? "AF_UNSPEC" : "UNKNOWN")));
328       if (addr->ai_addr->sa_family == AF_INET) {
329         struct sockaddr_in *inet_address = (struct sockaddr_in *) addr->ai_addr;
330         uint32Type ip4_address = ntohl(inet_address->sin_addr.s_addr);
331         printf("sin_port=%d\n", ntohs(inet_address->sin_port));
332         printf("sin_addr.s_addr=%d.%d.%d.%d\n",
333             (ip4_address >> 24) & 255,
334             (ip4_address >> 16) & 255,
335             (ip4_address >>  8) & 255,
336              ip4_address        & 255);
337       } else if (addr->ai_addr->sa_family == AF_INET6) {
338         struct sockaddr_in6 *inet6_address = (struct sockaddr_in6 *) addr->ai_addr;
339         unsigned int digitGroup[8];
340         int pos;
341         printf("sin_port=%d\n", ntohs(inet6_address->sin6_port));
342         for (pos = 0; pos <= 7; pos++) {
343           digitGroup[pos] =
344               (unsigned int) inet6_address->sin6_addr.s6_addr[pos << 1] << 8 |
345               (unsigned int) inet6_address->sin6_addr.s6_addr[(pos << 1) + 1];
346         } /* for */
347         printf("sin_addr.s_addr=%x:%x:%x:%x:%x:%x:%x:%x\n",
348             digitGroup[0], digitGroup[1], digitGroup[2], digitGroup[3],
349             digitGroup[4], digitGroup[5], digitGroup[6], digitGroup[7]);
350       }
351       printf("ai_canonname=%s\n", addr->ai_canonname);
352       printf("ai_next=%lx\n", (memSizeType) addr->ai_next);
353       logMessage({
354                    char name[MAX_HOSTNAME_LENGTH];
355                    char serv[MAX_ADDRESS_SIZE];
356                    getnameinfo(addr->ai_addr, 100, name, MAX_HOSTNAME_LENGTH,
357                                serv, MAX_ADDRESS_SIZE, 0);
358                    printf("name=%s\n", name);
359                    printf("serv=%s\n", serv);
360                  });
361       addr = addr->ai_next;
362     } while (addr != NULL);
363   } /* dump_addrinfo */
364 #endif
365 
366 
367 
368 /**
369  *  Read a string, if we do not know how many bytes are available.
370  *  This function reads data into a list of buffers. This is done
371  *  until enough characters are read or EOF has been reached.
372  *  Afterwards the string is allocated, the data is copied from the
373  *  buffers and the list of buffers is freed.
374  */
receive_and_alloc_stri(socketType inSocket,memSizeType chars_missing,errInfoType * err_info)375 static striType receive_and_alloc_stri (socketType inSocket, memSizeType chars_missing,
376     errInfoType *err_info)
377 
378   {
379     struct bufferStruct buffer;
380     bufferList currBuffer = &buffer;
381     bufferList oldBuffer;
382     memSizeType bytes_in_buffer = LIST_BUFFER_SIZE;
383     boolType input_ready = TRUE;
384     memSizeType result_pos;
385     memSizeType result_size = 0;
386     striType result;
387 
388   /* receive_and_alloc_stri */
389     logFunction(printf("receive_and_alloc_stri(%d, " FMT_U_MEM ", *)\n",
390                        inSocket, chars_missing););
391     buffer.next = NULL;
392     while (chars_missing - result_size >= LIST_BUFFER_SIZE &&
393            bytes_in_buffer == LIST_BUFFER_SIZE &&
394            input_ready) {
395       bytes_in_buffer = (memSizeType) recv((os_socketType) inSocket,
396                                            cast_send_recv_data(currBuffer->buffer),
397                                            cast_buffer_len(LIST_BUFFER_SIZE), 0);
398       /* printf("receive_and_alloc_stri: bytes_in_buffer=" FMT_U_MEM "\n", bytes_in_buffer); */
399       if (unlikely(bytes_in_buffer == (memSizeType) -1 && result_size == 0)) {
400         logError(printf("receive_and_alloc_stri: "
401                         "recv(%d, *, " FMT_U_MEM ", 0) failed:\n"
402                         "%s=%d\nerror: %s\n",
403                         inSocket, (memSizeType) LIST_BUFFER_SIZE,
404                         ERROR_INFORMATION););
405         *err_info = FILE_ERROR;
406         result = NULL;
407       } else {
408         result_size += bytes_in_buffer;
409         if (chars_missing > result_size && bytes_in_buffer == LIST_BUFFER_SIZE) {
410           currBuffer->next = (bufferList) malloc(sizeof(struct bufferStruct));
411           if (unlikely(currBuffer->next == NULL)) {
412             logError(printf("receive_and_alloc_stri(%d, " FMT_U_MEM ", *): "
413                             "malloc(" FMT_U_MEM ") failed.\n",
414                             inSocket, chars_missing, sizeof(struct bufferStruct)););
415             *err_info = MEMORY_ERROR;
416             result = NULL;
417             /* Leave the while loop by setting bytes_in_buffer to zero. */
418             bytes_in_buffer = 0;
419           } else {
420             currBuffer = currBuffer->next;
421             currBuffer->next = NULL;
422             input_ready = socInputReady(inSocket, 0, 0);
423           } /* if */
424         } /* if */
425       } /* if */
426     } /* while */
427     if (chars_missing > result_size &&
428         bytes_in_buffer == LIST_BUFFER_SIZE &&
429         input_ready) {
430       bytes_in_buffer = (memSizeType) recv((os_socketType) inSocket,
431                                            cast_send_recv_data(currBuffer->buffer),
432                                            cast_buffer_len(chars_missing - result_size), 0);
433       /* printf("receive_and_alloc_stri: bytes_in_buffer=" FMT_U_MEM "\n", bytes_in_buffer); */
434       if (unlikely(bytes_in_buffer == (memSizeType) -1 && result_size == 0)) {
435         logError(printf("receive_and_alloc_stri: "
436                         "recv(%d, *, " FMT_U_MEM ", 0) failed:\n"
437                         "%s=%d\nerror: %s\n",
438                         inSocket, chars_missing - result_size,
439                         ERROR_INFORMATION););
440         *err_info = FILE_ERROR;
441         result = NULL;
442       } else {
443         result_size += bytes_in_buffer;
444       } /* if */
445     } /* if */
446     if (likely(*err_info == OKAY_NO_ERROR)) {
447       if (unlikely(!ALLOC_STRI_SIZE_OK(result, result_size))) {
448         logError(printf("receive_and_alloc_stri(%d, " FMT_U_MEM ", *): "
449                         "ALLOC_STRI_SIZE_OK(*, " FMT_U_MEM ") failed.\n",
450                         inSocket, chars_missing, result_size););
451         *err_info = MEMORY_ERROR;
452       } else {
453         result->size = result_size;
454         currBuffer = &buffer;
455         result_pos = 0;
456         while (result_size - result_pos >= LIST_BUFFER_SIZE) {
457           memcpy_to_strelem(&result->mem[result_pos], currBuffer->buffer, LIST_BUFFER_SIZE);
458           currBuffer = currBuffer->next;
459           result_pos += LIST_BUFFER_SIZE;
460         } /* while */
461         memcpy_to_strelem(&result->mem[result_pos], currBuffer->buffer,
462                           result_size - result_pos);
463       } /* if */
464     } /* if */
465     currBuffer = buffer.next;
466     while (currBuffer != NULL) {
467       oldBuffer = currBuffer;
468       currBuffer = currBuffer->next;
469       free(oldBuffer);
470     } /* while */
471     logFunction(printf("receive_and_alloc_stri(%d, " FMT_U_MEM ", %d) --> \"%s\"\n",
472                        inSocket, chars_missing, *err_info, striAsUnquotedCStri(result)););
473     return result;
474   } /* receive_and_alloc_stri */
475 
476 
477 
478 /**
479  *  Create a new accepted connection socket for 'listenerSocket'.
480  *  The function waits until at least one connection request is
481  *  in the sockets queue of pending connections. Then it extracts
482  *  the first connection request from the sockets queue. This
483  *  request is accepted and a connection socket is created for it.
484  *  @return the accepted connection socket.
485  *  @exception FILE_ERROR A system function returns an error.
486  *  @exception MEMORY_ERROR An out of memory situation occurred.
487  */
socAccept(socketType listenerSocket,bstriType * address)488 socketType socAccept (socketType listenerSocket, bstriType *address)
489 
490   {
491     memSizeType old_address_size;
492     bstriType resized_address;
493     sockLenType addrlen;
494     os_socketType result;
495 
496   /* socAccept */
497     logFunction(printf("socAccept(%d, \"%s\")\n",
498                        listenerSocket, socAddressCStri(*address)););
499     old_address_size = (*address)->size;
500     REALLOC_BSTRI_SIZE_OK(resized_address, *address, old_address_size, MAX_ADDRESS_SIZE);
501     if (unlikely(resized_address == NULL)) {
502       raise_error(MEMORY_ERROR);
503       result = (os_socketType) -1;
504     } else {
505       *address = resized_address;
506       COUNT3_BSTRI(old_address_size, MAX_ADDRESS_SIZE);
507       addrlen = MAX_ADDRESS_SIZE;
508       result = (os_socketType) accept((os_socketType) listenerSocket,
509                                       (struct sockaddr *) (*address)->mem, &addrlen);
510       if (unlikely(result == INVALID_SOCKET || addrlen < 0 || addrlen > MAX_ADDRESS_SIZE)) {
511         /* printf("socAccept(%d) %s=%d %s\n", listenerSocket, ERROR_INFORMATION); */
512         REALLOC_BSTRI_SIZE_OK(resized_address, *address, MAX_ADDRESS_SIZE, old_address_size);
513         if (resized_address == NULL) {
514           (*address)->size = MAX_ADDRESS_SIZE;
515         } else {
516           *address = resized_address;
517           COUNT3_BSTRI(MAX_ADDRESS_SIZE, old_address_size);
518         } /* if */
519         logError(printf("socAccept: accept(%d, \"%s\") failed:\n"
520                         "%s=%d\nerror: %s\n",
521                         listenerSocket, socAddressCStri(*address),
522                         ERROR_INFORMATION););
523         raise_error(FILE_ERROR);
524       } else {
525         REALLOC_BSTRI_SIZE_OK(resized_address, *address, MAX_ADDRESS_SIZE,
526                               (memSizeType) addrlen);
527         if (unlikely(resized_address == NULL)) {
528           (*address)->size = MAX_ADDRESS_SIZE;
529           raise_error(MEMORY_ERROR);
530           result = (os_socketType) -1;
531         } else {
532           *address = resized_address;
533           COUNT3_BSTRI(MAX_ADDRESS_SIZE, (memSizeType) addrlen);
534           (*address)->size = (memSizeType) addrlen;
535         } /* if */
536       } /* if */
537     } /* if */
538     logFunction(printf("socAccept(%d, \"%s\") --> %d\n",
539                        listenerSocket, socAddressCStri(*address), result););
540     return (socketType) result;
541   } /* socAccept */
542 
543 
544 
socAddrFamily(const const_bstriType address)545 intType socAddrFamily (const const_bstriType address)
546 
547   {
548     const struct sockaddr *addr;
549     intType result;
550 
551   /* socAddrFamily */
552     logFunction(printf("socAddrFamily(\"%s\")\n", socAddressCStri(address)););
553     if (unlikely(address->size < sizeof(struct sockaddr))) {
554       logError(printf("socAddrFamily(\"%s\"): Size of address too small.\n",
555                       socAddressCStri(address)););
556       raise_error(RANGE_ERROR);
557       result = 0;
558     } else {
559       addr = (const struct sockaddr *) address->mem;
560       result = addr->sa_family;
561       /* printf("socAddrFamily --> %d\n", result); */
562     } /* if */
563     logFunction(printf("socAddrFamily(\"%s\") --> " FMT_D "\n",
564                        socAddressCStri(address), result););
565     return result;
566   } /* socAddrFamily */
567 
568 
569 
570 /**
571  *  Get the numeric (IP) address of the host at 'address'.
572  *  IPv4 addresses return the socketAddress in dot notation (e.g.:
573  *  "192.0.2.235") and IPv6 addresses return the socketAddress in
574  *  colon notation (e.g.: "fe80:0:0:0:202:b3ff:fe1e:8329").
575  *  @return the IP address of the specified host.
576  *  @exception RANGE_ERROR The address is neither AF_INET nor AF_INET6.
577  */
socAddrNumeric(const const_bstriType address)578 striType socAddrNumeric (const const_bstriType address)
579 
580   {
581     const struct sockaddr *addr;
582     char buffer[40];
583     striType result;
584 
585   /* socAddrNumeric */
586     logFunction(printf("socAddrNumeric(\"%s\")\n", socAddressCStri(address)););
587     if (unlikely(address->size < sizeof(struct sockaddr))) {
588       logError(printf("socAddrNumeric(\"%s\"): Size of address too small.\n",
589                       socAddressCStri(address)););
590       raise_error(RANGE_ERROR);
591       result = NULL;
592     } else {
593       addr = (const struct sockaddr *) address->mem;
594       switch (addr->sa_family) {
595         case AF_INET:
596           if (unlikely(address->size != sizeof(struct sockaddr_in))) {
597             logError(printf("socAddrNumeric(\"%s\"): Size of address wrong for AF_INET.\n",
598                             socAddressCStri(address)););
599             raise_error(RANGE_ERROR);
600             result = NULL;
601           } else {
602             const struct sockaddr_in *inet_address = (const struct sockaddr_in *) address->mem;
603             uint32Type ip4_address = ntohl(inet_address->sin_addr.s_addr);
604 
605             sprintf(buffer, "%d.%d.%d.%d",
606                 (ip4_address >> 24) & 255,
607                 (ip4_address >> 16) & 255,
608                 (ip4_address >>  8) & 255,
609                  ip4_address        & 255);
610             result = cstri_to_stri(buffer);
611           } /* if */
612           break;
613 #if HAS_GETADDRINFO || defined INET6_SERVER_ADDRESS
614         case AF_INET6:
615           if (unlikely(address->size != sizeof(struct sockaddr_in6))) {
616             logError(printf("socAddrNumeric(\"%s\"): Size of address wrong for AF_INET6.\n",
617                             socAddressCStri(address)););
618             raise_error(RANGE_ERROR);
619             result = NULL;
620           } else {
621             const struct sockaddr_in6 *inet6_address =
622                 (const struct sockaddr_in6 *) address->mem;
623             unsigned int digitGroup[8];
624             int pos;
625 
626             for (pos = 0; pos <= 7; pos++) {
627               digitGroup[pos] =
628                   (unsigned int) (inet6_address->sin6_addr.s6_addr[pos << 1]) << 8 |
629                   (unsigned int) (inet6_address->sin6_addr.s6_addr[(pos << 1) + 1]);
630             } /* for */
631             sprintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x",
632                 digitGroup[0], digitGroup[1], digitGroup[2], digitGroup[3],
633                 digitGroup[4], digitGroup[5], digitGroup[6], digitGroup[7]);
634             result = cstri_to_stri(buffer);
635           } /* if */
636           break;
637 #endif
638         default:
639           logError(printf("socAddrNumeric(\"%s\"): Address neither AF_INET nor AF_INET6.\n",
640                           socAddressCStri(address)););
641           raise_error(RANGE_ERROR);
642           result = NULL;
643           break;
644       } /* switch */
645     } /* if */
646     logFunction(printf("socAddrNumeric(\"%s\") --> \"%s\"\n",
647                        socAddressCStri(address), striAsUnquotedCStri(result)););
648     return result;
649   } /* socAddrNumeric */
650 
651 
652 
socAddrService(const const_bstriType address)653 striType socAddrService (const const_bstriType address)
654 
655   {
656     const struct sockaddr *addr;
657     striType result;
658 
659   /* socAddrService */
660     logFunction(printf("socAddrService(\"%s\")\n", socAddressCStri(address)););
661     if (unlikely(address->size < sizeof(struct sockaddr))) {
662       logError(printf("socAddrService(\"%s\"): Size of address too small.\n",
663                       socAddressCStri(address)););
664       raise_error(RANGE_ERROR);
665       result = NULL;
666     } else {
667       addr = (const struct sockaddr *) address->mem;
668       switch (addr->sa_family) {
669         case AF_INET:
670           if (unlikely(address->size != sizeof(struct sockaddr_in))) {
671             logError(printf("socAddrService(\"%s\"): Size of address wrong for AF_INET.\n",
672                             socAddressCStri(address)););
673             raise_error(RANGE_ERROR);
674             result = NULL;
675           } else {
676             intType port;
677             const struct sockaddr_in *inet_address;
678             inet_address = (const struct sockaddr_in *) address->mem;
679             port = ntohs(inet_address->sin_port);       /* short, network byte order */
680             result = intStr(port);
681           } /* if */
682           break;
683 #if HAS_GETADDRINFO || defined INET6_SERVER_ADDRESS
684         case AF_INET6:
685           if (unlikely(address->size != sizeof(struct sockaddr_in6))) {
686             logError(printf("socAddrService(\"%s\"): Size of address wrong for AF_INET6.\n",
687                             socAddressCStri(address)););
688             raise_error(RANGE_ERROR);
689             result = NULL;
690           } else {
691             intType port;
692             const struct sockaddr_in6 *inet6_address;
693             inet6_address = (const struct sockaddr_in6 *) address->mem;
694             port = ntohs(inet6_address->sin6_port);     /* short, network byte order */
695             result = intStr(port);
696           } /* if */
697           break;
698 #endif
699         default:
700           logError(printf("socAddrService(\"%s\"): Address neither AF_INET nor AF_INET6.\n",
701                           socAddressCStri(address)););
702           raise_error(RANGE_ERROR);
703           result = NULL;
704           break;
705       } /* switch */
706     } /* if */
707     logFunction(printf("socAddrService(\"%s\") --> \"%s\"\n",
708                        socAddressCStri(address), striAsUnquotedCStri(result)););
709     return result;
710   } /* socAddrService */
711 
712 
713 
714 /**
715  *  Assign the specified 'address' to the 'listenerSocket'.
716  *  @param address An internet listener socket address.
717  *  @exception FILE_ERROR A system function returns an error.
718  */
socBind(socketType listenerSocket,const_bstriType address)719 void socBind (socketType listenerSocket, const_bstriType address)
720 
721   { /* socBind */
722     logFunction(printf("socBind(%d, \"%s\")\n",
723                        listenerSocket, socAddressCStri(address)););
724     if (unlikely(bind((os_socketType) listenerSocket,
725                       (const struct sockaddr *) address->mem,
726                       (sockLenType) address->size) != 0)) {
727       logError(printf("socBind: bind(%d, \"%s\") failed:\n"
728                       "%s=%d\nerror: %s\n",
729                       listenerSocket, socAddressCStri(address),
730                       ERROR_INFORMATION););
731       raise_error(FILE_ERROR);
732     } /* if */
733   } /* socBind */
734 
735 
736 /**
737  *  Close the socket 'aSocket'.
738  *  @exception FILE_ERROR A system function returns an error.
739  */
socClose(socketType aSocket)740 void socClose (socketType aSocket)
741 
742   {
743     int close_result;
744 
745   /* socClose */
746     logFunction(printf("socClose(%d)\n", aSocket););
747     shutdown((os_socketType) aSocket, SHUT_RDWR);
748 #if SOCKET_LIB == UNIX_SOCKETS
749     close_result = close((os_socketType) aSocket);
750 #elif SOCKET_LIB == WINSOCK_SOCKETS
751     close_result = closesocket((os_socketType) aSocket);
752 #endif
753     if (unlikely(close_result != 0)) {
754       logError(printf("socClose: close(%d) failed:\n"
755                       "%s=%d\nerror: %s\n",
756                       aSocket, ERROR_INFORMATION););
757       raise_error(FILE_ERROR);
758     } /* if */
759   } /* socClose */
760 
761 
762 
763 /**
764  *  Connect 'aSocket' to the given 'address'.
765  *  @exception FILE_ERROR A system function returns an error.
766  */
socConnect(socketType aSocket,const_bstriType address)767 void socConnect (socketType aSocket, const_bstriType address)
768 
769   { /* socConnect */
770     logFunction(printf("socConnect(%d, \"%s\")\n",
771                        aSocket, socAddressCStri(address)););
772     if (unlikely(connect((os_socketType) aSocket,
773                          (const struct sockaddr *) address->mem,
774                          (sockLenType) address->size) != 0)) {
775       logError(printf("socConnect: connect(%d, \"%s\") failed:\n"
776                       "%s=%d\nerror: %s\n",
777                       aSocket, socAddressCStri(address),
778                       ERROR_INFORMATION););
779       raise_error(FILE_ERROR);
780     } /* if */
781   } /* socConnect */
782 
783 
784 
785 /**
786  *  Read a character from 'inSocket'.
787  *  @return the character read.
788  */
socGetc(socketType inSocket,charType * const eofIndicator)789 charType socGetc (socketType inSocket, charType *const eofIndicator)
790 
791   {
792     unsigned char ch;
793     memSizeType bytes_received;
794     charType result;
795 
796   /* socGetc */
797     logFunction(printf("socGetc(%d, '\\" FMT_U32 ";')\n",
798                        inSocket, *eofIndicator););
799     bytes_received = (memSizeType) recv((os_socketType) inSocket,
800                                         cast_send_recv_data(&ch), 1, 0);
801     /* printf("socGetc: bytes_received=" FMT_U_MEM "\n", bytes_received); */
802     if (bytes_received != 1) {
803       if (unlikely(inSocket == (socketType) -1)) {
804         logError(printf("socGetc(%d, '\\" FMT_U32 ";'): Invalid socket.\n",
805                         inSocket, *eofIndicator););
806         raise_error(FILE_ERROR);
807         result = (charType) EOF;
808       } else {
809         *eofIndicator = (charType) EOF;
810         result = (charType) EOF;
811       } /* if */
812     } else {
813       result = (charType) ch;
814     } /* if */
815     logFunction(printf("socGetc (%d, '\\" FMT_U32 ";') --> '\\" FMT_U32 ";'\n",
816                        inSocket, *eofIndicator, result););
817     return result;
818   } /* socGetc */
819 
820 
821 
822 /**
823  *  Read a string with a maximum length from 'inSocket'.
824  *  @return the string read.
825  *  @exception RANGE_ERROR The length is negative.
826  *  @exception MEMORY_ERROR Not enough memory to represent the result.
827  */
socGets(socketType inSocket,intType length,charType * const eofIndicator)828 striType socGets (socketType inSocket, intType length, charType *const eofIndicator)
829 
830   {
831     memSizeType chars_requested;
832     memSizeType result_size;
833     errInfoType err_info = OKAY_NO_ERROR;
834     striType resized_result;
835     striType result;
836 
837   /* socGets */
838     logFunction(printf("socGets(%d, " FMT_D ", '\\" FMT_U32 ";')\n",
839                        inSocket, length, *eofIndicator););
840     if (unlikely(inSocket == (socketType) -1)) {
841         logError(printf("socGets(%d, " FMT_D ", '\\" FMT_U32 ";'): "
842                         "Invalid socket.\n",
843                         inSocket, length, *eofIndicator););
844       raise_error(FILE_ERROR);
845       result = NULL;
846     } else if (unlikely(length <= 0)) {
847       if (unlikely(length != 0)) {
848         logError(printf("socGets(%d, " FMT_D ", *): Negative length.\n",
849                         inSocket, length););
850         raise_error(RANGE_ERROR);
851         result = NULL;
852       } else {
853         if (unlikely(!ALLOC_STRI_SIZE_OK(result, 0))) {
854           raise_error(MEMORY_ERROR);
855         } else {
856           result->size = 0;
857         } /* if */
858       } /* if */
859     } else {
860       if ((uintType) length > MAX_MEMSIZETYPE) {
861         chars_requested = MAX_MEMSIZETYPE;
862       } else {
863         chars_requested = (memSizeType) length;
864       } /* if */
865       if (chars_requested <= BUFFER_SIZE) {
866         ucharType buffer[BUFFER_SIZE];
867 
868         result_size = (memSizeType) recv((os_socketType) inSocket,
869                                          cast_send_recv_data(buffer),
870                                          cast_buffer_len(chars_requested), 0);
871         /* printf("socGets: result_size=" FMT_U_MEM "\n", result_size); */
872         if (result_size == (memSizeType) -1) {
873           result_size = 0;
874         } /* if */
875         if (unlikely(!ALLOC_STRI_CHECK_SIZE(result, result_size))) {
876           logError(printf("socGets(%d, " FMT_D ", *): "
877                           "Out of memory when allocating result.\n",
878                           inSocket, length););
879           raise_error(MEMORY_ERROR);
880           result = NULL;
881         } else {
882           memcpy_to_strelem(result->mem, buffer, result_size);
883           result->size = result_size;
884           if (result_size == 0 && result_size < chars_requested) {
885             *eofIndicator = (charType) EOF;
886           } /* if */
887         } /* if */
888       } else {
889         if (chars_requested > GETS_DEFAULT_SIZE) {
890           /* Read a string, if we do not know how many bytes are available. */
891           result = receive_and_alloc_stri(inSocket, chars_requested, &err_info);
892           if (unlikely(err_info != OKAY_NO_ERROR)) {
893             raise_error(err_info);
894           } /* if */
895         } else {
896           if (unlikely(!ALLOC_STRI_CHECK_SIZE(result, chars_requested))) {
897             logError(printf("socGets(%d, " FMT_D ", *): "
898                             "Out of memory when allocating result.\n",
899                             inSocket, length););
900             raise_error(MEMORY_ERROR);
901             result = NULL;
902           } else {
903             result_size = (memSizeType) recv((os_socketType) inSocket,
904                                              cast_send_recv_data(result->mem),
905                                              cast_buffer_len(chars_requested), 0);
906             /* printf("socGets: result_size=" FMT_U_MEM "\n", result_size); */
907             if (result_size == (memSizeType) -1) {
908               result_size = 0;
909             } /* if */
910             memcpy_to_strelem(result->mem, (ustriType) result->mem, result_size);
911             result->size = result_size;
912             if (result_size < chars_requested) {
913               if (result_size == 0) {
914                 *eofIndicator = (charType) EOF;
915               } /* if */
916               REALLOC_STRI_SIZE_SMALLER(resized_result, result, chars_requested, result_size);
917               if (unlikely(resized_result == NULL)) {
918                 FREE_STRI(result, chars_requested);
919                 logError(printf("socGets(%d, " FMT_D ", *): "
920                                 "Out of memory when allocating result.\n",
921                                 inSocket, length););
922                 raise_error(MEMORY_ERROR);
923                 result = NULL;
924               } else {
925                 result = resized_result;
926                 COUNT3_STRI(chars_requested, result_size);
927               } /* if */
928             } /* if */
929           } /* if */
930         } /* if */
931       } /* if */
932     } /* if */
933     logFunction(printf("socGets(%d, " FMT_D ", '\\" FMT_U32 ";') --> \"%s\"\n",
934                        inSocket, length, *eofIndicator, striAsUnquotedCStri(result)););
935     return result;
936   } /* socGets */
937 
938 
939 
940 /**
941  *  Determine the hostname.
942  *  @return the hostname.
943  *  @exception MEMORY_ERROR Not enough memory to represent the result.
944  */
socGetHostname(void)945 striType socGetHostname (void)
946 
947   {
948     char name[MAX_HOSTNAME_LENGTH];
949     striType result;
950 
951   /* socGetHostname */
952     check_initialization(NULL);
953     if (unlikely(gethostname(name, MAX_HOSTNAME_LENGTH) != 0)) {
954       raise_error(MEMORY_ERROR);
955       result = NULL;
956     } else {
957       result = cstri8_or_cstri_to_stri(name);
958     } /* if */
959     return result;
960   } /* socGetHostname */
961 
962 
963 
964 /**
965  *  Get the local address of the socket 'sock'.
966  *  @return the address to which the socket 'sock' is bound.
967  *  @exception FILE_ERROR A system function returns an error.
968  *  @exception MEMORY_ERROR Not enough memory to represent the result.
969  */
socGetLocalAddr(socketType sock)970 bstriType socGetLocalAddr (socketType sock)
971 
972   {
973     sockLenType addrlen;
974     int getsockname_result;
975     bstriType resized_address;
976     bstriType address;
977 
978   /* socGetLocalAddr */
979     logFunction(printf("socGetLocalAddr(%d)\n", sock););
980     if (unlikely(!ALLOC_BSTRI_SIZE_OK(address, MAX_ADDRESS_SIZE))) {
981       raise_error(MEMORY_ERROR);
982     } else {
983       addrlen = MAX_ADDRESS_SIZE;
984       getsockname_result = getsockname((os_socketType) sock,
985                                        (struct sockaddr *) address->mem, &addrlen);
986       if (unlikely(getsockname_result != 0 || addrlen < 0 || addrlen > MAX_ADDRESS_SIZE)) {
987         FREE_BSTRI(address, MAX_ADDRESS_SIZE);
988         logError(printf("socGetLocalAddr: getsockname(%d, ...) failed:\n"
989                         "%s=%d\nerror: %s\n",
990                         sock, ERROR_INFORMATION););
991         raise_error(FILE_ERROR);
992         address = NULL;
993       } else {
994         REALLOC_BSTRI_SIZE_OK(resized_address, address, MAX_ADDRESS_SIZE,
995                               (memSizeType) addrlen);
996         if (unlikely(resized_address == NULL)) {
997           FREE_BSTRI(address, MAX_ADDRESS_SIZE);
998           raise_error(MEMORY_ERROR);
999           address = NULL;
1000         } else {
1001           address = resized_address;
1002           COUNT3_BSTRI(MAX_ADDRESS_SIZE, (memSizeType) addrlen);
1003           address->size = (memSizeType) addrlen;
1004         } /* if */
1005       } /* if */
1006     } /* if */
1007     logFunction(printf("socGetLocalAddr(%d) --> \"%s\"\n",
1008                        sock, socAddressCStri(address)););
1009     return address;
1010   } /* socGetLocalAddr */
1011 
1012 
1013 
1014 /**
1015  *  Get the address of the peer to which the socket 'sock' is connected.
1016  *  @return the address of the peer connected to the socket 'sock'.
1017  *  @exception FILE_ERROR A system function returns an error.
1018  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1019  */
socGetPeerAddr(socketType sock)1020 bstriType socGetPeerAddr (socketType sock)
1021 
1022   {
1023     sockLenType addrlen;
1024     int getpeername_result;
1025     bstriType resized_address;
1026     bstriType address;
1027 
1028   /* socGetPeerAddr */
1029     logFunction(printf("socGetPeerAddr(%d)\n", sock););
1030     if (unlikely(!ALLOC_BSTRI_SIZE_OK(address, MAX_ADDRESS_SIZE))) {
1031       raise_error(MEMORY_ERROR);
1032     } else {
1033       addrlen = MAX_ADDRESS_SIZE;
1034       getpeername_result = getpeername((os_socketType) sock,
1035                                        (struct sockaddr *) address->mem, &addrlen);
1036       if (unlikely(getpeername_result != 0 || addrlen < 0 || addrlen > MAX_ADDRESS_SIZE)) {
1037         FREE_BSTRI(address, MAX_ADDRESS_SIZE);
1038         logError(printf("socGetPeerAddr: getpeername(%d, ...) failed:\n"
1039                         "%s=%d\nerror: %s\n",
1040                         sock, ERROR_INFORMATION););
1041         raise_error(FILE_ERROR);
1042         address = NULL;
1043       } else {
1044         REALLOC_BSTRI_SIZE_OK(resized_address, address, MAX_ADDRESS_SIZE,
1045                               (memSizeType) addrlen);
1046         if (unlikely(resized_address == NULL)) {
1047           FREE_BSTRI(address, MAX_ADDRESS_SIZE);
1048           raise_error(MEMORY_ERROR);
1049           address = NULL;
1050         } else {
1051           address = resized_address;
1052           COUNT3_BSTRI(MAX_ADDRESS_SIZE, (memSizeType) addrlen);
1053           address->size = (memSizeType) addrlen;
1054         } /* if */
1055       } /* if */
1056     } /* if */
1057     logFunction(printf("socGetPeerAddr(%d) --> \"%s\"\n",
1058                        sock, socAddressCStri(address)););
1059     return address;
1060   } /* socGetPeerAddr */
1061 
1062 
1063 
1064 /**
1065  *  Determine if at least one character can be read successfully.
1066  *  This function allows a socket to be handled like an iterator.
1067  *  Since socHasNext peeks the next character from the socket
1068  *  it may block.
1069  *  @return FALSE if socGetc would return EOF, TRUE otherwise.
1070  */
socHasNext(socketType inSocket)1071 boolType socHasNext (socketType inSocket)
1072 
1073   {
1074     unsigned char next_char;
1075     memSizeType bytes_received;
1076     boolType hasNext;
1077 
1078   /* socHasNext */
1079     logFunction(printf("socHasNext(%d)\n", inSocket););
1080     bytes_received = (memSizeType) recv((os_socketType) inSocket,
1081                                         cast_send_recv_data(&next_char), 1, MSG_PEEK);
1082     if (bytes_received != 1) {
1083       /* printf("socHasNext: bytes_received=" FMT_U_MEM "\n", bytes_received); */
1084       if (unlikely(inSocket == (socketType) -1)) {
1085         logError(printf("socHasNext(%d): Invalid socket.\n", inSocket););
1086         raise_error(FILE_ERROR);
1087       } /* if */
1088       hasNext = FALSE;
1089     } else {
1090       /* printf("socHasNext: next_char=%d\n", next_char); */
1091       hasNext = TRUE;
1092     } /* if */
1093     logFunction(printf("socHasNext(%d) --> %d\n", inSocket, hasNext););
1094     return hasNext;
1095   } /* socHasNext */
1096 
1097 
1098 
1099 /**
1100  *  Create an internet socket address of a port at a host.
1101  *  The 'hostName' is either a host name (e.g.: "www.example.org"),
1102  *  or an IPv4 address in standard dot notation (e.g.: "192.0.2.235").
1103  *  Operating systems supporting IPv6 may also accept an IPv6 address
1104  *  in colon notation.
1105  *  @return the internet socket address, or
1106  *          an empty bstring if the host cannot be found.
1107  *  @exception FILE_ERROR A system function returns an error.
1108  *  @exception RANGE_ERROR The port is not in the range 0 to 65535 or
1109  *             hostName cannot be converted to the system string type.
1110  *  @exception MEMORY_ERROR Not enough memory to convert 'hostName'.
1111  *             to the system representation or not enough memory to
1112  *             represent the result.
1113  */
socInetAddr(const const_striType hostName,intType port)1114 bstriType socInetAddr (const const_striType hostName, intType port)
1115 
1116   {
1117     cstriType name;
1118 #if HAS_GETADDRINFO
1119     char servicename[10];
1120     struct addrinfo *addrinfo_list;
1121     struct addrinfo *result_addrinfo;
1122     struct addrinfo hints;
1123     int getaddrinfo_result;
1124 #else
1125     struct hostent *host_ent;
1126     struct sockaddr_in *inet_address;
1127 #endif
1128     errInfoType err_info = OKAY_NO_ERROR;
1129     bstriType result;
1130 
1131   /* socInetAddr */
1132     logFunction(printf("socInetAddr(\"%s\", " FMT_D ")\n",
1133                        striAsUnquotedCStri(hostName), port););
1134     check_initialization(NULL);
1135     if (unlikely(port < 0 || port > 65535)) {
1136       logError(printf("socInetAddr(\"%s\", " FMT_D "): "
1137                       "Port not in allowed range.\n",
1138                       striAsUnquotedCStri(hostName), port););
1139       raise_error(RANGE_ERROR);
1140       result = NULL;
1141     } else {
1142       name = stri_to_cstri8(hostName, &err_info);
1143       if (unlikely(name == NULL)) {
1144         logError(printf("socInetAddr: stri_to_cstri8(\"%s\", *) failed:\n"
1145                         "err_info=%d\n",
1146                         striAsUnquotedCStri(hostName), err_info););
1147         raise_error(err_info);
1148         result = NULL;
1149       } else {
1150 #if HAS_GETADDRINFO
1151         sprintf(servicename, "%u", (unsigned int) port);
1152         memset(&hints, 0, sizeof(struct addrinfo));
1153         hints.ai_family = AF_UNSPEC;
1154         hints.ai_socktype = SOCK_STREAM;
1155         getaddrinfo_result = getaddrinfo(name, servicename, &hints, &addrinfo_list);
1156         if (unlikely(getaddrinfo_result != 0)) {
1157           /* printf("getaddrinfo(\"%s\") -> %d\n", name, getaddrinfo_result); */
1158           if (getaddrinfo_result == EAI_NONAME || getaddrinfo_result == EAI_AGAIN
1159 #ifdef EAI_NODATA
1160               || getaddrinfo_result == EAI_NODATA
1161 #endif
1162           ) {
1163             free_cstri8(name, hostName);
1164             /* Return empty address */
1165             if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, 0))) {
1166               raise_error(MEMORY_ERROR);
1167             } else {
1168               result->size = 0;
1169             } /* if */
1170           } else {
1171             logError(printf("socInetAddr(\"%s\", " FMT_D "): "
1172                             "getaddrinfo(\"%s\", \"%s\", *, *) failed with %d:\n"
1173                             "strerror: %s\n"
1174                             "%s=%d\nerror: %s\n",
1175                             striAsUnquotedCStri(hostName), port,
1176                             name, servicename, getaddrinfo_result,
1177                             gai_strerror(getaddrinfo_result),
1178                             ERROR_INFORMATION););
1179             /*
1180             printf("EAI_AGAIN=%d  EAI_BADFLAGS=%d  EAI_FAIL=%d  EAI_FAMILY=%d\n",
1181                 EAI_AGAIN, EAI_BADFLAGS, EAI_FAIL, EAI_FAMILY);
1182             printf("EAI_MEMORY=%d  EAI_NONAME=%d  EAI_SERVICE=%d  EAI_SOCKTYPE=%d\n",
1183                 EAI_MEMORY, EAI_NONAME, EAI_SERVICE, EAI_SOCKTYPE);
1184             */
1185             /* printf("EAI_SYSTEM=%d  EAI_OVERFLOW=%d\n",
1186                 EAI_SYSTEM, EAI_OVERFLOW); */
1187             /* printf("EAI_ADDRFAMILY=%d  EAI_NODATA=%d\n",
1188                 EAI_ADDRFAMILY, EAI_NODATA); */
1189             free_cstri8(name, hostName);
1190             raise_error(FILE_ERROR);
1191             result = NULL;
1192           } /* if */
1193         } else {
1194           /* dump_addrinfo(addrinfo_list); */
1195           result_addrinfo = select_addrinfo(addrinfo_list, AF_INET, AF_INET6);
1196           if (unlikely(SOCKLEN_NEGATIVE(result_addrinfo->ai_addrlen) ||
1197                        !ALLOC_BSTRI_SIZE_OK(result,
1198                            (memSizeType) result_addrinfo->ai_addrlen))) {
1199             free_cstri8(name, hostName);
1200             freeaddrinfo(addrinfo_list);
1201             raise_error(MEMORY_ERROR);
1202           } else {
1203             result->size = (memSizeType) result_addrinfo->ai_addrlen;
1204             memcpy(result->mem, result_addrinfo->ai_addr,
1205                    (memSizeType) result_addrinfo->ai_addrlen);
1206             free_cstri8(name, hostName);
1207             freeaddrinfo(addrinfo_list);
1208           } /* if */
1209         } /* if */
1210 #else
1211         host_ent = gethostbyname(name);
1212         if (host_ent == NULL && h_errno == TRY_AGAIN) {
1213           /*
1214           printf("***** h_errno=%d\n", h_errno);
1215           printf("***** name=\"%s\"\n", name);
1216           printf("***** port=%d\n", port);
1217           printf("***** hostName=%s\n", striAsUnquotedCStri(hostName));
1218           */
1219           host_ent = gethostbyname(name);
1220         } /* if */
1221         if (unlikely(host_ent == NULL)) {
1222           /* printf("***** gethostbyname(\"%s\"): h_errno=%d\n", name, h_errno);
1223              printf("HOST_NOT_FOUND=%d  NO_DATA=%d  NO_RECOVERY=%d  TRY_AGAIN=%d\n",
1224                  HOST_NOT_FOUND, NO_DATA, NO_RECOVERY, TRY_AGAIN); */
1225           free_cstri8(name, hostName);
1226           /* Return empty address */
1227           if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, 0))) {
1228             raise_error(MEMORY_ERROR);
1229           } else {
1230             result->size = 0;
1231           } /* if */
1232         } else {
1233           /*
1234           printf("Host name:      %s\n", host_ent->h_name);
1235           printf("Port:           %d\n", port);
1236           printf("Address type:   %d\n", host_ent->h_addrtype);
1237           printf("Address type:   %d\n", AF_INET);
1238           printf("Address length: %d\n", host_ent->h_length);
1239           printf("Address length: %d\n", sizeof(struct sockaddr_in));
1240           printf("IP Address:     %s\n", inet_ntoa(*((struct in_addr *)host_ent->h_addr)));
1241           */
1242           free_cstri8(name, hostName);
1243           if (host_ent->h_addrtype == AF_INET &&
1244               host_ent->h_length == sizeof(inet_address->sin_addr.s_addr)) {
1245             if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, sizeof(struct sockaddr_in)))) {
1246               raise_error(MEMORY_ERROR);
1247             } else {
1248               result->size = sizeof(struct sockaddr_in);
1249               inet_address = (struct sockaddr_in *) result->mem;
1250               inet_address->sin_family = host_ent->h_addrtype;
1251               inet_address->sin_port = htons((uint16Type) port); /* short, network byte order */
1252               memcpy(&inet_address->sin_addr.s_addr, host_ent->h_addr,
1253                      (size_t) host_ent->h_length);
1254               memset(inet_address->sin_zero, '\0', sizeof(inet_address->sin_zero));
1255               /* {
1256                 uint32Type ip4_address = ntohl(inet_address->sin_addr.s_addr);
1257                 printf("ip4_address=%d.%d.%d.%d\n",
1258                     (ip4_address >> 24  & 255,
1259                     (ip4_address >> 16) & 255,
1260                     (ip4_address >>  8) & 255,
1261                      ip4_address        & 255);
1262               } */
1263             } /* if */
1264           } else {
1265             /* printf("socInetAddr: addrtype=%d\n", host_ent->h_addrtype); */
1266             /* raise_error(FILE_ERROR);
1267                result = NULL; */
1268             /* Return empty address */
1269             if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, 0))) {
1270               raise_error(MEMORY_ERROR);
1271             } else {
1272               result->size = 0;
1273             } /* if */
1274           } /* if */
1275         } /* if */
1276 #endif
1277       } /* if */
1278     } /* if */
1279     logFunction(printf("socInetAddr(\"%s\", " FMT_D ") --> \"%s\"\n",
1280                        striAsUnquotedCStri(hostName), port,
1281                        socAddressCStri(result)););
1282     return result;
1283   } /* socInetAddr */
1284 
1285 
1286 
1287 /**
1288  *  Create an internet socket address of a port at localhost.
1289  *  @return the internet socket address.
1290  *  @exception FILE_ERROR A system function returns an error.
1291  *  @exception RANGE_ERROR The port is not in the range 0 to 65535.
1292  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1293  */
socInetLocalAddr(intType port)1294 bstriType socInetLocalAddr (intType port)
1295 
1296   {
1297 #if HAS_GETADDRINFO
1298     char servicename[10];
1299     struct addrinfo *addrinfo_list;
1300     struct addrinfo *result_addrinfo;
1301     struct addrinfo hints;
1302     int getaddrinfo_result;
1303 #else
1304     struct sockaddr_in *inet_address;
1305 #endif
1306     bstriType result;
1307 
1308   /* socInetLocalAddr */
1309     logFunction(printf("socInetLocalAddr(" FMT_D ")\n", port););
1310     check_initialization(NULL);
1311     if (unlikely(port < 0 || port > 65535)) {
1312       logError(printf("socInetLocalAddr(" FMT_D "): "
1313                       "Port not in allowed range.\n",
1314                       port););
1315       raise_error(RANGE_ERROR);
1316       result = NULL;
1317     } else {
1318 #if HAS_GETADDRINFO
1319       sprintf(servicename, "%u", (unsigned int) port);
1320       memset(&hints, 0, sizeof(struct addrinfo));
1321       hints.ai_family = AF_UNSPEC;
1322       hints.ai_socktype = SOCK_STREAM;
1323       getaddrinfo_result = getaddrinfo(NULL, servicename, &hints, &addrinfo_list);
1324       if (unlikely(getaddrinfo_result != 0)) {
1325         logError(printf("socInetLocalAddr" FMT_D "): "
1326                         "getaddrinfo(NULL, %s, *, *) failed with %d:\n"
1327                         "strerror: %s\n"
1328                         "%s=%d\nerror: %s\n",
1329                         port, servicename, getaddrinfo_result,
1330                         gai_strerror(getaddrinfo_result),
1331                         ERROR_INFORMATION););
1332         raise_error(FILE_ERROR);
1333         result = NULL;
1334       } else {
1335         /* dump_addrinfo(addrinfo_list); */
1336         result_addrinfo = select_addrinfo(addrinfo_list, AF_INET, AF_INET6);
1337         if (unlikely(SOCKLEN_NEGATIVE(result_addrinfo->ai_addrlen) ||
1338                      !ALLOC_BSTRI_SIZE_OK(result,
1339                          (memSizeType) result_addrinfo->ai_addrlen))) {
1340           freeaddrinfo(addrinfo_list);
1341           raise_error(MEMORY_ERROR);
1342         } else {
1343           result->size = (memSizeType) result_addrinfo->ai_addrlen;
1344           memcpy(result->mem, result_addrinfo->ai_addr,
1345                  (memSizeType) result_addrinfo->ai_addrlen);
1346           freeaddrinfo(addrinfo_list);
1347         } /* if */
1348       } /* if */
1349 #else
1350       if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, sizeof(struct sockaddr_in)))) {
1351         raise_error(MEMORY_ERROR);
1352       } else {
1353         result->size = sizeof(struct sockaddr_in);
1354         inet_address = (struct sockaddr_in *) result->mem;
1355         inet_address->sin_family = AF_INET;
1356         inet_address->sin_port = htons((uint16Type) port);      /* short, network byte order */
1357         inet_address->sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* local host */
1358         memset(inet_address->sin_zero, '\0', sizeof(inet_address->sin_zero));
1359       } /* if */
1360 #endif
1361     } /* if */
1362     logFunction(printf("socInetLocalAddr(" FMT_D ") --> \"%s\"\n",
1363                        port, socAddressCStri(result)););
1364     return result;
1365   } /* socInetLocalAddr */
1366 
1367 
1368 
1369 /**
1370  *  Create an internet listener socket address of a port at localhost.
1371  *  @return the internet listener socket address.
1372  *  @exception FILE_ERROR A system function returns an error.
1373  *  @exception RANGE_ERROR The port is not in the range 0 to 65535.
1374  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1375  */
socInetServAddr(intType port)1376 bstriType socInetServAddr (intType port)
1377 
1378   {
1379 #if HAS_GETADDRINFO
1380     char servicename[10];
1381     struct addrinfo *addrinfo_list;
1382     struct addrinfo *result_addrinfo;
1383     struct addrinfo hints;
1384     int getaddrinfo_result;
1385 #else
1386 #ifdef INET6_SERVER_ADDRESS
1387     struct sockaddr_in6 *inet6_address;
1388 #else
1389     struct sockaddr_in *inet_address;
1390 #endif
1391 #endif
1392     bstriType result;
1393 
1394   /* socInetServAddr */
1395     logFunction(printf("socInetServAddr(" FMT_D ")\n", port););
1396     check_initialization(NULL);
1397     if (unlikely(port < 0 || port > 65535)) {
1398       logError(printf("socInetServAddr(" FMT_D "): "
1399                       "Port not in allowed range.\n",
1400                       port););
1401       raise_error(RANGE_ERROR);
1402       result = NULL;
1403     } else {
1404 #if HAS_GETADDRINFO
1405       sprintf(servicename, "%u", (unsigned int) port);
1406       memset(&hints, 0, sizeof(struct addrinfo));
1407       hints.ai_family = AF_UNSPEC;
1408       hints.ai_socktype = SOCK_STREAM;
1409       hints.ai_flags = AI_PASSIVE;
1410       getaddrinfo_result = getaddrinfo(NULL, servicename, &hints, &addrinfo_list);
1411       if (unlikely(getaddrinfo_result != 0)) {
1412         logError(printf("socInetServAddr" FMT_D "): "
1413                         "getaddrinfo(NULL, %s, *, *) failed with %d:\n"
1414                         "strerror: %s\n"
1415                         "%s=%d\nerror: %s\n",
1416                         port, servicename, getaddrinfo_result,
1417                         gai_strerror(getaddrinfo_result),
1418                         ERROR_INFORMATION););
1419         raise_error(FILE_ERROR);
1420         result = NULL;
1421       } else {
1422         /* dump_addrinfo(addrinfo_list); */
1423         result_addrinfo = select_addrinfo(addrinfo_list, AF_INET, AF_INET6);
1424         if (unlikely(SOCKLEN_NEGATIVE(result_addrinfo->ai_addrlen) ||
1425                      !ALLOC_BSTRI_SIZE_OK(result,
1426                          (memSizeType) result_addrinfo->ai_addrlen))) {
1427           freeaddrinfo(addrinfo_list);
1428           raise_error(MEMORY_ERROR);
1429         } else {
1430           result->size = (memSizeType) result_addrinfo->ai_addrlen;
1431           memcpy(result->mem, result_addrinfo->ai_addr,
1432                  (memSizeType) result_addrinfo->ai_addrlen);
1433           freeaddrinfo(addrinfo_list);
1434         } /* if */
1435       } /* if */
1436 #else
1437 #ifdef INET6_SERVER_ADDRESS
1438       if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, sizeof(struct sockaddr_in6)))) {
1439         raise_error(MEMORY_ERROR);
1440       } else {
1441         result->size = sizeof(struct sockaddr_in6);
1442         inet6_address = (struct sockaddr_in6 *) result->mem;
1443         inet6_address->sin6_family = AF_INET6;
1444         inet6_address->sin6_port = htons((uint16Type) port); /* short, network byte order */
1445         inet6_address->sin6_flowinfo = 0;
1446         memcpy(&inet6_address->sin6_addr, &in6addr_any,
1447                sizeof(struct in6_addr));                     /* auto-fill with local IP */
1448         inet6_address->sin6_scope_id = 0;
1449       } /* if */
1450 #else
1451       if (unlikely(!ALLOC_BSTRI_SIZE_OK(result, sizeof(struct sockaddr_in)))) {
1452         raise_error(MEMORY_ERROR);
1453       } else {
1454         result->size = sizeof(struct sockaddr_in);
1455         inet_address = (struct sockaddr_in *) result->mem;
1456         inet_address->sin_family = AF_INET;
1457         inet_address->sin_port = htons((uint16Type) port); /* short, network byte order */
1458         inet_address->sin_addr.s_addr = INADDR_ANY;        /* auto-fill with local IP */
1459         memset(inet_address->sin_zero, '\0', sizeof(inet_address->sin_zero));
1460       } /* if */
1461 #endif
1462 #endif
1463     } /* if */
1464     logFunction(printf("socInetServAddr(" FMT_D ") --> \"%s\"\n",
1465                        port, socAddressCStri(result)););
1466     return result;
1467   } /* socInetServAddr */
1468 
1469 
1470 
1471 #if HAS_POLL
socInputReady(socketType sock,intType seconds,intType micro_seconds)1472 boolType socInputReady (socketType sock, intType seconds, intType micro_seconds)
1473 
1474   {
1475     struct pollfd pollFd[1];
1476     int timeout;
1477     int poll_result;
1478     unsigned char next_char;
1479     memSizeType bytes_received;
1480     boolType inputReady;
1481 
1482   /* socInputReady */
1483     logFunction(printf("socInputReady(%d, " FMT_D ", " FMT_D ")\n",
1484                        sock, seconds, micro_seconds););
1485     if (unlikely(sock == (socketType) -1)) {
1486       logError(printf("socInputReady(%d, " FMT_D ", " FMT_D "): "
1487                       "Invalid socket.\n",
1488                       sock, seconds, micro_seconds););
1489       raise_error(FILE_ERROR);
1490       inputReady = FALSE;
1491     } else if (unlikely(seconds < 0 || seconds >= INT_MAX / 1000 ||
1492                  micro_seconds < 0 || micro_seconds >= 1000000)) {
1493       logError(printf("socInputReady(%d, " FMT_D ", " FMT_D"): "
1494                       "seconds or micro_seconds not in allowed range.\n",
1495                       sock, seconds, micro_seconds););
1496       raise_error(RANGE_ERROR);
1497       inputReady = FALSE;
1498     } else {
1499       pollFd[0].fd = (int) sock;
1500       pollFd[0].events = POLLIN;
1501       timeout = (int) seconds * 1000 + (int) (micro_seconds / 1000);
1502       poll_result = os_poll(pollFd, 1, timeout);
1503       if (unlikely(poll_result < 0)) {
1504         logError(printf("socInputReady(%d, " FMT_D ", " FMT_D "): "
1505                         "os_poll([%d, POLLIN], 1, %d) failed:\n"
1506                         "%s=%d\nerror: %s\n",
1507                         sock, seconds, micro_seconds,
1508                         sock, timeout,
1509                         ERROR_INFORMATION););
1510         raise_error(FILE_ERROR);
1511         inputReady = FALSE;
1512       } else {
1513         inputReady = poll_result == 1 && (pollFd[0].revents & POLLIN);
1514         if (inputReady) {
1515           /* Verify that it is really possible to read at least one character */
1516           bytes_received = (memSizeType) recv((os_socketType) sock,
1517                                               cast_send_recv_data(&next_char), 1, MSG_PEEK);
1518           if (bytes_received != 1) {
1519             /* printf("socInputReady: bytes_received=%ld\n", (long int) bytes_received); */
1520             inputReady = FALSE;
1521           } /* if */
1522         } /* if */
1523       } /* if */
1524     } /* if */
1525     logFunction(printf("socInputReady(%d, " FMT_D ", " FMT_D ") --> %d\n",
1526                        sock, seconds, micro_seconds, inputReady););
1527     return inputReady;
1528   } /* socInputReady */
1529 
1530 #else
1531 
1532 
1533 
socInputReady(socketType sock,intType seconds,intType micro_seconds)1534 boolType socInputReady (socketType sock, intType seconds, intType micro_seconds)
1535 
1536   {
1537     int nfds;
1538     fd_set readfds;
1539     struct timeval timeout;
1540     int select_result;
1541     unsigned char next_char;
1542     memSizeType bytes_received;
1543     boolType inputReady;
1544 
1545   /* socInputReady */
1546     logFunction(printf("socInputReady(%d, " FMT_D ", " FMT_D ")\n",
1547                        sock, seconds, micro_seconds););
1548     if (unlikely(sock == (socketType) -1)) {
1549       logError(printf("socInputReady(%d, " FMT_D ", " FMT_D "): "
1550                       "Invalid socket.\n",
1551                       sock, seconds, micro_seconds););
1552       raise_error(FILE_ERROR);
1553       inputReady = FALSE;
1554     } else if (unlikely(seconds < 0 || seconds >= LONG_MAX ||
1555                  micro_seconds < 0 || micro_seconds >= 1000000)) {
1556       logError(printf("socInputReady(%d, " FMT_D ", " FMT_D"): "
1557                       "seconds or micro_seconds not in allowed range.\n",
1558                       sock, seconds, micro_seconds););
1559       raise_error(RANGE_ERROR);
1560       inputReady = FALSE;
1561     } else {
1562       FD_ZERO(&readfds);
1563       FD_SET((os_socketType) sock, &readfds);
1564       nfds = (int) sock + 1;
1565       timeout.tv_sec = (long int) seconds;
1566       timeout.tv_usec = (long int) micro_seconds;
1567       /* printf("select(%d, %d)\n", nfds, sock); */
1568       select_result = select(nfds, &readfds, NULL, NULL, &timeout);
1569       /* printf("select_result: %d\n", select_result); */
1570       if (unlikely(select_result < 0)) {
1571         logError(printf("socInputReady(%d, " FMT_D ", " FMT_D "): "
1572                         "select(%d, [%d], NULL, NULL, [" FMT_D ", " FMT_D "]) failed:\n"
1573                         "%s=%d\nerror: %s\n",
1574                         sock, seconds, micro_seconds,
1575                         nfds, sock, seconds, micro_seconds,
1576                         ERROR_INFORMATION););
1577         raise_error(FILE_ERROR);
1578         inputReady = FALSE;
1579       } else {
1580         inputReady = FD_ISSET((os_socketType) sock, &readfds);
1581         if (inputReady) {
1582           /* Verify that it is really possible to read at least one character */
1583           bytes_received = (memSizeType) recv((os_socketType) sock,
1584                                               cast_send_recv_data(&next_char), 1, MSG_PEEK);
1585           if (bytes_received != 1) {
1586             /* printf("socInputReady: bytes_received=%ld\n", (long int) bytes_received); */
1587             inputReady = FALSE;
1588           } /* if */
1589         } /* if */
1590       } /* if */
1591     } /* if */
1592     logFunction(printf("socInputReady(%d, " FMT_D ", " FMT_D ") --> %d\n",
1593                        sock, seconds, micro_seconds, inputReady););
1594     return inputReady;
1595   } /* socInputReady */
1596 
1597 #endif
1598 
1599 
1600 
1601 #define BUFFER_START_SIZE 256
1602 #define BUFFER_DELTA_SIZE 256
1603 
1604 /**
1605  *  Read a line from 'inSocket'.
1606  *  The function accepts lines ending with "\n", "\r\n" or EOF.
1607  *  The line ending characters are not copied into the string.
1608  *  That means that the "\r" of a "\r\n" sequence is silently removed.
1609  *  When the function is left terminationChar contains '\n' or EOF.
1610  *  @return the line read.
1611  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1612  */
socLineRead(socketType inSocket,charType * const terminationChar)1613 striType socLineRead (socketType inSocket, charType *const terminationChar)
1614 
1615   {
1616     memSizeType bytes_received;
1617     memSizeType bytes_requested;
1618     memSizeType result_size;
1619     memSizeType old_result_size;
1620     memSizeType result_pos;
1621     ucharType *nlPos;
1622     ucharType buffer[BUFFER_SIZE];
1623     striType resized_result;
1624     striType result;
1625 
1626   /* socLineRead */
1627     logFunction(printf("socLineRead(%d, '\\" FMT_U32 ";')\n",
1628                        inSocket, *terminationChar););
1629     if (unlikely(inSocket == (socketType) -1)) {
1630       logError(printf("socLineRead(%d, '\\" FMT_U32 ";'): Invalid socket.\n",
1631                       inSocket, *terminationChar););
1632       raise_error(FILE_ERROR);
1633       result = NULL;
1634     } else {
1635       bytes_received = (memSizeType) recv((os_socketType) inSocket,
1636                                           cast_send_recv_data(buffer),
1637                                           BUFFER_START_SIZE, MSG_PEEK);
1638       /* printf("socLineRead: bytes_received: " FMT_U_MEM "\n", bytes_received); */
1639       if (bytes_received == (memSizeType) -1) {
1640         bytes_received = 0;
1641       } /* if */
1642       if (bytes_received == 0) {
1643         if (unlikely(!ALLOC_STRI_SIZE_OK(result, 0))) {
1644           raise_error(MEMORY_ERROR);
1645           result = NULL;
1646         } else {
1647           result->size = 0;
1648           *terminationChar = (charType) EOF;
1649         } /* if */
1650       } else {
1651         nlPos = (ucharType *) memchr(buffer, '\n', bytes_received);
1652         if (nlPos != NULL) {
1653           bytes_requested = (memSizeType) (nlPos - buffer) + 1;
1654           /* This should overwrite the buffer with identical data up to '\n'. */
1655           bytes_received = (memSizeType) recv((os_socketType) inSocket,
1656                                               cast_send_recv_data(buffer),
1657                                               cast_buffer_len(bytes_requested), 0);
1658           /* bytes_received should always be identical to bytes_requested. */
1659           result_size = bytes_requested - 1;
1660           if (nlPos != buffer && nlPos[-1] == '\r') {
1661             result_size--;
1662           } /* if */
1663           if (unlikely(!ALLOC_STRI_CHECK_SIZE(result, result_size))) {
1664             raise_error(MEMORY_ERROR);
1665             result = NULL;
1666           } else {
1667             memcpy_to_strelem(result->mem, buffer, result_size);
1668             result->size = result_size;
1669             *terminationChar = '\n';
1670           } /* if */
1671         } else {
1672           result_size = bytes_received;
1673           old_result_size = 0;
1674           result_pos = 0;
1675           result = NULL;
1676           do {
1677             bytes_requested = bytes_received;
1678             /* This should overwrite the buffer with identical data. */
1679             bytes_received = (memSizeType) recv((os_socketType) inSocket,
1680                                                 cast_send_recv_data(buffer),
1681                                                 cast_buffer_len(bytes_requested), 0);
1682             /* bytes_received should always be identical to bytes_requested. */
1683             result_size += BUFFER_DELTA_SIZE;
1684             /* printf("A result=%08lx, old_result_size=%d, result_size=%d\n",
1685                 (unsigned long) result, old_result_size, result_size); */
1686             REALLOC_STRI_CHECK_SIZE(resized_result, result, old_result_size, result_size);
1687             /* printf("B result=%08lx, resized_result=%08lx\n",
1688                 (unsigned long) result, (unsigned long) resized_result); */
1689             if (unlikely(resized_result == NULL)) {
1690               if (result != NULL) {
1691                 FREE_STRI(result, old_result_size);
1692               } /* if */
1693               raise_error(MEMORY_ERROR);
1694               result = NULL;
1695             } else {
1696               result = resized_result;
1697               old_result_size = result_size;
1698               /* printf("a result[%d], size=%d\n", result_pos, bytes_requested); */
1699               memcpy_to_strelem(&result->mem[result_pos], buffer, bytes_requested);
1700               result_pos += bytes_requested;
1701               bytes_received = (memSizeType) recv((os_socketType) inSocket,
1702                                                   cast_send_recv_data(buffer),
1703                                                   BUFFER_DELTA_SIZE, MSG_PEEK);
1704               if (bytes_received == (memSizeType) -1) {
1705                 bytes_received = 0;
1706               } /* if */
1707               if (bytes_received == 0) {
1708                 REALLOC_STRI_CHECK_SIZE(resized_result, result, result_size, result_pos);
1709                 if (unlikely(resized_result == NULL)) {
1710                   FREE_STRI(result, result_size);
1711                   raise_error(MEMORY_ERROR);
1712                   result = NULL;
1713                 } else {
1714                   result = resized_result;
1715                   result->size = result_pos;
1716                   *terminationChar = (charType) EOF;
1717                 } /* if */
1718               } else {
1719                 nlPos = (ucharType *) memchr(buffer, '\n', bytes_received);
1720               } /* if */
1721             } /* if */
1722           } while (result != NULL && bytes_received != 0 && nlPos == NULL);
1723           if (result != NULL && nlPos != NULL) {
1724             bytes_requested = (memSizeType) (nlPos - buffer) + 1;
1725             /* This should overwrite the buffer with identical data up to '\n'. */
1726             bytes_received = (memSizeType) recv((os_socketType) inSocket,
1727                                                 cast_send_recv_data(buffer),
1728                                                 cast_buffer_len(bytes_requested), 0);
1729             /* bytes_received should always be identical to bytes_requested. */
1730             bytes_requested--;
1731             if (nlPos == buffer) {
1732               if (result->mem[result_pos - 1] == '\r') {
1733                 result_pos--;
1734               } /* if */
1735             } else if (nlPos[-1] == '\r') {
1736               bytes_requested--;
1737             } /* if */
1738             old_result_size = result_size;
1739             result_size = result_pos + bytes_requested;
1740             /* printf("C result=%08lx, old_result_size=%d, result_size=%d\n",
1741                 (unsigned long) result, old_result_size, result_size); */
1742             REALLOC_STRI_CHECK_SIZE(resized_result, result, old_result_size, result_size);
1743             /* printf("D result=%08lx, resized_result=%08lx\n",
1744                 (unsigned long) result, (unsigned long) resized_result); */
1745             if (unlikely(resized_result == NULL)) {
1746               FREE_STRI(result, result_size);
1747               raise_error(MEMORY_ERROR);
1748               result = NULL;
1749             } else {
1750               result = resized_result;
1751               /* printf("e result[%d], size=%d\n", result_pos, bytes_requested); */
1752               memcpy_to_strelem(&result->mem[result_pos], buffer, bytes_requested);
1753               result->size = result_size;
1754               *terminationChar = '\n';
1755             } /* if */
1756           } /* if */
1757         } /* if */
1758       } /* if */
1759     } /* if */
1760     logFunction(printf("socLineRead(%d, '\\" FMT_U32 ";') --> \"%s\"\n",
1761                        inSocket, *terminationChar, striAsUnquotedCStri(result)););
1762     return result;
1763   } /* socLineRead */
1764 
1765 
1766 
1767 /**
1768  *  Listen for socket connections and limit the incoming queue.
1769  *  The 'backlog' argument defines the maximum length to which
1770  *  the queue of pending connections for 'listenerSocket' may grow.
1771  *  @exception FILE_ERROR A system function returns an error.
1772  */
socListen(socketType listenerSocket,intType backlog)1773 void socListen (socketType listenerSocket, intType backlog)
1774 
1775   { /* socListen */
1776     logFunction(printf("socListen(%d, " FMT_D ")\n", listenerSocket, backlog););
1777     if (!inIntRange(backlog)) {
1778       logError(printf("socListen(%d, " FMT_D "): "
1779                       "backlog not in allowed range.\n",
1780                       listenerSocket, backlog););
1781       raise_error(RANGE_ERROR);
1782     } else if (unlikely(listen((os_socketType) listenerSocket,
1783                                (int) backlog) != 0)) {
1784       logError(printf("socListen: listen(%d, " FMT_D ") failed:\n"
1785                       "%s=%d\nerror: %s\n",
1786                       listenerSocket, backlog, ERROR_INFORMATION););
1787       raise_error(FILE_ERROR);
1788     } /* if */
1789   } /* socListen */
1790 
1791 
1792 
socRecv(socketType sock,striType * stri,intType length,intType flags)1793 intType socRecv (socketType sock, striType *stri, intType length, intType flags)
1794 
1795   {
1796     striType resized_stri;
1797     memSizeType bytes_requested;
1798     memSizeType old_stri_size;
1799     memSizeType new_stri_size;
1800 
1801   /* socRecv */
1802     logFunction(printf("socRecv(%d, *, " FMT_D ", 0x" FMT_X ")\n",
1803                        sock, length, flags););
1804     if (unlikely(sock == (socketType) -1)) {
1805       logError(printf("socRecv(%d, *, " FMT_D ", 0x" FMT_X "): "
1806                       "Invalid socket.\n",
1807                       sock, length, flags););
1808       raise_error(FILE_ERROR);
1809       return 0;
1810     } else if (unlikely(length < 0 || !inIntRange(flags))) {
1811       logError(printf("socRecv(%d, *, " FMT_D ", 0x" FMT_X "): "
1812                       "length or flags not in allowed range.\n",
1813                       sock, length, flags););
1814       raise_error(RANGE_ERROR);
1815       return 0;
1816     } else {
1817       if ((uintType) length > MAX_MEMSIZETYPE) {
1818         bytes_requested = MAX_MEMSIZETYPE;
1819       } else {
1820         bytes_requested = (memSizeType) length;
1821       } /* if */
1822       old_stri_size = (*stri)->size;
1823       if (old_stri_size < bytes_requested) {
1824         REALLOC_STRI_CHECK_SIZE(resized_stri, *stri, old_stri_size, bytes_requested);
1825         if (unlikely(resized_stri == NULL)) {
1826           raise_error(MEMORY_ERROR);
1827           return 0;
1828         } /* if */
1829         *stri = resized_stri;
1830         COUNT3_STRI(old_stri_size, bytes_requested);
1831         old_stri_size = bytes_requested;
1832       } /* if */
1833       new_stri_size = (memSizeType) recv((os_socketType) sock,
1834                                          cast_send_recv_data((*stri)->mem),
1835                                          cast_buffer_len(bytes_requested), (int) flags);
1836       if (likely(new_stri_size != (memSizeType) -1)) {
1837         memcpy_to_strelem((*stri)->mem, (ustriType) (*stri)->mem, new_stri_size);
1838         (*stri)->size = new_stri_size;
1839         if (new_stri_size < old_stri_size) {
1840           REALLOC_STRI_SIZE_OK(resized_stri, *stri, old_stri_size, new_stri_size);
1841           if (unlikely(resized_stri == NULL)) {
1842             raise_error(MEMORY_ERROR);
1843             return 0;
1844           } /* if */
1845           *stri = resized_stri;
1846           COUNT3_STRI(old_stri_size, new_stri_size);
1847         } /* if */
1848       } /* if */
1849     } /* if */
1850     return (intType) new_stri_size;
1851   } /* socRecv */
1852 
1853 
1854 
socRecvfrom(socketType sock,striType * stri,intType length,intType flags,bstriType * address)1855 intType socRecvfrom (socketType sock, striType *stri, intType length, intType flags,
1856     bstriType *address)
1857 
1858   {
1859     striType resized_stri;
1860     memSizeType old_address_size;
1861     bstriType resized_address;
1862     memSizeType bytes_requested;
1863     sockLenType addrlen;
1864     memSizeType stri_size;
1865 
1866   /* socRecvfrom */
1867     logFunction(printf("socRecvfrom(%d, *, " FMT_D ", 0x" FMT_X ")\n",
1868                        sock, length, flags););
1869     if (unlikely(sock == (socketType) -1)) {
1870       logError(printf("socRecvfrom(%d, *, " FMT_D ", 0x" FMT_X "): "
1871                       "Invalid socket.\n",
1872                       sock, length, flags););
1873       raise_error(FILE_ERROR);
1874       return 0;
1875     } else if (unlikely(length < 0 || !inIntRange(flags))) {
1876       logError(printf("socRecvfrom(%d, *, " FMT_D ", 0x" FMT_X "): "
1877                       "length or flags not in allowed range.\n",
1878                       sock, length, flags););
1879       raise_error(RANGE_ERROR);
1880       return 0;
1881     } else {
1882       if ((uintType) length > MAX_MEMSIZETYPE) {
1883         bytes_requested = MAX_MEMSIZETYPE;
1884       } else {
1885         bytes_requested = (memSizeType) length;
1886       } /* if */
1887       REALLOC_STRI_CHECK_SIZE(resized_stri, *stri, (*stri)->size, bytes_requested);
1888       if (unlikely(resized_stri == NULL)) {
1889         raise_error(MEMORY_ERROR);
1890         return 0;
1891       } /* if */
1892       *stri = resized_stri;
1893       COUNT3_STRI((*stri)->size, bytes_requested);
1894       old_address_size = (*address)->size;
1895       REALLOC_BSTRI_SIZE_OK(resized_address, *address, old_address_size, MAX_ADDRESS_SIZE);
1896       if (unlikely(resized_address == NULL)) {
1897         stri_size = (*stri)->size;
1898         REALLOC_STRI_SIZE_OK(resized_stri, *stri, bytes_requested, stri_size);
1899         if (resized_stri == NULL) {
1900           (*stri)->size = bytes_requested;
1901         } else {
1902           *stri = resized_stri;
1903           COUNT3_STRI(bytes_requested, stri_size);
1904         } /* if */
1905         raise_error(MEMORY_ERROR);
1906         return 0;
1907       } else {
1908         *address = resized_address;
1909         COUNT3_BSTRI(old_address_size, MAX_ADDRESS_SIZE);
1910         addrlen = MAX_ADDRESS_SIZE;
1911         stri_size = (memSizeType) recvfrom((os_socketType) sock,
1912                                            cast_send_recv_data((*stri)->mem),
1913                                            cast_buffer_len(bytes_requested), (int) flags,
1914                                            (struct sockaddr *) (*address)->mem, &addrlen);
1915         if (unlikely(stri_size == (memSizeType) -1 || addrlen < 0 ||
1916                      addrlen > MAX_ADDRESS_SIZE)) {
1917           REALLOC_BSTRI_SIZE_OK(resized_address, *address, MAX_ADDRESS_SIZE, old_address_size);
1918           if (resized_address == NULL) {
1919             (*address)->size = MAX_ADDRESS_SIZE;
1920           } else {
1921             *address = resized_address;
1922             COUNT3_BSTRI(MAX_ADDRESS_SIZE, old_address_size);
1923           } /* if */
1924           logError(printf("socRecvfrom: recvfrom(%d, ...) failed:\n"
1925                           "%s=%d\nerror: %s\n",
1926                           sock, ERROR_INFORMATION););
1927           raise_error(FILE_ERROR);
1928         } else {
1929           REALLOC_BSTRI_SIZE_OK(resized_address, *address, MAX_ADDRESS_SIZE,
1930                                 (memSizeType) addrlen);
1931           if (unlikely(resized_address == NULL)) {
1932             (*address)->size = MAX_ADDRESS_SIZE;
1933             raise_error(MEMORY_ERROR);
1934             return 0;
1935           } else {
1936             *address = resized_address;
1937             COUNT3_BSTRI(MAX_ADDRESS_SIZE, (memSizeType) addrlen);
1938             (*address)->size = (memSizeType) addrlen;
1939           } /* if */
1940         } /* if */
1941       } /* if */
1942       if (likely(stri_size != (memSizeType) -1)) {
1943         memcpy_to_strelem((*stri)->mem, (ustriType) (*stri)->mem, stri_size);
1944         (*stri)->size = stri_size;
1945         if (stri_size < bytes_requested) {
1946           REALLOC_STRI_SIZE_OK(resized_stri, *stri, bytes_requested, stri_size);
1947           if (unlikely(resized_stri == NULL)) {
1948             raise_error(MEMORY_ERROR);
1949             return 0;
1950           } /* if */
1951           *stri = resized_stri;
1952           COUNT3_STRI(bytes_requested, stri_size);
1953         } /* if */
1954       } /* if */
1955     } /* if */
1956     return (intType) stri_size;
1957   } /* socRecvfrom */
1958 
1959 
1960 
socSend(socketType sock,const const_striType stri,intType flags)1961 intType socSend (socketType sock, const const_striType stri, intType flags)
1962 
1963   {
1964     bstriType buf;
1965     memSizeType bytes_sent;
1966     errInfoType err_info = OKAY_NO_ERROR;
1967     intType result;
1968 
1969   /* socSend */
1970     logFunction(printf("socSend(%d, \"%s\", 0x" FMT_X ")\n",
1971                        sock, striAsUnquotedCStri(stri), flags););
1972     if (unlikely(sock == (socketType) -1)) {
1973       logError(printf("socSend(%d, \"%s\", 0x" FMT_X "): "
1974                       "Invalid socket.\n",
1975                       sock, striAsUnquotedCStri(stri), flags););
1976       raise_error(FILE_ERROR);
1977       result = 0;
1978     } else if (unlikely(!inIntRange(flags))) {
1979       logError(printf("socSend(%d, \"%s\", 0x" FMT_X "): "
1980                       "flags not in allowed range.\n",
1981                       sock, striAsUnquotedCStri(stri), flags););
1982       raise_error(RANGE_ERROR);
1983       result = 0;
1984     } else {
1985       buf = stri_to_bstri(stri, &err_info);
1986       if (unlikely(buf == NULL)) {
1987         logError(printf("socSend: stri_to_bstri(\"%s\", *) failed:\n"
1988                         "err_info=%d\n",
1989                         striAsUnquotedCStri(stri), err_info););
1990         raise_error(err_info);
1991         result = 0;
1992       } else {
1993         bytes_sent = (memSizeType) send((os_socketType) sock,
1994                                         cast_send_recv_data(buf->mem),
1995                                         cast_buffer_len(buf->size), (int) flags);
1996         FREE_BSTRI(buf, buf->size);
1997         if (unlikely(bytes_sent == (memSizeType) -1)) {
1998           result = -1;
1999         } else if (unlikely(bytes_sent > MAX_MEM_INDEX)) {
2000           result = MAX_MEM_INDEX;
2001         } else {
2002           result = (intType) bytes_sent;
2003         } /* if */
2004       } /* if */
2005     } /* if */
2006     return result;
2007   } /* socSend */
2008 
2009 
2010 
socSendto(socketType sock,const const_striType stri,intType flags,const_bstriType address)2011 intType socSendto (socketType sock, const const_striType stri, intType flags,
2012     const_bstriType address)
2013 
2014   {
2015     bstriType buf;
2016     memSizeType bytes_sent;
2017     errInfoType err_info = OKAY_NO_ERROR;
2018     intType result;
2019 
2020   /* socSendto */
2021     logFunction(printf("socSendto(%d, \"%s\", 0x" FMT_X ", \"%s\")\n",
2022                        sock, striAsUnquotedCStri(stri), flags,
2023                        socAddressCStri(address)););
2024     if (unlikely(sock == (socketType) -1)) {
2025       logError(printf("socSendto(%d, \"%s\", 0x" FMT_X ", \"%s\"): "
2026                       "Invalid socket.\n",
2027                       sock, striAsUnquotedCStri(stri), flags,
2028                       socAddressCStri(address)););
2029       raise_error(FILE_ERROR);
2030       result = 0;
2031     } else if (unlikely(!inIntRange(flags))) {
2032       logError(printf("socSendto(%d, \"%s\", 0x" FMT_X ", \"%s\"): "
2033                       "flags not in allowed range.\n",
2034                       sock, striAsUnquotedCStri(stri), flags,
2035                       socAddressCStri(address)););
2036       raise_error(RANGE_ERROR);
2037       result = 0;
2038     } else {
2039       buf = stri_to_bstri(stri, &err_info);
2040       if (unlikely(buf == NULL)) {
2041         logError(printf("socSendto: stri_to_bstri(\"%s\", *) failed:\n"
2042                         "err_info=%d\n",
2043                         striAsUnquotedCStri(stri), err_info););
2044         raise_error(err_info);
2045         result = 0;
2046       } else {
2047         bytes_sent = (memSizeType) sendto((os_socketType) sock,
2048                                           cast_send_recv_data(buf->mem),
2049                                           cast_buffer_len(buf->size), (int) flags,
2050                                           (const struct sockaddr *) address->mem,
2051                                           (sockLenType) address->size);
2052         FREE_BSTRI(buf, buf->size);
2053         if (unlikely(bytes_sent == (memSizeType) -1)) {
2054           result = -1;
2055         } else if (unlikely(bytes_sent > MAX_MEM_INDEX)) {
2056           result = MAX_MEM_INDEX;
2057         } else {
2058           result = (intType) bytes_sent;
2059         } /* if */
2060       } /* if */
2061     } /* if */
2062     return result;
2063   } /* socSendto */
2064 
2065 
2066 
socSetOptBool(socketType sock,intType optname,boolType optval)2067 void socSetOptBool (socketType sock, intType optname, boolType optval)
2068 
2069   { /* socSetOptBool */
2070     logFunction(printf("socSetOptBool(%d, " FMT_D ", %s)\n",
2071                        sock, optname, optval ? "TRUE" : "FALSE"););
2072     switch (castIntTypeForSwitch(optname)) {
2073       case SOC_OPT_NONE:
2074         break;
2075       case SOC_OPT_REUSEADDR: {
2076           int so_reuseaddr = optval;
2077           if (unlikely(setsockopt((os_socketType) sock,
2078                                   SOL_SOCKET, SO_REUSEADDR,
2079                                   (const char *) &so_reuseaddr,
2080                                   sizeof(so_reuseaddr)) != 0)) {
2081             logError(printf("socSetOptBool(%d, " FMT_D ", %s): "
2082                             "setsockopt(%d, ...) failed:\n"
2083                             "%s=%d\nerror: %s\n",
2084                             sock, optname, optval ? "TRUE" : "FALSE",
2085                             sock, ERROR_INFORMATION););
2086             raise_error(FILE_ERROR);
2087           } /* if */
2088         }
2089         break;
2090       default:
2091         logError(printf("socSetOptBool(%d, " FMT_D ", %s): "
2092                         "Unsupperted option.\n",
2093                         sock, optname, optval ? "TRUE" : "FALSE"););
2094         raise_error(RANGE_ERROR);
2095         break;
2096     } /* switch */
2097   } /* socSetOptBool */
2098 
2099 
2100 
socSocket(intType domain,intType type,intType protocol)2101 socketType socSocket (intType domain, intType type, intType protocol)
2102 
2103   {
2104     os_socketType result;
2105 
2106   /* socSocket */
2107     logFunction(printf("socSocket(" FMT_D ", " FMT_D ", " FMT_D ")\n",
2108                        domain, type, protocol););
2109     if (unlikely(!inIntRange(domain) || !inIntRange(type) || !inIntRange(protocol))) {
2110       logError(printf("socSocket(" FMT_D ", " FMT_D ", " FMT_D "): "
2111                       "domain, type or protocol not in allowed range.\n",
2112                       domain, type, protocol););
2113       raise_error(RANGE_ERROR);
2114       result = 0;
2115     } else {
2116       /* printf("socSocket(%d, %d, %d)\n", domain, type, protocol); */
2117       check_initialization((socketType) -1);
2118       result = (os_socketType) socket((int) domain, (int) type, (int) protocol);
2119 #if SOCKET_LIB == WINSOCK_SOCKETS && !TWOS_COMPLEMENT_INTTYPE
2120       /* In this case INVALID_SOCKET != (socketType) -1 holds and    */
2121       /* (socketType) -1 must be returned instead of INVALID_SOCKET. */
2122       /* Probably a computer, which needs this, does not exist.      */
2123       if (unlikely(result == INVALID_SOCKET)) {
2124         result = (os_socketType) -1;
2125       } /* if */
2126 #endif
2127     } /* if */
2128     logFunction(printf("socSocket(" FMT_D ", " FMT_D ", " FMT_D ") --> %d\n",
2129                        domain, type, protocol, result););
2130     return (socketType) result;
2131   } /* socSocket */
2132 
2133 
2134 
2135 /**
2136  *  Read a word from 'inSocket'.
2137  *  Before reading the word it skips spaces and tabs. The function
2138  *  accepts words ending with " ", "\t", "\n", "\r\n" or EOF.
2139  *  The word ending characters are not copied into the string.
2140  *  That means that the "\r" of a "\r\n" sequence is silently removed.
2141  *  When the function is left terminationChar contains ' ', '\t', '\n' or
2142  *  EOF.
2143  *  @return the word read.
2144  *  @exception MEMORY_ERROR Not enough memory to represent the result.
2145  */
socWordRead(socketType inSocket,charType * const terminationChar)2146 striType socWordRead (socketType inSocket, charType *const terminationChar)
2147 
2148   {
2149     unsigned char ch;
2150     register memSizeType position;
2151     register memSizeType bytes_received;
2152     strElemType *memory;
2153     memSizeType memlength = READ_STRI_INIT_SIZE;
2154     memSizeType newmemlength;
2155     striType resized_result;
2156     striType result;
2157 
2158   /* socWordRead */
2159     logFunction(printf("socWordRead(%d, '\\" FMT_U32 ";')\n",
2160                        inSocket, *terminationChar););
2161     if (unlikely(inSocket == (socketType) -1)) {
2162       logError(printf("socWordRead(%d, '\\" FMT_U32 ";'): Invalid socket.\n",
2163                       inSocket, *terminationChar););
2164       raise_error(FILE_ERROR);
2165       result = NULL;
2166     } else if (unlikely(!ALLOC_STRI_SIZE_OK(result, memlength))) {
2167       raise_error(MEMORY_ERROR);
2168     } else {
2169       memory = result->mem;
2170       position = 0;
2171       do {
2172         bytes_received = (memSizeType) recv((os_socketType) inSocket,
2173                                             cast_send_recv_data(&ch), 1, 0);
2174       } while (bytes_received == 1 && (ch == ' ' || ch == '\t'));
2175       while (bytes_received == 1 &&
2176           ch != ' ' && ch != '\t' && ch != '\n') {
2177         if (position >= memlength) {
2178           newmemlength = memlength + READ_STRI_SIZE_DELTA;
2179           REALLOC_STRI_CHECK_SIZE(resized_result, result, memlength, newmemlength);
2180           if (unlikely(resized_result == NULL)) {
2181             FREE_STRI(result, memlength);
2182             raise_error(MEMORY_ERROR);
2183             return NULL;
2184           } /* if */
2185           result = resized_result;
2186           COUNT3_STRI(memlength, newmemlength);
2187           memory = result->mem;
2188           memlength = newmemlength;
2189         } /* if */
2190         memory[position++] = (strElemType) ch;
2191         bytes_received = (memSizeType) recv((os_socketType) inSocket,
2192                                             cast_send_recv_data(&ch), 1, 0);
2193       } /* while */
2194       if (bytes_received == 1 && ch == '\n' &&
2195           position != 0 && memory[position - 1] == '\r') {
2196         position--;
2197       } /* if */
2198       REALLOC_STRI_SIZE_OK(resized_result, result, memlength, position);
2199       if (unlikely(resized_result == NULL)) {
2200         FREE_STRI(result, memlength);
2201         raise_error(MEMORY_ERROR);
2202         result = NULL;
2203       } else {
2204         result = resized_result;
2205         COUNT3_STRI(memlength, position);
2206         result->size = position;
2207         if (bytes_received != 1) {
2208           *terminationChar = (charType) EOF;
2209         } else {
2210           *terminationChar = (charType) ch;
2211         } /* if */
2212       } /* if */
2213     } /* if */
2214     logFunction(printf("socWordRead(%d, '\\" FMT_U32 ";') --> \"%s\"\n",
2215                        inSocket, *terminationChar, striAsUnquotedCStri(result)););
2216     return result;
2217   } /* socWordRead */
2218 
2219 
2220 
2221 /**
2222  *  Write a string to 'outSocket'.
2223  *  @exception FILE_ERROR The system function is not able to write
2224  *             all characters of the string.
2225  *  @exception RANGE_ERROR The string contains a character that does
2226  *             not fit into a byte.
2227  */
socWrite(socketType outSocket,const const_striType stri)2228 void socWrite (socketType outSocket, const const_striType stri)
2229 
2230   {
2231     ucharType buffer[BUFFER_SIZE];
2232     ustriType buf;
2233     memSizeType bytes_to_send;
2234     memSizeType bytes_sent;
2235     memSizeType totally_sent = 0;
2236     errInfoType err_info = OKAY_NO_ERROR;
2237     bstriType bstri = NULL;
2238 
2239   /* socWrite */
2240     logFunction(printf("socWrite(%d, \"%s\")\n",
2241                        outSocket, striAsUnquotedCStri(stri)););
2242     if (unlikely(outSocket == (socketType) -1)) {
2243         logError(printf("socWrite(%d, \"%s\"): Invalid socket.\n",
2244                         outSocket, striAsUnquotedCStri(stri)););
2245       err_info = FILE_ERROR;
2246       buf = NULL;
2247       bytes_to_send = 0;
2248     } else if (stri->size <= BUFFER_SIZE) {
2249       if (unlikely(memcpy_from_strelem(buffer, stri->mem, stri->size))) {
2250         logError(printf("socWrite(%d, \"%s\"): "
2251                         "At least one character does not fit into a byte.\n",
2252                         outSocket, striAsUnquotedCStri(stri)););
2253         err_info = RANGE_ERROR;
2254         buf = NULL;
2255         bytes_to_send = 0;
2256       } else {
2257         buf = buffer;
2258         bytes_to_send = stri->size;
2259       } /* if */
2260     } else {
2261       bstri = stri_to_bstri(stri, &err_info);
2262       if (unlikely(bstri == NULL)) {
2263         logError(printf("socWrite(%d, \"%s\"): "
2264                         "Failed to create a temporary bstring.\n"
2265                         "err_info=%d\n",
2266                         outSocket, striAsUnquotedCStri(stri), err_info););
2267         buf = NULL;
2268         bytes_to_send = 0;
2269       } else {
2270         buf = bstri->mem;
2271         bytes_to_send = bstri->size;
2272       } /* if */
2273     } /* if */
2274     while (bytes_to_send != 0 && err_info == OKAY_NO_ERROR) {
2275       bytes_sent = (memSizeType) send((os_socketType) outSocket,
2276                                       cast_send_recv_data(&buf[totally_sent]),
2277                                       cast_buffer_len(bytes_to_send), 0);
2278       if (bytes_sent == (memSizeType) -1) {
2279         logError(printf("socWrite: send(%d, data, " FMT_U_MEM ") failed:\n"
2280                         "%s=%d\nerror: %s\n"
2281                         "bytes sent successfully: " FMT_U_MEM "\n",
2282                         outSocket, bytes_to_send, ERROR_INFORMATION,
2283                         totally_sent););
2284         err_info = FILE_ERROR;
2285       } else {
2286         totally_sent += bytes_sent;
2287         bytes_to_send -= bytes_sent;
2288       } /* if */
2289     } /* while */
2290     if (bstri != NULL) {
2291       FREE_BSTRI(bstri, bstri->size);
2292     } /* if */
2293     if (unlikely(err_info != OKAY_NO_ERROR)) {
2294       raise_error(err_info);
2295     } /* if */
2296   } /* socWrite */
2297 
2298 #endif
2299