PageRenderTime 110ms CodeModel.GetById 58ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 0ms

/vendors/socket/socket.c

https://github.com/outbred/libimobiledevice-win32
C | 392 lines | 302 code | 52 blank | 38 comment | 51 complexity | 8964894a11489210a42e4f904cd17412 MD5 | raw file
  1/*
  2 * socket.c
  3 *
  4 * Copyright (c) 2012 Martin Szulecki All Rights Reserved.
  5 * Copyright (c) 2012 Nikias Bassen All Rights Reserved.
  6 *
  7 * This library is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU Lesser General Public
  9 * License as published by the Free Software Foundation; either
 10 * version 2.1 of the License, or (at your option) any later version.
 11 * 
 12 * This library is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15 * Lesser General Public License for more details.
 16 * 
 17 * You should have received a copy of the GNU Lesser General Public
 18 * License along with this library; if not, write to the Free Software
 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
 20 */
 21
 22#include <stdio.h>
 23#include <stddef.h>
 24#include <stdlib.h>
 25#include <string.h>
 26#include <unistd.h>
 27#include <errno.h>
 28#include <time.h>
 29#include <sys/stat.h>
 30#ifdef WIN32
 31#include <winsock2.h>
 32#include <windows.h>
 33static int wsa_init = 0;
 34#else
 35#include <sys/socket.h>
 36#include <sys/un.h>
 37#include <netinet/in.h>
 38#include <netdb.h>
 39#include <arpa/inet.h>
 40#endif
 41#include "socket.h"
 42
 43#define RECV_TIMEOUT 20000
 44
 45static int verbose = 0;
 46
 47void socket_set_verbose(int level)
 48{
 49	verbose = level;
 50}
 51
 52#ifndef WIN32
 53int socket_create_unix(const char *filename)
 54{
 55	struct sockaddr_un name;
 56	int sock;
 57	size_t size;
 58
 59	// remove if still present
 60	unlink(filename);
 61
 62	/* Create the socket. */
 63	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
 64	if (sock < 0) {
 65		perror("socket");
 66		return -1;
 67	}
 68
 69	/* Bind a name to the socket. */
 70	name.sun_family = AF_LOCAL;
 71	strncpy(name.sun_path, filename, sizeof(name.sun_path));
 72	name.sun_path[sizeof(name.sun_path) - 1] = '\0';
 73
 74	/* The size of the address is
 75	   the offset of the start of the filename,
 76	   plus its length,
 77	   plus one for the terminating null byte.
 78	   Alternatively you can just do:
 79	   size = SUN_LEN (&name);
 80	 */
 81	size = (offsetof(struct sockaddr_un, sun_path)
 82			+ strlen(name.sun_path) + 1);
 83
 84	if (bind(sock, (struct sockaddr *) &name, size) < 0) {
 85		perror("bind");
 86		socket_close(sock);
 87		return -1;
 88	}
 89
 90	if (listen(sock, 10) < 0) {
 91		perror("listen");
 92		socket_close(sock);
 93		return -1;
 94	}
 95
 96	return sock;
 97}
 98
 99int socket_connect_unix(const char *filename)
