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