summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2020-05-18 02:57:32 +0200
committerGravatar Nikias Bassen2020-05-18 02:57:32 +0200
commit798601d8ff09d4f80a2fd42119112846ea8f050e (patch)
treebcac7a6a8f6a6b4d1da7e8153b84d0813caf6266
parent05d2e6d09674a8f66a57b5d4b2b42a5b758d2054 (diff)
downloadlibimobiledevice-798601d8ff09d4f80a2fd42119112846ea8f050e.tar.gz
libimobiledevice-798601d8ff09d4f80a2fd42119112846ea8f050e.tar.bz2
common: Update socket.c/.h from libusbmuxd
-rw-r--r--common/socket.c235
-rw-r--r--common/socket.h5
2 files changed, 218 insertions, 22 deletions
diff --git a/common/socket.c b/common/socket.c
index 777b23e..cf6e9eb 100644
--- a/common/socket.c
+++ b/common/socket.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * socket.c 2 * socket.c
3 * 3 *
4 * Copyright (C) 2012-2018 Nikias Bassen <nikias@gmx.li> 4 * Copyright (C) 2012-2020 Nikias Bassen <nikias@gmx.li>
5 * Copyright (C) 2012 Martin Szulecki <m.szulecki@libimobiledevice.org> 5 * Copyright (C) 2012 Martin Szulecki <m.szulecki@libimobiledevice.org>
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
@@ -49,6 +49,9 @@ static int wsa_init = 0;
49#define RECV_TIMEOUT 20000 49#define RECV_TIMEOUT 20000
50#define CONNECT_TIMEOUT 5000 50#define CONNECT_TIMEOUT 5000
51 51
52#ifndef EAFNOSUPPORT
53#define EAFNOSUPPORT 102
54#endif
52#ifndef ECONNRESET 55#ifndef ECONNRESET
53#define ECONNRESET 108 56#define ECONNRESET 108
54#endif 57#endif
@@ -63,6 +66,59 @@ void socket_set_verbose(int level)
63 verbose = level; 66 verbose = level;
64} 67}
65 68
69const char *socket_addr_to_string(struct sockaddr *addr, char *addr_out, size_t addr_out_size)
70{
71#ifdef WIN32
72 WSADATA wsa_data;
73 if (!wsa_init) {
74 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
75 fprintf(stderr, "WSAStartup failed!\n");
76 ExitProcess(-1);
77 }
78 wsa_init = 1;
79 }
80 DWORD addr_out_len = addr_out_size;
81 DWORD addrlen = 0;
82
83 if (addr->sa_family == AF_INET) {
84 addrlen = sizeof(struct sockaddr_in);
85 }
86#ifdef AF_INET6
87 else if (addr->sa_family == AF_INET6) {
88 addrlen = sizeof(struct sockaddr_in6);
89 }
90#endif
91 else {
92 errno = EAFNOSUPPORT;
93 return NULL;
94 }
95
96 if (WSAAddressToString(addr, addrlen, NULL, addr_out, &addr_out_len) == 0) {
97 return addr_out;
98 }
99#else
100 const void *addrdata = NULL;
101
102 if (addr->sa_family == AF_INET) {
103 addrdata = &((struct sockaddr_in*)addr)->sin_addr;
104 }
105#ifdef AF_INET6
106 else if (addr->sa_family == AF_INET6) {
107 addrdata = &((struct sockaddr_in6*)addr)->sin6_addr;
108 }
109#endif
110 else {
111 errno = EAFNOSUPPORT;
112 return NULL;
113 }
114
115 if (inet_ntop(addr->sa_family, addrdata, addr_out, addr_out_size)) {
116 return addr_out;
117 }
118#endif
119 return NULL;
120}
121
66#ifndef WIN32 122#ifndef WIN32
67int socket_create_unix(const char *filename) 123int socket_create_unix(const char *filename)
68{ 124{
@@ -161,11 +217,37 @@ int socket_connect_unix(const char *filename)
161 strncpy(name.sun_path, filename, sizeof(name.sun_path)); 217 strncpy(name.sun_path, filename, sizeof(name.sun_path));
162 name.sun_path[sizeof(name.sun_path) - 1] = 0; 218 name.sun_path[sizeof(name.sun_path) - 1] = 0;
163 219
164 if (connect(sfd, (struct sockaddr*)&name, sizeof(name)) < 0) { 220 int flags = fcntl(sfd, F_GETFL, 0);
221 fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
222
223 do {
224 if (connect(sfd, (struct sockaddr*)&name, sizeof(name)) != -1) {
225 break;
226 }
227 if (errno == EINPROGRESS) {
228 fd_set fds;
229 FD_ZERO(&fds);
230 FD_SET(sfd, &fds);
231
232 struct timeval timeout;
233 timeout.tv_sec = CONNECT_TIMEOUT / 1000;
234 timeout.tv_usec = (CONNECT_TIMEOUT - (timeout.tv_sec * 1000)) * 1000;
235 if (select(sfd + 1, NULL, &fds, NULL, &timeout) == 1) {
236 int so_error;
237 socklen_t len = sizeof(so_error);
238 getsockopt(sfd, SOL_SOCKET, SO_ERROR, (void*)&so_error, &len);
239 if (so_error == 0) {
240 break;
241 }
242 }
243 }
165 socket_close(sfd); 244 socket_close(sfd);
245 sfd = -1;
246 } while (0);
247
248 if (sfd < 0) {
166 if (verbose >= 2) 249 if (verbose >= 2)
167 fprintf(stderr, "%s: connect: %s\n", __func__, 250 fprintf(stderr, "%s: connect: %s\n", __func__, strerror(errno));
168 strerror(errno));
169 return -1; 251 return -1;
170 } 252 }
171 253
@@ -228,6 +310,124 @@ int socket_create(uint16_t port)
228 return sfd; 310 return sfd;
229} 311}
230 312
313int socket_connect_addr(struct sockaddr* addr, uint16_t port)
314{
315 int sfd = -1;
316 int yes = 1;
317 int bufsize = 0x20000;
318 int addrlen = 0;
319#ifdef WIN32
320 u_long l_yes = 1;
321 WSADATA wsa_data;
322 if (!wsa_init) {
323 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
324 fprintf(stderr, "WSAStartup failed!\n");
325 ExitProcess(-1);
326 }
327 wsa_init = 1;
328 }
329#endif
330
331 if (addr->sa_family == AF_INET) {
332 struct sockaddr_in* addr_in = (struct sockaddr_in*)addr;
333 addr_in->sin_port = htons(port);
334 addrlen = sizeof(struct sockaddr_in);
335 }
336#ifdef AF_INET6
337 else if (addr->sa_family == AF_INET6) {
338 struct sockaddr_in6* addr_in = (struct sockaddr_in6*)addr;
339 addr_in->sin6_port = htons(port);
340 addrlen = sizeof(struct sockaddr_in6);
341 }
342#endif
343 else {
344 fprintf(stderr, "ERROR: Unsupported address family");
345 return -1;
346 }
347
348 sfd = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
349 if (sfd == -1) {
350 perror("socket()");
351 return -1;
352 }
353
354#ifdef SO_NOSIGPIPE
355 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
356 perror("setsockopt()");
357 socket_close(sfd);
358 return -1;
359 }
360#endif
361
362 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
363 perror("setsockopt()");
364 socket_close(sfd);
365 return -1;
366 }
367
368#ifdef WIN32
369 ioctlsocket(sfd, FIONBIO, &l_yes);
370#else
371 int flags = fcntl(sfd, F_GETFL, 0);
372 fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
373#endif
374
375 do {
376 if (connect(sfd, addr, addrlen) != -1) {
377 break;
378 }
379#ifdef WIN32
380 if (WSAGetLastError() == WSAEWOULDBLOCK)
381#else
382 if (errno == EINPROGRESS)
383#endif
384 {
385 fd_set fds;
386 FD_ZERO(&fds);
387 FD_SET(sfd, &fds);
388
389 struct timeval timeout;
390 timeout.tv_sec = CONNECT_TIMEOUT / 1000;
391 timeout.tv_usec = (CONNECT_TIMEOUT - (timeout.tv_sec * 1000)) * 1000;
392 if (select(sfd + 1, NULL, &fds, NULL, &timeout) == 1) {
393 int so_error;
394 socklen_t len = sizeof(so_error);
395 getsockopt(sfd, SOL_SOCKET, SO_ERROR, (void*)&so_error, &len);
396 if (so_error == 0) {
397 errno = 0;
398 break;
399 }
400 errno = so_error;
401 }
402 }
403 socket_close(sfd);
404 sfd = -1;
405 } while (0);
406
407 if (sfd < 0) {
408 if (verbose >= 2) {
409 char addrtxt[48];
410 socket_addr_to_string(addr, addrtxt, sizeof(addrtxt));
411 fprintf(stderr, "%s: Could not connect to %s port %d\n", __func__, addrtxt, port);
412 }
413 return -1;
414 }
415
416 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)) == -1) {
417 perror("Could not set TCP_NODELAY on socket");
418 }
419
420 if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsize, sizeof(int)) == -1) {
421 perror("Could not set send buffer for socket");
422 }
423
424 if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsize, sizeof(int)) == -1) {
425 perror("Could not set receive buffer for socket");
426 }
427
428 return sfd;
429}
430
231int socket_connect(const char *addr, uint16_t port) 431int socket_connect(const char *addr, uint16_t port)
232{ 432{
233 int sfd = -1; 433 int sfd = -1;
@@ -239,7 +439,6 @@ int socket_connect(const char *addr, uint16_t port)
239 int res; 439 int res;
240#ifdef WIN32 440#ifdef WIN32
241 u_long l_yes = 1; 441 u_long l_yes = 1;
242 u_long l_no = 0;
243 WSADATA wsa_data; 442 WSADATA wsa_data;
244 if (!wsa_init) { 443 if (!wsa_init) {
245 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) { 444 if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
@@ -277,6 +476,14 @@ int socket_connect(const char *addr, uint16_t port)
277 continue; 476 continue;
278 } 477 }
279 478
479#ifdef SO_NOSIGPIPE
480 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
481 perror("setsockopt()");
482 socket_close(sfd);
483 return -1;
484 }
485#endif
486
280 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) { 487 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
281 perror("setsockopt()"); 488 perror("setsockopt()");
282 socket_close(sfd); 489 socket_close(sfd);
@@ -286,7 +493,8 @@ int socket_connect(const char *addr, uint16_t port)
286#ifdef WIN32 493#ifdef WIN32
287 ioctlsocket(sfd, FIONBIO, &l_yes); 494 ioctlsocket(sfd, FIONBIO, &l_yes);
288#else 495#else
289 fcntl(sfd, F_SETFL, O_NONBLOCK); 496 flags = fcntl(sfd, F_GETFL, 0);
497 fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
290#endif 498#endif
291 499
292 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) { 500 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) {
@@ -325,21 +533,6 @@ int socket_connect(const char *addr, uint16_t port)
325 return -1; 533 return -1;
326 } 534 }
327 535
328#ifdef WIN32
329 ioctlsocket(sfd, FIONBIO, &l_no);
330#else
331 flags = fcntl(sfd, F_GETFL, 0);
332 fcntl(sfd, F_SETFL, flags & (~O_NONBLOCK));
333#endif
334
335#ifdef SO_NOSIGPIPE
336 if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
337 perror("setsockopt()");
338 socket_close(sfd);
339 return -1;
340 }
341#endif
342
343 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)) == -1) { 536 if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)) == -1) {
344 perror("Could not set TCP_NODELAY on socket"); 537 perror("Could not set TCP_NODELAY on socket");
345 } 538 }
diff --git a/common/socket.h b/common/socket.h
index e31de6b..38eeddf 100644
--- a/common/socket.h
+++ b/common/socket.h
@@ -1,8 +1,8 @@
1/* 1/*
2 * socket.h 2 * socket.h
3 * 3 *
4 * Copyright (C) 2012-2020 Nikias Bassen <nikias@gmx.li>
4 * Copyright (C) 2012 Martin Szulecki <m.szulecki@libimobiledevice.org> 5 * Copyright (C) 2012 Martin Szulecki <m.szulecki@libimobiledevice.org>
5 * Copyright (C) 2012 Nikias Bassen <nikias@gmx.li>
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
@@ -46,6 +46,7 @@ int socket_create_unix(const char *filename);
46int socket_connect_unix(const char *filename); 46int socket_connect_unix(const char *filename);
47#endif 47#endif
48int socket_create(uint16_t port); 48int socket_create(uint16_t port);
49int socket_connect_addr(struct sockaddr *addr, uint16_t port);
49int socket_connect(const char *addr, uint16_t port); 50int socket_connect(const char *addr, uint16_t port);
50int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout); 51int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout);
51int socket_accept(int fd, uint16_t port); 52int socket_accept(int fd, uint16_t port);
@@ -62,4 +63,6 @@ int socket_send(int fd, void *data, size_t size);
62 63
63void socket_set_verbose(int level); 64void socket_set_verbose(int level);
64 65
66const char *socket_addr_to_string(struct sockaddr *addr, char *addr_out, size_t addr_out_size);
67
65#endif /* SOCKET_SOCKET_H */ 68#endif /* SOCKET_SOCKET_H */