PageRenderTime 131ms CodeModel.GetById 102ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/src/libmanos/manos_socket.c

http://github.com/jacksonh/manos
C | 292 lines | 225 code | 67 blank | 0 comment | 33 complexity | 4ddc4ca952e1dac6485f12bbca6da623 MD5 | raw file
  1
  2#include <stdlib.h>
  3#include <stdio.h>
  4#include <unistd.h>
  5#include <fcntl.h>
  6#include <errno.h>
  7#include <string.h>
  8
  9#include <sys/ioctl.h>
 10#include <sys/socket.h>
 11#include <sys/un.h>
 12#include <sys/types.h>
 13
 14#include <arpa/inet.h>
 15
 16#include <netdb.h>
 17#include <netinet/in.h>
 18#include <netinet/tcp.h>
 19
 20#ifdef HAVE_SYS_SENDFILE_H
 21#include <sys/sendfile.h>
 22#endif
 23
 24
 25#include "manos.h"
 26
 27
 28
 29static int
 30setup_socket (int fd)
 31{
 32	int flags = 1;
 33	setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof (flags));
 34
 35	return (fcntl (fd, F_SETFL, O_NONBLOCK) != -1);
 36}
 37
 38static void
 39parse_sockaddr (struct sockaddr_storage *addr, manos_ip_endpoint_t *ep)
 40{
 41	struct sockaddr_in *in4;
 42	struct sockaddr_in6 *in6;
 43
 44	switch (addr->ss_family) {
 45		case AF_INET:
 46			in4 = (struct sockaddr_in*) addr;
 47			ep->port = ntohs (in4->sin_port);
 48			memcpy (ep->address_bytes, &in4->sin_addr.s_addr, sizeof (struct in_addr));
 49			ep->is_ipv4 = 1;
 50			break;
 51
 52		case AF_INET6:
 53			in6 = (struct sockaddr_in6*) addr;
 54			ep->port = ntohs (in6->sin6_port);
 55			memcpy (ep->address_bytes, in6->sin6_addr.s6_addr, sizeof (struct in6_addr));
 56			ep->is_ipv4 = 0;
 57			break;
 58	}
 59}
 60
 61static socklen_t
 62parse_endpoint (manos_ip_endpoint_t *ep, struct sockaddr_storage *addr)
 63{
 64	struct sockaddr_in *in4;
 65	struct sockaddr_in6 *in6;
 66
 67	if (ep->is_ipv4) {
 68		in4 = (struct sockaddr_in*) addr;
 69		in4->sin_family = AF_INET;
 70		in4->sin_port = htons (ep->port);
 71		memcpy (&in4->sin_addr.s_addr, ep->address_bytes, sizeof (struct in_addr));
 72		return sizeof (*in4);
 73	} else {
 74		in6 = (struct sockaddr_in6*) addr;
 75		in6->sin6_family = AF_INET6;
 76		in6->sin6_port = htons (ep->port);
 77		memcpy (in6->sin6_addr.s6_addr, ep->address_bytes, sizeof (struct in6_addr));
 78		return sizeof (*in6);
 79	}
 80}
 81
 82
 83
 84
 85int
 86manos_socket_localname_ip (int fd, manos_ip_endpoint_t *ep, int *err)
 87{
 88	struct sockaddr_storage addr;
 89	socklen_t len;
 90	int result;
 91
 92	len = sizeof (addr);
 93
 94	result = getsockname (fd, (struct sockaddr*) &addr, &len);
 95
 96	parse_sockaddr (&addr, ep);
 97
 98	*err = errno;
 99	return result;
100}
101
102int
103manos_socket_peername_ip (int fd, manos_ip_endpoint_t *ep, int *err)
104{
105	struct sockaddr_storage addr;
106	socklen_t len;
107	int result;
108
109	len = sizeof (addr);
110
111	result = getpeername (fd, (struct sockaddr*) &addr, &len);
112
113	parse_sockaddr (&addr, ep);
114
115	*err = errno;
116	return result;
117}
118
119int
120manos_socket_create (int addressFamily, int protocolFamily, int *err)
121{
122	static int domains[] = { AF_INET, AF_INET6 };
123	static int types[] = { SOCK_STREAM, SOCK_DGRAM };
124	static int protocols[] = { IPPROTO_TCP, IPPROTO_UDP };
125
126	int result = socket (domains[addressFamily], types[protocolFamily], protocols[protocolFamily]);
127
128	if (result > 0 && setup_socket (result) < 0) {
129		*err = errno;
130		close (result);
131		return -1;
132	}
133
134	*err = errno;
135	return result;
136}
137
138int
139manos_socket_bind_ip (int fd, manos_ip_endpoint_t *ep, int *err)
140{
141	struct sockaddr_storage addr;
142	socklen_t len;
143	int result;
144
145	len = parse_endpoint (ep, &addr);
146
147	result = bind (fd, (struct sockaddr*) &addr, len);
148
149	*err = errno;
150	return result;
151}
152
153int
154manos_socket_connect_ip (int fd, manos_ip_endpoint_t *ep, int *err)
155{
156	struct sockaddr_storage addr;
157	socklen_t len;
158	int result;
159
160	len = parse_endpoint (ep, &addr);
161
162	result = connect (fd, (struct sockaddr*) &addr, len);
163	
164	if (result < 0 && errno == EINPROGRESS) {
165		*err = 0;
166		return 0;
167	} else {
168		*err = errno;
169		return result;
170	}
171}
172
173int
174manos_socket_listen (int fd, int backlog, int *err)
175{
176	int result;
177
178	result = listen (fd, backlog);
179	*err = errno;
180	return result;
181}
182
183int
184manos_socket_accept (int fd, manos_ip_endpoint_t *remote, int *err)
185{
186	struct sockaddr_storage addr;
187	socklen_t len = sizeof (struct sockaddr_storage);
188	int result;
189
190	result = accept (fd, (struct sockaddr*) &addr, &len);
191	if (result < 0) {
192		if (errno == EAGAIN || errno == ECONNABORTED) {
193			*err = 0;
194			return -1;
195		}
196		*err = errno;
197		return -1;
198	}
199
200	if (!setup_socket (result)) {
201		*err = errno;
202		close (result);
203		return -1;
204	}
205
206	parse_sockaddr (&addr, remote);
207	
208	return result;
209}
210
211int
212manos_socket_send (int fd, const char *buffer, int offset, int len, int* err)
213{
214	ssize_t rc;
215
216	rc = send (fd, buffer + offset, len, 0);
217
218	if (rc < 0 && (errno == EAGAIN)) {
219		*err = 0;
220	} else {
221		*err = errno;
222	}
223	return rc;
224}
225
226int
227manos_socket_receive (int fd, char* buffer, int len, int *err)
228{
229	int result;
230
231	result = recv (fd, buffer, len, 0);
232
233	if (result < 0 && (errno == EAGAIN)) {
234		*err = 0;
235	} else {
236		*err = errno;
237	}
238	return result;
239}
240
241int
242manos_socket_sendto_ip (int fd, const char *buffer, int offset, int len, manos_ip_endpoint_t *to, int *err)
243{
244	int result;
245	struct sockaddr_storage target;
246	socklen_t slen;
247
248	slen = parse_endpoint (to, &target);
249
250	result = sendto (fd, buffer + offset, len, 0, (struct sockaddr*) &target, slen);
251
252	if (result < 0 && (errno == EAGAIN)) {
253		*err = 0;
254	} else {
255		*err = errno;
256	}
257	return result;
258}
259
260int
261manos_socket_receivefrom_ip (int fd, char* data, int len, manos_ip_endpoint_t *from, int *err)
262{
263	int result;
264	struct sockaddr_storage source;
265	socklen_t slen = sizeof (source);
266
267	result = recvfrom (fd, data, len, 0, (struct sockaddr*) &source, &slen);
268
269	if (result < 0 && (errno == EAGAIN)) {
270		*err = 0;
271		return -1;
272	} else {
273		*err = errno;
274		if (from) {
275			parse_sockaddr (&source, from);
276		}
277		return result;
278	}
279}
280
281int
282manos_socket_close (int fd, int *err)
283{
284	int result = close (fd);
285	*err = errno;
286	return result;
287}
288
289
290
291
292