/src/sflsock.c
C | 2126 lines | 1216 code | 252 blank | 658 comment | 188 complexity | 4a9dbb63d0825e46972cab6827944732 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/*===========================================================================* 2 * * 3 * sflsock.c - Socket handling functions * 4 * * 5 * Copyright (c) 1991-2010 iMatix Corporation * 6 * * 7 * ------------------ GPL Licensed Source Code ------------------ * 8 * iMatix makes this software available under the GNU General * 9 * Public License (GPL) license for open source projects. For * 10 * details of the GPL license please see www.gnu.org or read the * 11 * file license.gpl provided in this package. * 12 * * 13 * This program is free software; you can redistribute it and/or * 14 * modify it under the terms of the GNU General Public License as * 15 * published by the Free Software Foundation; either version 2 of * 16 * the License, or (at your option) any later version. * 17 * * 18 * This program is distributed in the hope that it will be useful, * 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 21 * GNU General Public License for more details. * 22 * * 23 * You should have received a copy of the GNU General Public * 24 * License along with this program in the file 'license.gpl'; if * 25 * not, write to the Free Software Foundation, Inc., 59 Temple * 26 * Place - Suite 330, Boston, MA 02111-1307, USA. * 27 * * 28 * You can also license this software under iMatix's General Terms * 29 * of Business (GTB) for commercial projects. If you have not * 30 * explicitly licensed this software under the iMatix GTB you may * 31 * only use it under the terms of the GNU General Public License. * 32 * * 33 * For more information, send an email to info@imatix.com. * 34 * -------------------------------------------------------------- * 35 *===========================================================================*/ 36 37#include "prelude.h" /* Universal header file */ 38#include "sfllist.h" /* List-management functions */ 39#include "sflmem.h" /* Memory-allocation functions */ 40#include "sflsymb.h" /* Symbol-table functions */ 41#include "sfltok.h" /* Token-handling functions */ 42#include "sfluid.h" /* User/group functions */ 43#include "sflcons.h" /* Console i/o functions */ 44#include "sflfile.h" /* File handling functions */ 45#include "sflprint.h" /* snprintf functions */ 46#include "sflsock.h" /* Prototypes for functions */ 47 48/* Implementation notes 49 * 50 * These functions work on 16-bit Windows, 32-bit Windows, 32-bit UNIX, 51 * 64-bit UNIX, Digital OpenVMS. The size of a socket handle varies from 52 * 16 bits to 64 bits. All native socket functions define a socket handle 53 * as 'int'. However, we need a fixed-length external representation. So, 54 * we define a type, 'sock_t', which is a qbyte (32 bits). Outside this 55 * package, sockets are always a 'sock_t'. Internally, we always use an 56 * (SOCKET) cast when passing a sock_t to a system function like connect(). 57 * If the system does not support sockets we fake them just a little. 58 * 59 * Modifications Oct 7 1998 for Unix by Grant McDorman <grant@isgtec.com> to 60 * allow running with the program suid root; it will run as the user until 61 * the socket must be opened; at that time, it will briefly switch to root 62 * and then return to the actual user id. 63 */ 64 65/* Global variables */ 66 67int 68 ip_portbase = 0; /* Base for created services */ 69Bool 70 ip_nonblock = TRUE; /* Create non-blocking sockets */ 71qbyte 72 ip_passive = INADDR_ANY; /* IP address for passive connects */ 73int 74 ip_sockets = 0; /* Number of open sockets */ 75 76 77/* The connect_error_value holds the last recorded error cause after a */ 78/* connection attempt. */ 79 80static int 81 connect_error_value = 0; 82char 83 *connect_errlist [] = { /* Corresponding error messages */ 84 "No errors", 85 "System does not support sockets", 86 "Host is not known", 87 "Service or port not known", 88 "Protocol not known", 89 "Connection failed on socket()", 90 "Connection failed on connect()", 91 "Port is already used by another server", 92 "Connection failed on listen()" 93 }; 94 95/* Internal functions used to create passive and active connections */ 96 97#if (defined (DOES_SOCKETS)) 98static void prepare_socket (sock_t handle); 99# if (defined (__WINDOWS__)) 100static int win_error (int rc); 101# endif 102#endif 103 104 105/* ---------------------------------------------------------------------[<]- 106 Function: sock_init 107 108 Synopsis: Initialise the internet protocol. On most systems this is a 109 null call. On some systems this loads dynamic libraries. Returns 0 110 if everything was okay, else returns SOCKET_ERROR. You should call 111 sock_term() when your program ends. 112 ---------------------------------------------------------------------[>]-*/ 113 114int 115sock_init (void) 116{ 117#if (defined (__WINDOWS__)) 118 WORD 119 wVersionRequested; /* We really want Winsock 1.1 */ 120 WSADATA 121 wsaData; 122 123 wVersionRequested = 0x0101; /* ... but we'll take 1.1 */ 124 if (WSAStartup (wVersionRequested, &wsaData) == 0) 125 return (0); 126 else 127 return ((int) SOCKET_ERROR); 128 129#elif (defined (__UTYPE_BEOS)) 130 /* BeOS numbers sockets from 0 upwards, but this causes havoc with 131 * programs that expect a BSD-style numbering of 1 or higher. We 132 * force compatibility by creating (and wasting) one socket so that 133 * further socket handles are guaranteed >0. 134 */ 135 create_socket ("tcp"); 136 return (0); 137 138#elif (defined (DOES_SOCKETS) || defined (FAKE_SOCKETS)) 139 return (0); 140 141#else 142 connect_error_value = IP_NOSOCKETS; 143 return ((int) SOCKET_ERROR); /* Sockets not supported */ 144#endif 145} 146 147 148/* ---------------------------------------------------------------------[<]- 149 Function: sock_term 150 151 Synopsis: Shuts-down the internet protocol. On most systems this is a 152 null call. On some systems this unloads dynamic libraries. Returns -1 153 if there was an error, or 0 if everything was okay. See sock_init(). 154 ---------------------------------------------------------------------[>]-*/ 155 156int 157sock_term (void) 158{ 159#if (defined (__WINDOWS__)) 160 WSACleanup (); 161#endif 162 return (0); 163} 164 165 166/* ---------------------------------------------------------------------[<]- 167 Function: passive_TCP 168 169 Synopsis: Creates a passive bound TCP socket for the specified service. 170 Returns socket number or INVALID_SOCKET. If it returns INVALID_SOCKET, 171 you can get the reason for the error by calling connect_error (). This 172 may be one of: 173 <TABLE> 174 IP_NOSOCKETS Sockets not supported on this system 175 IP_BADSERVICE Service cannot be converted to port number 176 IP_BADPROTOCOL Cannot understand protocol name 177 IP_SOCKETERROR Cannot create the passive socket 178 IP_BINDERROR Cannot bind to the port 179 IP_LISTENERROR Cannot listen to port 180 </TABLE> 181 ---------------------------------------------------------------------[>]-*/ 182 183sock_t 184passive_TCP ( 185 const char *service, /* Service name or port as string */ 186 int queue_length /* Queue length for listen() */ 187) 188{ 189 ASSERT (service && *service); 190 ASSERT (queue_length > 0); 191 return (passive_socket (service, "tcp", queue_length)); 192} 193 194 195/* ---------------------------------------------------------------------[<]- 196 Function: passive_UDP 197 198 Synopsis: Creates a passive UDP socket for the specified service. 199 Returns socket number or INVALID_SOCKET. If it returns INVALID_SOCKET, 200 you can get the reason for the error by calling connect_error (). This 201 may be one of: 202 <TABLE> 203 IP_NOSOCKETS Sockets not supported on this system 204 IP_BADSERVICE Service cannot be converted to port number 205 IP_BADPROTOCOL Cannot understand protocol name 206 IP_SOCKETERROR Cannot create the passive socket 207 IP_BINDERROR Cannot bind to the port 208 </TABLE> 209 ---------------------------------------------------------------------[>]-*/ 210 211sock_t 212passive_UDP ( 213 const char *service /* Service name or port as string */ 214) 215{ 216 ASSERT (service && *service); 217 return (passive_socket (service, "udp", 0)); 218} 219 220 221/* ---------------------------------------------------------------------[<]- 222 Function: passive_socket 223 224 Synopsis: 225 Creates a passive TCP or UDP socket. This function allows a server 226 program to create a master socket, so that connections can be accepted. 227 Used by the passive_TCP and passive_UDP functions. Returns a socket 228 number or INVALID_SOCKET. If it returns INVALID_SOCKET, you can get the 229 reason for the error by calling connect_error (). This may be one of: 230 <TABLE> 231 IP_NOSOCKETS Sockets not supported on this system 232 IP_BADSERVICE Service cannot be converted to port number 233 IP_BADPROTOCOL Cannot understand protocol name 234 IP_SOCKETERROR Cannot create the passive socket 235 IP_BINDERROR Cannot bind to the port 236 IP_LISTENERROR Cannot listen to port 237 </TABLE> 238 By default, opens a socket on all available IP addresses. You can open 239 the socket on a specific address, by setting the global variable 240 ip_passive to the address (in network order). This variable is reset 241 to INADDR_ANY after each call to passive_socket or one of the functions 242 that calls it. 243 ---------------------------------------------------------------------[>]-*/ 244 245sock_t 246passive_socket ( 247 const char *service, /* Service name or port as string */ 248 const char *protocol, /* Protocol "tcp" or "udp" */ 249 int queue_length /* Queue length for TCP sockets */ 250) 251{ 252#if (defined (DOES_SOCKETS)) 253 struct servent 254 *pse; /* Service information entry */ 255 struct sockaddr_in 256 sin; /* Internet end-point address */ 257 sock_t 258 handle; /* Socket from socket() call */ 259 260 ASSERT (service && *service); 261 ASSERT (protocol && *protocol); 262 263 connect_error_value = IP_NOERROR; /* Assume no errors */ 264 265 memset ((void *) &sin, 0, sizeof (sin)); 266 sin.sin_family = AF_INET; 267 sin.sin_addr.s_addr = ip_passive; 268 ip_passive = INADDR_ANY; /* Reset passive address */ 269 270 /* To allow privileged operations, if possible */ 271 set_uid_root (); 272 273 /* Map service name to port number */ 274 pse = getservbyname (service, protocol); 275 if (pse) 276 sin.sin_port = htons ((dbyte) (ntohs (pse-> s_port) + ip_portbase)); 277 else 278 { 279 sin.sin_port = atoi (service); 280 if (sin.sin_port + ip_portbase > 0) 281 sin.sin_port = htons ((dbyte) (sin.sin_port + ip_portbase)); 282 else 283 { 284 connect_error_value = IP_BADSERVICE; 285 set_uid_user (); 286 return (INVALID_SOCKET); 287 } 288 } 289 handle = create_socket (protocol); 290 if (handle == INVALID_SOCKET) /* Cannot create the socket */ 291 { 292 set_uid_user (); 293 return (INVALID_SOCKET); 294 } 295 296 /* Bind the socket */ 297 if (bind ((SOCKET) handle, (struct sockaddr *) &sin, 298 sizeof (sin)) == SOCKET_ERROR) 299 { 300 connect_error_value = IP_BINDERROR; 301 set_uid_user (); 302 return (INVALID_SOCKET); /* Cannot bind to port */ 303 } 304 set_uid_user (); 305 306 /* Specify incoming queue length for stream socket */ 307 if (streq (protocol, "tcp") 308 && listen ((SOCKET) handle, queue_length) == SOCKET_ERROR) 309 { 310 connect_error_value = IP_LISTENERROR; 311 return (INVALID_SOCKET); /* Cannot listen on port */ 312 } 313 return (handle); 314 315#elif (defined (FAKE_SOCKETS)) 316 return (1); /* Return dummy handle */ 317 318#else 319 connect_error_value = IP_NOSOCKETS; 320 return (INVALID_SOCKET); /* Sockets not supported */ 321#endif 322} 323 324 325/* ---------------------------------------------------------------------[<]- 326 Function: create_socket 327 328 Synopsis: 329 Creates a TCP or UDP socket. The socket is not connected. To use 330 with TCP services you must bind or connect the socket. You can use 331 the socket with UDP services - e.g. read_UDP () - immediately. Returns 332 a socket number or INVALID_SOCKET, in which case you can get the reason 333 for the error by calling connect_error (). This may be one of: 334 <TABLE> 335 IP_NOSOCKETS Sockets not supported on this system 336 IP_BADPROTOCOL Cannot understand protocol name 337 IP_SOCKETERROR Cannot create the socket 338 </TABLE> 339 ---------------------------------------------------------------------[>]-*/ 340 341sock_t 342create_socket ( 343 const char *protocol /* Protocol "tcp" or "udp" */ 344) 345{ 346#if (defined (DOES_SOCKETS)) 347 struct protoent 348 *ppe; /* Protocol information entry */ 349 int 350# if (!defined (__WINDOWS__)) 351 true_value = 1, /* Boolean value for setsockopt() */ 352# endif 353 sock_type; /* Type of socket we want */ 354 sock_t 355 handle; /* Socket from socket() call */ 356 357 ASSERT (protocol && *protocol); 358 connect_error_value = IP_NOERROR; /* Assume no errors */ 359 360 /* Map protocol name to protocol number */ 361 ppe = getprotobyname (protocol); 362 if (ppe == NULL) /* Cannot get protocol entry */ 363 { 364 connect_error_value = IP_BADPROTOCOL; 365 return (INVALID_SOCKET); 366 } 367 /* Use protocol string to choose a socket type */ 368 if (streq (protocol, "udp")) 369 sock_type = SOCK_DGRAM; 370 else 371 sock_type = SOCK_STREAM; 372 373 /* Allocate a socket */ 374 handle = (sock_t) socket (AF_INET, sock_type, ppe-> p_proto); 375 if (handle == INVALID_SOCKET) /* Cannot create passive socket */ 376 { 377 connect_error_value = IP_SOCKETERROR; 378 return (INVALID_SOCKET); 379 } 380# if (!defined (__WINDOWS__)) 381 /* On BSD-socket systems we need to do this to allow the server to 382 * restart on a previously-used socket, without an annoying timeout 383 * of several minutes. With winsock the reuseaddr option lets the 384 * server work with an already-used socket (!), so we don't do it. 385 */ 386 setsockopt ((SOCKET) handle, SOL_SOCKET, SO_REUSEADDR, 387 (char *) &true_value, sizeof (true_value)); 388# endif 389 prepare_socket (handle); /* Ready socket for use */ 390 ip_sockets++; 391 return (handle); 392 393#elif (defined (FAKE_SOCKETS)) 394 return (1); /* Return dummy handle */ 395 396#else 397 connect_error_value = IP_NOSOCKETS; 398 return (INVALID_SOCKET); /* Sockets not supported */ 399#endif 400} 401 402 403#if (defined (DOES_SOCKETS)) 404/* ------------------------------------------------------------------------- 405 * prepare_socket -- internal 406 * 407 * Does any system-specific work required to prepare a socket for normal 408 * use. In Windows we have to set the socket to nonblocking mode. In 409 * UNIX we do this if the ip_nonblock flag is set. 410 */ 411 412static void 413prepare_socket (sock_t handle) 414{ 415#if (defined (__WINDOWS__)) 416 u_long 417 command = ip_nonblock? 1: 0; 418 419 /* Redirect events and set non-blocking mode */ 420 if (handle != INVALID_SOCKET) 421 ioctlsocket ((SOCKET) handle, FIONBIO, &command); 422 423#elif (defined (__UTYPE_BEOS)) 424 setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK, 425 (void *) &ip_nonblock, sizeof (ip_nonblock)); 426 427#elif (defined (__UNIX__) || defined (__OS2__)) 428 if (ip_nonblock) 429 fcntl ((SOCKET) handle, F_SETFL, O_NONBLOCK 430 | fcntl (handle, F_GETFL, 0)); 431#endif 432} 433#endif 434 435 436/* ---------------------------------------------------------------------[<]- 437 Function: connect_TCP 438 439 Synopsis: 440 Creates a TCP socket and connects it to a specified host and service. 441 Returns a socket number or INVALID_SOCKET. In that case you can get 442 the reason for the error by calling connect_error (). This may be: 443 <TABLE> 444 IP_NOSOCKETS Sockets not supported on this system 445 IP_BADHOST Host is not known 446 IP_BADPROTOCOL Cannot understand protocol name 447 IP_SOCKETERROR Cannot open a socket 448 IP_CONNECTERROR Cannot connect socket 449 </TABLE> 450 The host name may be a full name, NULL or "" meaning the current host, 451 or a dotted-decimal number. The service may be a defined service, e.g. 452 "echo", or a port number, specified as an ASCII string. See 453 connect_socket() for details. 454 455 Single-threaded clients may set ip_nonblock to FALSE and block on all 456 read and write operations. They may use select() if they need to be 457 able to time-out during reading/writing. 458 459 Multi-threaded servers should set ip_nonblock to TRUE, and use select() 460 to multiplex socket access. When ip_nonblock is TRUE, connect calls 461 will return immediately, and the server should use select() to wait until 462 the socket is ready for writing. On some systems (early Linux?), the 463 select() call will fail in this situation. If you compile with 464 -DBLOCKING_CONNECT, connects are done synchronously in all cases. 465 466 Examples: 467 sock_t handle; 468 handle = connect_TCP ("", "8080"); 469 handle = connect_TCP (NULL, "echo"); 470 handle = connect_TCP ("www.imatix.com", "http"); 471 ---------------------------------------------------------------------[>]-*/ 472 473sock_t 474connect_TCP ( 475 const char *host, /* Host name */ 476 const char *service /* Service name */ 477) 478{ 479 ASSERT (service && *service); 480 return (connect_socket (host, /* We have a host name */ 481 service, /* We have a service name */ 482 "tcp", /* Protocol is TCP */ 483 NULL, /* No prepared address */ 484 3, 0)); /* 3 retries, no waiting */ 485} 486 487 488/* ---------------------------------------------------------------------[<]- 489 Function: connect_UDP 490 491 Synopsis: 492 Creates a UDP socket and connects it to a specified host and service. 493 Returns a socket number or INVALID_SOCKET. In that case you can get 494 the reason for the error by calling connect_error (). This may be: 495 <TABLE> 496 IP_NOSOCKETS Sockets not supported on this system 497 IP_BADHOST Host is not known 498 IP_BADPROTOCOL Cannot understand protocol name 499 IP_SOCKETERROR Cannot open a socket 500 IP_CONNECTERROR Cannot connect socket 501 </TABLE> 502 The host name may be a full name, NULL or "" meaning the current host, 503 or a dotted-decimal number. The service may be a defined service, e.g. 504 "echo", or a port number, specified as an ASCII string. See 505 connect_socket() for details. 506 507 Single-threaded clients may set ip_nonblock to FALSE and block on all 508 read and write operations. They may use select() if they need to be 509 able to time-out during reading/writing. 510 511 Multi-threaded servers should set ip_nonblock to TRUE, and use select() 512 to multiplex socket access. When ip_nonblock is TRUE, connect calls 513 will return immediately, and the server should use select() to wait until 514 the socket is ready for writing. On some systems (early Linux?), the 515 select() call will fail in this situation. If you compile with 516 -DBLOCKING_CONNECT, connects are done synchronously in all cases. 517 518 Examples: 519 sock_t handle; 520 handle = connect_UDP ("", "7"); 521 handle = connect_UDP (NULL, "echo"); 522 handle = connect_UDP ("imatix.com", "echo"); 523 ---------------------------------------------------------------------[>]-*/ 524 525sock_t 526connect_UDP ( 527 const char *host, /* Host name */ 528 const char *service /* Service name */ 529) 530{ 531 ASSERT (service && *service); 532 return (connect_socket (host, /* We have a host name */ 533 service, /* We have a service name */ 534 "udp", /* Protocol is UDP */ 535 NULL, /* No prepared address */ 536 3, 0)); /* 3 retries, no waiting */ 537} 538 539 540/* ---------------------------------------------------------------------[<]- 541 Function: connect_TCP_fast 542 543 Synopsis: Creates a TCP socket and connects it to a specified host/port 544 address. Returns a socket number or INVALID_SOCKET. In that case you 545 can get the reason for the error by calling connect_error (). This may 546 be: 547 <TABLE> 548 IP_NOSOCKETS Sockets not supported on this system 549 IP_BADHOST Host is not known 550 IP_BADPROTOCOL Cannot understand protocol name 551 IP_SOCKETERROR Cannot open a socket 552 IP_CONNECTERROR Cannot connect socket 553 </TABLE> 554 This function is faster, if you know the host system address and port, 555 than connect_TCP() because no translation is needed. 556 You can get the host/address structure by calling address_end_point() 557 or get_peer_addr(). See connect_socket() for details. 558 ---------------------------------------------------------------------[>]-*/ 559 560sock_t 561connect_TCP_fast ( 562 const struct sockaddr_in *sin /* Socket address structure */ 563) 564{ 565 ASSERT (sin); 566 return (connect_socket (NULL, /* No host name */ 567 NULL, /* No service name */ 568 "tcp", /* Protocol is TCP */ 569 sin, /* We have a prepared address */ 570 1, 0)); /* 1 retry, no waiting */ 571} 572 573 574/* ---------------------------------------------------------------------[<]- 575 Function: connect_UDP_fast 576 577 Synopsis: 578 Creates a UDP socket and connects it to a specified host/port address. 579 Returns a socket number or INVALID_SOCKET. In that case you can get 580 the reason for the error by calling connect_error (). This may be: 581 <TABLE> 582 IP_NOSOCKETS Sockets not supported on this system 583 IP_BADHOST Host is not known 584 IP_BADPROTOCOL Cannot understand protocol name 585 IP_SOCKETERROR Cannot open a socket 586 IP_CONNECTERROR Cannot connect socket 587 </TABLE> 588 This function is faster, if you know the host system address and port, 589 than connect_UDP() because no translation is needed. 590 You can get the host/address structure by calling address_end_point() 591 or get_peer_addr(). See connect_socket() for details. 592 ---------------------------------------------------------------------[>]-*/ 593 594sock_t 595connect_UDP_fast ( 596 const struct sockaddr_in *sin /* Socket address structure */ 597) 598{ 599 ASSERT (sin); 600 return (connect_socket (NULL, /* No host name */ 601 NULL, /* No service name */ 602 "udp", /* Protocol is UDP */ 603 sin, /* We have a prepared address */ 604 1, 0)); /* 1 retry, no waiting */ 605} 606 607 608/* ---------------------------------------------------------------------[<]- 609 Function: connect_socket 610 611 Synopsis: 612 Makes a connection to a remote TCP or UDP port. This allows a client 613 program to start sending information to a server. Used by the 614 connect_TCP and connect_UDP functions. Returns a socket number or 615 INVALID_SOCKET. If it returns INVALID_SOCKET, you can get the reason 616 for the error by calling connect_error (). This may be one of: 617 <TABLE> 618 IP_NOSOCKETS Sockets not supported on this system 619 IP_BADHOST Host is not known 620 IP_BADPROTOCOL Cannot understand protocol name 621 IP_SOCKETERROR Cannot open a socket 622 IP_CONNECTERROR Cannot connect socket 623 </TABLE> 624 Always blocks until the connection has been made; i.e. when this 625 function returns you can start to read and write on the socket. 626 627 The host name may be a full name, NULL or "" meaning the current host, 628 or a dotted-decimal number. The service may be a defined service, e.g. 629 "echo", or a port number, specified as an ASCII string. Alternatively, 630 both these values may be NULL or "", in which case the function uses 631 the host_addr argument to supply an address. If you want to build the 632 host_addr structure yourself, use build_sockaddr(). 633 634 Single-threaded clients may set ip_nonblock to FALSE and block on all 635 read and write operations. They may use select() if they need to be 636 able to time-out during reading/writing. 637 638 Multi-threaded servers should set ip_nonblock to TRUE, and use select() 639 to multiplex socket access. When ip_nonblock is TRUE, connect calls 640 will return immediately, and the server should use select() to wait until 641 the socket is ready for writing. On some systems (early Linux?), the 642 select() call will fail in this situation. If you compile with 643 -DBLOCKING_CONNECT, connects are done synchronously in all cases. 644 645 Examples: 646 struct sockaddr_in 647 host_addr; 648 sock_t 649 handle; 650 build_sockaddr (&host_addr, 32_bit_host, 16_bit_port); 651 handle = connect_socket (NULL, NULL, "tcp", &host_addr, 3, 0); 652 ---------------------------------------------------------------------[>]-*/ 653 654sock_t 655connect_socket ( 656 const char *host, /* Name of host, "" = localhost */ 657 const char *service, /* Service name or port as string */ 658 const char *protocol, /* Protocol "tcp" or "udp" */ 659 const struct sockaddr_in *host_addr, /* Socket address structure */ 660 int retries_left, /* Max. number of retries */ 661 int retry_delay /* Delay between retries */ 662) 663{ 664#if (defined (DOES_SOCKETS)) 665 struct sockaddr_in 666 sin; /* Internet end-point address */ 667 sock_t 668 handle = 0; /* Created socket */ 669 int 670 rc; /* Return code from call */ 671 Bool 672 old_nonblock; /* Create non-blocking sockets */ 673 674 connect_error_value = IP_NOERROR; /* Assume no errors */ 675 676 /* Format sockaddr_in port and hostname, and quit if that failed */ 677 if (service && strused (service)) 678 { 679 ASSERT (protocol && *protocol); 680 if (address_end_point (host, service, protocol, &sin)) 681 return (INVALID_SOCKET); 682 } 683 else 684 { 685 ASSERT (host_addr); 686 sin = *host_addr; /* Fast connect requested */ 687 } 688 /* Connect socket and maybe retry a few times... */ 689 old_nonblock = ip_nonblock; 690# if (defined (BLOCKING_CONNECT)) 691 ip_nonblock = FALSE; /* Block on this socket */ 692# endif 693 694 while (retries_left) 695 { 696 handle = create_socket (protocol); 697 if (handle == INVALID_SOCKET) /* Unable to open a socket */ 698 { 699 ip_nonblock = old_nonblock; 700 return (INVALID_SOCKET); 701 } 702 rc = connect ((SOCKET) handle, (struct sockaddr *) &sin, sizeof (sin)); 703 if (rc == 0) 704 break; /* Connected okay */ 705 else 706 { 707# if (defined (__WINDOWS__)) 708 if (WSAGetLastError () == WSAEWOULDBLOCK) 709# else 710 if (errno == EINPROGRESS) 711# endif 712 break; /* Still connecting, but okay */ 713 } 714 /* Retry if we have any attempts left */ 715 close_socket (handle); 716 if (--retries_left == 0) /* Connection failed */ 717 { 718 connect_error_value = IP_CONNECTERROR; 719 ip_nonblock = old_nonblock; 720 return (INVALID_SOCKET); 721 } 722 sleep (retry_delay); 723 } 724 ip_nonblock = old_nonblock; 725 prepare_socket (handle); /* Set final blocking mode */ 726 return (handle); 727 728#elif (defined (FAKE_SOCKETS)) 729 return (1); /* Return dummy handle */ 730 731#else 732 connect_error_value = IP_NOSOCKETS; 733 return (INVALID_SOCKET); /* Sockets not supported */ 734#endif 735} 736 737 738/* ---------------------------------------------------------------------[<]- 739 Function: connect_to_peer 740 741 Synopsis: 742 Connects an unconnected TCP or UDP socket to a peer specified by a 743 sockaddr structure. Returns 0 if the connection succeeded, or 744 SOCKET_ERROR if there was a problem. In the latter case you can 745 get the reason for the error by calling sockmsg(). 746 ---------------------------------------------------------------------[>]-*/ 747 748int 749connect_to_peer ( 750 sock_t handle, /* Socket to connect */ 751 const struct sockaddr_in *sin /* Socket address structure */ 752) 753{ 754#if (defined (DOES_SOCKETS)) 755 int 756 rc; /* Return code from call */ 757 Bool 758 old_nonblock; /* Create non-blocking sockets */ 759 760 ASSERT (sin); 761 old_nonblock = ip_nonblock; 762# if (defined (BLOCKING_CONNECT)) 763 ip_nonblock = FALSE; /* Block on this socket */ 764# endif 765 766 rc = connect ((SOCKET) handle, (struct sockaddr *) sin, sizeof (*sin)); 767 768 ip_nonblock = old_nonblock; 769 prepare_socket (handle); /* Set final blocking mode */ 770 771# if (defined (__WINDOWS__)) 772 return (win_error (rc)); 773# else 774 return (rc); 775# endif 776 777#else 778 connect_error_value = IP_NOSOCKETS; 779 return ((int) SOCKET_ERROR); /* Sockets not supported */ 780#endif 781} 782 783 784/* ---------------------------------------------------------------------[<]- 785 Function: address_end_point 786 787 Synopsis: 788 Formats an address block (struct sockaddr_in) for the specified host 789 and service (port) information. Returns 0 if okay, SOCKET_ERROR if 790 there was an error, in which case you can call connect_error () to get 791 the reason for the error. This may be one of: 792 <TABLE> 793 IP_NOSOCKETS Sockets not supported on this system 794 IP_BADHOST Host is not known 795 </TABLE> 796 ---------------------------------------------------------------------[>]-*/ 797 798int 799address_end_point ( 800 const char *host, /* Name of host, "" = localhost */ 801 const char *service, /* Service name or port as string */ 802 const char *protocol, /* Protocol "tcp" or "udp" */ 803 struct sockaddr_in *sin /* Block for formatted address */ 804) 805{ 806#if (defined (DOES_SOCKETS)) 807 struct hostent 808 *phe; /* Host information entry */ 809 struct servent 810 *pse; /* Service information entry */ 811 char 812 hostname [MAXHOSTNAMELEN + 1]; /* Name of this system */ 813 int 814 feedback = 0; /* Assume everything works */ 815 816 ASSERT (service && *service); 817 ASSERT (protocol && *protocol); 818 ASSERT (sin); 819 820 connect_error_value = IP_NOERROR; /* Assume no errors */ 821 memset ((void *) sin, 0, sizeof (*sin)); 822 sin-> sin_family = AF_INET; 823 824 /* Map service name to a port number */ 825 pse = getservbyname (service, protocol); 826 if (pse) 827 sin-> sin_port = htons ((short) (ntohs (pse-> s_port))); 828 else 829 sin-> sin_port = htons ((short) (atoi (service))); 830 831 /* Map host name to IP address, allowing for dotted decimal */ 832 if (host && strused (host)) 833 strcpy (hostname, host); 834 else 835 strcpy (hostname, "127.0.0.1"); 836 837 /* Check if it's a valid IP address first */ 838 sin-> sin_addr.s_addr = inet_addr (hostname); 839 if (sin-> sin_addr.s_addr == (unsigned) INADDR_NONE) 840 { 841 /* Not a dotted address -- try to translate the name */ 842 phe = (void *) gethostbyname (hostname); 843 if (phe) 844 memcpy ((void *) &sin-> sin_addr, phe-> h_addr, phe-> h_length); 845 else 846 { /* Cannot map to host */ 847 connect_error_value = IP_BADHOST; 848 feedback = (int) SOCKET_ERROR; 849 } 850 } 851 return (feedback); 852 853#else 854 connect_error_value = IP_NOSOCKETS; 855 return ((int) SOCKET_ERROR); /* Sockets not supported */ 856#endif 857} 858 859 860/* ---------------------------------------------------------------------[<]- 861 Function: build_sockaddr 862 863 Synopsis: 864 Builds a socket address structure from the specified host and port 865 addresses. Does not return any value except the built structure. 866 ---------------------------------------------------------------------[>]-*/ 867 868void 869build_sockaddr ( 870 struct sockaddr_in *sin, /* Socket address structure */ 871 qbyte host, /* 32-bit host address */ 872 dbyte port /* 16-bit port number */ 873) 874{ 875 ASSERT (sin); 876 877 sin-> sin_family = AF_INET; 878 sin-> sin_addr.s_addr = htonl (host); 879 sin-> sin_port = htons (port); 880} 881 882 883/* ---------------------------------------------------------------------[<]- 884 Function: socket_localaddr 885 886 Synopsis: Returns a string containing the local host address for the 887 specified connected socket. The string is formatted as a string 888 "n.n.n.n". Returns the address of a static string or a buffer that 889 is overwritten by each call. If sockets are not supported, or there 890 was an error, returns the loopback address "127.0.0.1". 891 ---------------------------------------------------------------------[>]-*/ 892 893char * 894socket_localaddr ( 895 sock_t handle) 896{ 897#define NTOA_MAX 16 898#if (defined (DOES_SOCKETS)) 899 static char 900 localaddr [NTOA_MAX + 1]; /* xxx.xxx.xxx.xxx */ 901 struct sockaddr_in 902 sin; /* Address of local system */ 903 904 if (get_sock_addr (handle, &sin, NULL, 0)) 905 return ("127.0.0.1"); 906 else 907 { 908 strncpy (localaddr, inet_ntoa (sin.sin_addr), NTOA_MAX); 909 return (localaddr); 910 } 911#else 912 return ("127.0.0.1"); 913#endif 914} 915 916 917/* ---------------------------------------------------------------------[<]- 918 Function: socket_peeraddr 919 920 Synopsis: Returns a string containing the peer host address for the 921 specified connected socket. The string is formatted as a string 922 "n.n.n.n". Returns the address of a static string or a buffer that 923 is overwritten by each call. If sockets are not supported, or there 924 was an error, returns the loopback address "127.0.0.1". 925 ---------------------------------------------------------------------[>]-*/ 926 927char * 928socket_peeraddr ( 929 sock_t handle) 930{ 931#if (defined (DOES_SOCKETS)) 932 static char 933 peeraddr [NTOA_MAX + 1]; /* xxx.xxx.xxx.xxx */ 934 struct sockaddr_in 935 sin; /* Address of peer system */ 936 937 if (get_peer_addr (handle, &sin, NULL, 0)) 938 return ("127.0.0.1"); 939 else 940 { 941 strncpy (peeraddr, inet_ntoa (sin.sin_addr), NTOA_MAX); 942 return (peeraddr); 943 } 944#else 945 return ("127.0.0.1"); 946#endif 947} 948 949 950/* ---------------------------------------------------------------------[<]- 951 Function: socket_nodelay 952 953 Synopsis: Disables Nagle's algorithm for the specified socket; use this 954 when you want to ensure that data is sent outwards as fast as possible, 955 and when you are certain that Nagle's algorithm is causing a slowdown in 956 performance. Recommended for HTTP, but not recommended for telnet. 957 Returns 0 if okay, SOCKET_ERROR if there was a problem. 958 ---------------------------------------------------------------------[>]-*/ 959 960int 961socket_nodelay ( 962 sock_t handle) 963{ 964#if (defined (__WINDOWS__)) 965 int 966 true_value = 1; /* Boolean value for setsockopt() */ 967 968 return (setsockopt ((SOCKET) handle, IPPROTO_TCP, TCP_NODELAY, 969 (char *) &true_value, sizeof (true_value))); 970 971#elif (defined (TCP_NODELAY) && defined (SOL_TCP)) 972 int 973 true_value = 1; /* Boolean value for setsockopt() */ 974 975 return (setsockopt ((SOCKET) handle, SOL_TCP, TCP_NODELAY, 976 (char *) &true_value, sizeof (true_value))); 977#elif (defined (TCP_NODELAY) && defined (IPPROTO_TCP)) 978 int 979 true_value = 1; /* Boolean value for setsockopt() */ 980 981 return (setsockopt ((SOCKET) handle, IPPROTO_TCP, TCP_NODELAY, 982 (char *) &true_value, sizeof (true_value))); 983#else 984 return (0); /* Not applicable to this system */ 985#endif 986} 987 988 989/* ---------------------------------------------------------------------[<]- 990 Function: socket_is_alive 991 992 Synopsis: 993 Returns TRUE if the socket is open. Returns FALSE if the socket is no 994 longer accessible. You can use this function to check that a socket has 995 not been closed by the other party, before doing reading or writing. 996 ---------------------------------------------------------------------[>]-*/ 997 998Bool 999socket_is_alive ( 1000 sock_t handle) 1001{ 1002#if (defined (__UTYPE_BEOS)) 1003 /* BeOS 4.5 does not support the getsockopt() function */ 1004 int 1005 rc; 1006 1007 rc = setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK, 1008 (void *) &ip_nonblock, sizeof (ip_nonblock)); 1009 return (rc == 0); 1010 1011#elif (defined (DOES_SOCKETS)) 1012 int 1013 rc; 1014 1015 rc = socket_error (handle); 1016 if (rc == 0 1017 || rc == EINPROGRESS 1018 || rc == EAGAIN 1019 || rc == EWOULDBLOCK) 1020 return TRUE; 1021 else 1022 return FALSE; 1023#else 1024 return (FALSE); 1025#endif 1026} 1027 1028 1029/* ---------------------------------------------------------------------[<]- 1030 Function: socket_error 1031 1032 Synopsis: Returns an errno value for the socket, or 0 if no error was 1033 outstanding on the socket. This function is useful if you are handling 1034 sockets using the select() function: this may return error indicators 1035 on sockets, without precision on the type of error. This function will 1036 return the precise error number. Errors like EINPROGRESS, EAGAIN, and 1037 EWOULDBLOCK can usually be ignored or handled by retrying. 1038 ---------------------------------------------------------------------[>]-*/ 1039 1040int 1041socket_error ( 1042 sock_t handle) 1043{ 1044#if (defined (DOES_SOCKETS)) 1045# if (defined (__UTYPE_BEOS)) 1046 return (errno); 1047# else 1048 int 1049 socket_error, 1050 rc; 1051 argsize_t 1052 error_size = sizeof (socket_error); 1053 1054 rc = getsockopt ((SOCKET) handle, SOL_SOCKET, SO_ERROR, 1055 (char *) &socket_error, &error_size); 1056 1057 if (rc) 1058 errno = rc; 1059 else 1060 errno = socket_error; 1061 1062 return (errno); 1063# endif 1064#else 1065 return (0); 1066#endif 1067} 1068 1069 1070/* ---------------------------------------------------------------------[<]- 1071 Function: accept_socket 1072 1073 Synopsis: Accepts a connection on a specified master socket. If you 1074 do not want to wait on this call, use select() to poll the socket until 1075 there is an incoming request, then call accept_socket. Returns the 1076 number of the new slave socket, or INVALID_SOCKET if there was an error 1077 on the accept call. You can handle errors as fatal except for EAGAIN 1078 which indicates that the operation would cause a non-blocking socket to 1079 block (treat EWOULDBLOCK in the same way). 1080 ---------------------------------------------------------------------[>]-*/ 1081 1082sock_t 1083accept_socket ( 1084 sock_t master_socket) 1085{ 1086#if (defined (DOES_SOCKETS)) 1087 sock_t 1088 slave_socket; /* Connected slave socket */ 1089 struct sockaddr_in 1090 sin; /* Address of connecting party */ 1091 argsize_t 1092 sin_length; /* Length of address */ 1093 1094 connect_error_value = IP_NOERROR; /* Assume no errors */ 1095 1096 sin_length = (int) sizeof (sin); 1097 slave_socket = accept ((SOCKET) master_socket, 1098 (struct sockaddr *) &sin, &sin_length); 1099 1100 /* On non-Windows systems, accept returns -1 in case of error, which */ 1101 /* is the same as INVALID_SOCKET. */ 1102# if (defined (__WINDOWS__)) 1103 if (slave_socket == INVALID_SOCKET) 1104 { 1105 int sock_errno = WSAGetLastError (); 1106 if (sock_errno == WSAEWOULDBLOCK || sock_errno == WSAEINPROGRESS) 1107 errno = EAGAIN; 1108 } 1109# endif 1110 if (slave_socket != INVALID_SOCKET) 1111 { 1112 prepare_socket (slave_socket); 1113 ip_sockets++; 1114 } 1115 return (slave_socket); 1116#else 1117 connect_error_value = IP_NOSOCKETS; 1118 return (INVALID_SOCKET); /* Sockets not supported */ 1119#endif 1120} 1121 1122 1123/* ---------------------------------------------------------------------[<]- 1124 Function: connect_error 1125 1126 Synopsis: 1127 Returns the last error code from one of the connection functions. For 1128 portability in a multithreaded environment, call immediately after the 1129 call to the connection function. 1130 ---------------------------------------------------------------------[>]-*/ 1131 1132int 1133connect_error (void) 1134{ 1135 return (connect_error_value); 1136} 1137 1138 1139/* ---------------------------------------------------------------------[<]- 1140 Function: get_sock_addr 1141 1142 Synopsis: Builds an address block (struct sockaddr_in) for the local 1143 end of the specified connected socket. Returns 0 if okay, SOCKET_ERROR 1144 if there was an error. If the name argument is not null, looks-up the 1145 host name and returns it. The name is truncated to namesize characters, 1146 including a trailing null character. 1147 ---------------------------------------------------------------------[>]-*/ 1148 1149int 1150get_sock_addr ( 1151 sock_t handle, /* Socket to get address for */ 1152 struct sockaddr_in *sin, /* Block for formatted address */ 1153 char *name, /* Buffer for host name, or NULL */ 1154 int namesize /* Size of host name buffer */ 1155) 1156{ 1157#if (defined (DOES_SOCKETS)) 1158 int 1159 rc; /* Return code from call */ 1160 struct hostent 1161 *phe; /* Host information entry */ 1162 argsize_t 1163 sin_length; /* Length of address */ 1164 1165 ASSERT (sin); 1166 1167 /* Get address for local connected socket */ 1168 sin_length = sizeof (struct sockaddr_in); 1169 1170 rc = getsockname ((SOCKET) handle, (struct sockaddr *) sin, &sin_length); 1171 1172 /* Translate into host name string, only if wanted */ 1173 if (name != NULL && rc == 0) 1174 { 1175 phe = (void *)gethostbyaddr ((char *) &sin-> sin_addr, 1176 sizeof (sin-> sin_addr), AF_INET); 1177 if (phe) 1178 { 1179 strncpy (name, phe-> h_name, namesize); 1180 name [namesize - 1] = '\0'; 1181 } 1182 } 1183# if (defined (__WINDOWS__)) 1184 return (win_error (rc)); 1185# else 1186 return (rc); 1187# endif 1188#else 1189 return ((int) SOCKET_ERROR); /* Sockets not supported */ 1190#endif 1191} 1192 1193 1194/* ---------------------------------------------------------------------[<]- 1195 Function: get_peer_addr 1196 1197 Synopsis: Builds an address block (struct sockaddr_in) for the remote 1198 end of the specified connected socket. Returns 0 if okay, SOCKET_ERROR 1199 if there was an error. If the name argument is not null, looks-up the 1200 host name and returns it. The name is truncated to namesize characters, 1201 including a trailing null character. 1202 ---------------------------------------------------------------------[>]-*/ 1203 1204int 1205get_peer_addr ( 1206 sock_t handle, /* Socket to get address for */ 1207 struct sockaddr_in *sin, /* Block for formatted address */ 1208 char *name, /* Buffer for host name, or NULL */ 1209 int namesize /* Size of host name buffer */ 1210) 1211{ 1212#if (defined (DOES_SOCKETS)) 1213 int 1214 rc; /* Return code from call */ 1215 struct hostent 1216 *phe; /* Host information entry */ 1217 argsize_t 1218 sin_length; /* Length of address */ 1219 1220 ASSERT (sin); 1221 1222 /* Get address for connected socket peer */ 1223 sin_length = sizeof (struct sockaddr_in); 1224 rc = getpeername ((SOCKET) handle, (struct sockaddr *) sin, &sin_length); 1225 1226 /* Translate into host name string, only if wanted */ 1227 if (name != NULL && rc == 0) 1228 { 1229 phe = (void *)gethostbyaddr ((char *) &sin-> sin_addr, 1230 sizeof (sin-> sin_addr), AF_INET); 1231 if (phe) 1232 { 1233 strncpy (name, phe-> h_name, namesize); 1234 name [namesize - 1] = '\0'; 1235 } 1236 } 1237# if (defined (__WINDOWS__)) 1238 return (win_error (rc)); 1239# else 1240 return (rc); 1241# endif 1242#else 1243 return ((int) SOCKET_ERROR); /* Sockets not supported */ 1244#endif 1245} 1246 1247 1248/* ---------------------------------------------------------------------[<]- 1249 Function: read_TCP 1250 1251 Synopsis: 1252 Reads data from the socket. On UNIX, VMS, OS/2, passes through to the 1253 standard read function; some other systems have particular ways of 1254 accessing sockets. If there is an error on the read this function 1255 returns SOCKET_ERROR. You can handle errors (in sockerrno) as fatal except 1256 for EAGAIN which indicates that the operation would cause a non-blocking 1257 socket to block, and EPIPE or ECONNRESET which indicate that the socket 1258 was closed at the other end. Treat EWOULDBLOCK as EAGAIN. 1259 ---------------------------------------------------------------------[>]-*/ 1260 1261int 1262read_TCP ( 1263 sock_t handle, /* Socket handle */ 1264 void *buffer, /* Buffer to receive data */ 1265 size_t length /* Maximum amount of data to read */ 1266) 1267{ 1268#if (defined (DOES_SOCKETS)) 1269# if (defined (__UTYPE_BEOS)) 1270 return (recv ((SOCKET) handle, buffer, length, 0)); 1271 1272# elif (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__)) 1273 return (read ((SOCKET) handle, buffer, length)); 1274 1275# elif (defined (__WINDOWS__)) 1276 int 1277 rc; /* Return code from call */ 1278 1279 ASSERT (buffer); 1280 rc = recv ((SOCKET) handle, buffer, length, 0); 1281 return (win_error (rc)); 1282# else 1283# error "No code for function body." 1284 return ((int) SOCKET_ERROR); /* Sockets not supported */ 1285# endif 1286#else 1287 return ((int) SOCKET_ERROR); /* Sockets not supported */ 1288#endif 1289} 1290 1291 1292#if (defined (__WINDOWS__)) 1293/* ------------------------------------------------------------------------- 1294 * win_error -- internal 1295 * 1296 * For Winsockets only: fetches real error code and sticks it in errno, 1297 * if the return code from the last call was SOCKET_ERROR. Returns rc. 1298 */ 1299 1300static int 1301win_error (int rc) 1302{ 1303 …
Large files files are truncated, but you can click here to view the full file