100{
101	struct sockaddr_un name;
102	int sfd = -1;
103	size_t size;
104	struct stat fst;
105
106	// check if socket file exists...
107	if (stat(filename, &fst) != 0) {
108		if (verbose >= 2)
109			fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename,
110					strerror(errno));
111		return -1;
112	}
113	// ... and if it is a unix domain socket
114	if (!S_ISSOCK(fst.st_mode)) {
115		if (verbose >= 2)
116			fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__,
117					filename);
118		return -1;
119	}
120	// make a new socket
121	if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
122		if (verbose >= 2)
123			fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
124		return -1;
125	}
126	// and connect to 'filename'
127	name.sun_family = AF_LOCAL;
128	strncpy(name.sun_path, filename, sizeof(name.sun_path));
129	name.sun_path[sizeof(name.sun_path) - 1] = 0;
130
131	size = (offsetof(struct sockaddr_un, sun_path)
132			+ strlen(name.sun_path) + 1);
133
134	if (connect(sfd, (struct sockaddr *) &name, size) < 0) {
135		socket_close(sfd);
136		if (verbose >= 2)
137			fprintf(stderr, "%s: connect: %s\n", __func__,
138					strerror(errno));
139		return -1;
140	}
141
142	return sfd;
143}
144#endif
145
146int socket_create(uint16_t port)
147{
148	int sfd = -1;
149	int yes = 1;
150#ifdef WIN32
151	WSADATA wsa_data;
152	if (!wsa_init) {
153		if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
154			fprintf(stderr, "WSAStartup failed!\n");
155			ExitProcess(-1);
156		}
157		wsa_init = 1;
158	}
159#endif
160	struct sockaddr_in saddr;
161
162	if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
163		perror("socket()");
164		return -1;
165	}
166
167	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
168		perror("setsockopt()");
169		socket_close(sfd);
170		return -1;
171	}
172
173	memset((void *) &saddr, 0, sizeof(saddr));
174	saddr.sin_family = AF_INET;
175	saddr.sin_addr.s_addr = htonl(INADDR_ANY);
176	saddr.sin_port = htons(port);
177
178	if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
179		perror("bind()");
180		socket_close(sfd);
181		return -1;
182	}
183
184	if (listen(sfd, 1) == -1) {
185		perror("listen()");
186		socket_close(sfd);
187		return -1;
188	}
189
190	return sfd;
191}
192
193int socket_connect(const char *addr, uint16_t port)
194{
195	int sfd = -1;
196	int yes = 1;
197	struct hostent *hp;
198	struct sockaddr_in saddr;
199#ifdef WIN32
200	WSADATA wsa_data;
201	if (!wsa_init) {
202		if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
203			fprintf(stderr, "WSAStartup failed!\n");
204			ExitProcess(-1);
205		}
206		wsa_init = 1;
207	}
208#endif
209
210	if (!addr) {
211		errno = EINVAL;
212		return -1;
213	}
214
215	if ((hp = gethostbyname(addr)) == NULL) {
216		if (verbose >= 2)
217			fprintf(stderr, "%s: unknown host '%s'\n", __FUNCTION__, addr);
218		return -1;
219	}
220
221	if (!hp->h_addr) {
222		if (verbose >= 2)
223			fprintf(stderr, "%s: gethostbyname returned NULL address!\n",
224					__FUNCTION__);
225		return -1;
226	}
227
228	if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
229		perror("socket()");
230		return -1;
231	}
232
233	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
234		perror("setsockopt()");
235		socket_close(sfd);
236		return -1;
237	}
238
239	memset((void *) &saddr, 0, sizeof(saddr));
240	saddr.sin_family = AF_INET;
241	saddr.sin_addr.s_addr = *(uint32_t *) hp->h_addr;
242	saddr.sin_port = htons(port);
243
244	if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
245		perror("connect");
246		socket_close(sfd);
247		return -2;
248	}
249
250	return sfd;
251}
252
253int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout)
254{
255	fd_set fds;
256	int sret;
257	int eagain;
258	struct timeval to;
259	struct timeval *pto;
260
261	if (fd <= 0) {
262		if (verbose >= 2)
263			fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
264		return -1;
265	}
266
267	FD_ZERO(&fds);
268	FD_SET(fd, &fds);
269
270	if (timeout > 0) {
271		to.tv_sec = (time_t) (timeout / 1000);
272		to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000);
273		pto = &to;
274	} else {
275		pto = NULL;
276	}
277
278	sret = -1;
279
280	do {
281		eagain = 0;
282		switch (fdm) {
283		case FDM_READ:
284			sret = select(fd + 1, &fds, NULL, NULL, pto);
285			break;
286		case FDM_WRITE:
287			sret = select(fd + 1, NULL, &fds, NULL, pto);
288			break;
289		case FDM_EXCEPT:
290			sret = select(fd + 1, NULL, NULL, &fds, pto);
291			break;
292		default:
293			return -1;
294		}
295
296		if (sret < 0) {
297			switch (errno) {
298			case EINTR:
299				// interrupt signal in select
300				if (verbose >= 2)
301					fprintf(stderr, "%s: EINTR\n", __FUNCTION__);
302				eagain = 1;
303				break;
304			case EAGAIN:
305				if (verbose >= 2)
306					fprintf(stderr, "%s: EAGAIN\n", __FUNCTION__);
307				break;
308			default:
309				if (verbose >= 2)
310					fprintf(stderr, "%s: select failed: %s\n", __FUNCTION__,
311							strerror(errno));
312				return -1;
313			}
314		}
315	} while (eagain);
316
317	return sret;
318}
319
320int socket_accept(int fd, uint16_t port)
321{
322#ifdef WIN32
323	int addr_len;
324#else
325	socklen_t addr_len;
326#endif
327	int result;
328	struct sockaddr_in addr;
329
330	memset(&addr, 0, sizeof(addr));
331	addr.sin_family = AF_INET;
332	addr.sin_addr.s_addr = htonl(INADDR_ANY);
333	addr.sin_port = htons(port);
334
335	addr_len = sizeof(addr);
336	result = accept(fd, (struct sockaddr*)&addr, &addr_len);
337
338	return result;
339}
340
341int socket_shutdown(int fd, int how)
342{
343	return shutdown(fd, how);
344}
345
346int socket_close(int fd) {
347#ifdef WIN32
348	return closesocket(fd);
349#else
350	return close(fd);
351#endif
352}
353
354int socket_receive(int fd, void *data, size_t length)
355{
356	return socket_receive_timeout(fd, data, length, 0, RECV_TIMEOUT);
357}
358
359int socket_peek(int fd, void *data, size_t length)
360{
361	return socket_receive_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
362}
363
364int socket_receive_timeout(int fd, void *data, size_t length, int flags,
365					 unsigned int timeout)
366{
367	int res;
368	int result;
369
370	// check if data is available
371	res = socket_check_fd(fd, FDM_READ, timeout);
372	if (res <= 0) {
373		return res;
374	}
375	// if we get here, there _is_ data available
376	result = recv(fd, (char *)data, length, flags);
377	if (res > 0 && result == 0) {
378		// but this is an error condition
379		if (verbose >= 3)
380			fprintf(stderr, "%s: fd=%d recv returned 0\n", __FUNCTION__, fd);
381		return -EAGAIN;
382	}
383	if (result < 0) {
384		return -errno;
385	}
386	return result;
387}
388
389int socket_send(int fd, void *data, size_t length)
390{
391	return send(fd, (char *)data, length, 0);
392}