PageRenderTime 61ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sflsock.c

https://github.com/gbluma/gsl
C | 2126 lines | 1216 code | 252 blank | 658 comment | 188 complexity | 4a9dbb63d0825e46972cab6827944732 MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause

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

Large files files are truncated, but you can click here to view the full file