1 /* ttt-socket.c - Simple interface for creating sockets.
3 * Copyright © 2005 Carl Worth
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Author: Carl Worth <cworth@cworth.org>
22 #include "ttt-socket.h"
24 #include <netinet/in.h>
27 /* Initialize a TCP/IP address structure with the given host and port.
29 * Lookup for host (e.g. /etc/hosts and DNA) and port (e.g /etc/services)
30 * will be performed if necessary.
32 * A special host value of "0.0.0.0" may be used to prepare a server
33 * socket to bind to all available addresses.
35 * Errors: If any lookup error occurs, this function will not return.
38 _sockaddr_init (struct sockaddr_in *addr,
42 struct hostent *hostent;
43 struct servent *servent;
48 addr->sin_family = AF_INET;
50 hostent = gethostbyname (host);
53 fprintf (stderr, "Error: Lookup failed for host %s: %s\n",
54 host, hstrerror (h_errno));
57 memcpy (&addr->sin_addr.s_addr, hostent->h_addr_list[0],
58 sizeof (addr->sin_addr.s_addr));
60 assert (*port != '\0');
61 port_long = strtol (port, &endptr, 10);
65 if (port_long <= 0 || port_long >= (1 << 16)) {
66 fprintf (stderr, "Error: Port %ld out of range.\n", port_long);
69 port_short = port_long;
70 addr->sin_port = htons (port_short);
73 servent = getservbyname (port, "tcp");
75 fprintf (stderr, "Error: Lookup failed for port %s: %s\n",
76 port, hstrerror (h_errno));
79 addr->sin_port = servent->s_port;
84 _wait_for_connection (int listen_socket)
92 FD_SET (listen_socket, &read_set);
95 num_selected = select (listen_socket + 1,
96 &read_set, NULL, NULL,
99 flags = fcntl (listen_socket, F_GETFL);
101 xfcntl (listen_socket, F_SETFL, flags);
103 connected_socket = accept (listen_socket, 0, 0);
106 flags &= ~O_NONBLOCK;
107 xfcntl (listen_socket, F_SETFL, flags);
109 if (connected_socket != -1)
110 return connected_socket;
112 if (err == EWOULDBLOCK || err == EAGAIN)
115 fprintf (stderr, "Error: accept failed: %s. Aborting.\n",
121 /* Exported: see ttt-socket.h for documentation. */
123 ttt_socket_create_server (const char *host, const char *port)
126 struct sockaddr_in addr;
128 listen_socket = xsocket (PF_INET, SOCK_STREAM, 0);
130 _sockaddr_init (&addr, host, port);
135 setsockopt (listen_socket, SOL_SOCKET,
136 SO_REUSEADDR, (char *) &one, sizeof (int));
140 xbind (listen_socket, (struct sockaddr *) &addr, sizeof (addr));
142 xlisten (listen_socket, SOMAXCONN);
144 return listen_socket;
147 /* Exported: see ttt-socket.h for documentation. */
149 ttt_socket_accept (int listen_socket,
150 ttt_socket_accept_func_t accept,
153 int connected_socket;
155 connected_socket = _wait_for_connection (listen_socket);
157 (accept) (closure, connected_socket);
160 /* Exported: see ttt-socket.h for documentation. */
162 ttt_socket_read (int socket,
170 bytes_read = xread (socket, cbuf, count);
176 /* Exported: see ttt-socket.h for documentation. */
178 ttt_socket_write (int socket,
183 const char *cbuf = buf;
186 written = xwrite (socket, cbuf, count);