blob: ef35220f9f5de300ac762668e33204a95498943b [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +020012#ifdef __linux__ /* Recent versions of glibc only define EAI_NODATA, which is an
13 extension to the POSIX standard, if _GNU_SOURCE is defined. */
14# define _GNU_SOURCE 1
15#endif
16
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080017#include "sockets.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018#include <fcntl.h>
19#include <stddef.h>
20#include "qemu_debug.h"
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070021#include "qemu-char.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080022#include <stdlib.h>
23#include <string.h>
24#include "android/utils/path.h"
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +020025#include "android/utils/debug.h"
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070026#include "android/utils/misc.h"
David 'Digit' Turner18fe86e2010-10-19 08:07:11 +020027#include "android/utils/system.h"
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +020028
29#define D(...) VERBOSE_PRINT(socket,__VA_ARGS__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080030
31#ifdef _WIN32
32# define xxWIN32_LEAN_AND_MEAN
33# include <windows.h>
34# include <winsock2.h>
35# include <ws2tcpip.h>
36#else /* !_WIN32 */
37# include <sys/ioctl.h>
38# include <sys/socket.h>
39# include <netinet/in.h>
40# include <netinet/tcp.h>
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +020041# include <netdb.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080042# if HAVE_UNIX_SOCKETS
43# include <sys/un.h>
44# ifndef UNIX_PATH_MAX
45# define UNIX_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
46# endif
47# endif
48#endif /* !_WIN32 */
49
50
51
52/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
53 * easily in QEMU since we use SIGALRM to implement periodic timers
54 */
55#ifdef _WIN32
56# define QSOCKET_CALL(_ret,_cmd) \
57 do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
58#else
59# define QSOCKET_CALL(_ret,_cmd) \
David 'Digit' Turner7410e8a2009-05-20 10:57:56 +020060 do { \
61 errno = 0; \
62 do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
63 } while (0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080064#endif
65
66#ifdef _WIN32
67
68#include <errno.h>
69
70static int winsock_error;
71
72#define WINSOCK_ERRORS_LIST \
73 EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
74 EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
75 EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
76 EE(WSAEINTR,EINTR,"interrupted function call") \
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070077 EE(WSAEALREADY,EALREADY,"operation already in progress") \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080078 EE(WSAEBADF,EBADF,"bad file descriptor") \
79 EE(WSAEACCES,EACCES,"permission denied") \
80 EE(WSAEFAULT,EFAULT,"bad address") \
81 EE(WSAEINVAL,EINVAL,"invalid argument") \
82 EE(WSAEMFILE,EMFILE,"too many opened files") \
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -070083 EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
84 EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080085 EE(WSAEALREADY,EAGAIN,"operation already in progress") \
86 EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
87 EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
88 EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
89 EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
90 EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
91 EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
92 EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
93 EE(WSAENETDOWN,ENETDOWN,"network is down") \
94 EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
95 EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
96 EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
97 EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
98 EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
99 EE(WSAEISCONN,EISCONN,"socket is already connected") \
100 EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
101 EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
102 EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
103 EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
104 EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
105 EE(WSAELOOP,ELOOP,"cannot translate name") \
106 EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
107 EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
108 EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
109
110typedef struct {
111 int winsock;
112 int unix;
113 const char* string;
114} WinsockError;
115
116static const WinsockError _winsock_errors[] = {
117#define EE(w,u,s) { w, u, s },
118 WINSOCK_ERRORS_LIST
119#undef EE
120 { -1, -1, NULL }
121};
122
123/* this function reads the latest winsock error code and updates
124 * errno to a matching value. It also returns the new value of
125 * errno.
126 */
127static int
128_fix_errno( void )
129{
130 const WinsockError* werr = _winsock_errors;
131 int unix = EINVAL; /* generic error code */
132
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700133 winsock_error = WSAGetLastError();
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200134
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800135 for ( ; werr->string != NULL; werr++ ) {
136 if (werr->winsock == winsock_error) {
137 unix = werr->unix;
138 break;
139 }
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200140 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800141 errno = unix;
142 return -1;
143}
144
145static int
146_set_errno( int code )
147{
148 winsock_error = -1;
149 errno = code;
150 return -1;
151}
152
153/* this function returns a string describing the latest Winsock error */
154const char*
155_errno_str(void)
156{
157 const WinsockError* werr = _winsock_errors;
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700158 const char* result = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800159
160 for ( ; werr->string; werr++ ) {
161 if (werr->winsock == winsock_error) {
162 result = werr->string;
163 break;
164 }
165 }
166
David 'Digit' Turnerce0f4b02010-03-25 11:11:29 -0700167 if (result == NULL) {
168 result = tempstr_format(
169 "Unkown socket error (Winsock=0x%08x) errno=%d: %s",
170 winsock_error, errno, strerror(errno));
171 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800172 return result;
173}
174#else
175static int
176_fix_errno( void )
177{
178 return -1;
179}
180
181static int
182_set_errno( int code )
183{
184 errno = code;
185 return -1;
186}
187#endif
188
189/* socket types */
190
191static int
192socket_family_to_bsd( SocketFamily family )
193{
194 switch (family) {
195 case SOCKET_INET: return AF_INET;
196 case SOCKET_IN6: return AF_INET6;
197#if HAVE_UNIX_SOCKETS
198 case SOCKET_UNIX: return AF_LOCAL;
199#endif
200 default: return -1;
201 }
202}
203
204static int
205socket_type_to_bsd( SocketType type )
206{
207 switch (type) {
208 case SOCKET_DGRAM: return SOCK_DGRAM;
209 case SOCKET_STREAM: return SOCK_STREAM;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700210 default: return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800211 }
212}
213
214static SocketType
215socket_type_from_bsd( int type )
216{
217 switch (type) {
218 case SOCK_DGRAM: return SOCKET_DGRAM;
219 case SOCK_STREAM: return SOCKET_STREAM;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700220 default: return (SocketType) SOCKET_UNSPEC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800221 }
222}
223
224#if 0
225static int
226socket_type_check( SocketType type )
227{
228 return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
229}
230#endif
231
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700232typedef union {
233 struct sockaddr sa[1];
234 struct sockaddr_in in[1];
235#if HAVE_IN6_SOCKETS
236 struct sockaddr_in6 in6[1];
237#endif
238#if HAVE_UNIX_SOCKETS
239 struct sockaddr_un un[1];
240#endif
241} sockaddr_storage;
242
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800243/* socket addresses */
244
245void
246sock_address_init_inet( SockAddress* a, uint32_t ip, uint16_t port )
247{
248 a->family = SOCKET_INET;
249 a->u.inet.port = port;
250 a->u.inet.address = ip;
251}
252
253void
254sock_address_init_in6 ( SockAddress* a, const uint8_t* ip6[16], uint16_t port )
255{
256 a->family = SOCKET_IN6;
257 a->u.in6.port = port;
258 memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
259}
260
261void
262sock_address_init_unix( SockAddress* a, const char* path )
263{
264 a->family = SOCKET_UNIX;
265 a->u._unix.path = strdup(path ? path : "");
266 a->u._unix.owner = 1;
267}
268
269void sock_address_done( SockAddress* a )
270{
271 if (a->family == SOCKET_UNIX && a->u._unix.owner) {
272 a->u._unix.owner = 0;
273 free((char*)a->u._unix.path);
274 }
275}
276
277static char*
278format_char( char* buf, char* end, int c )
279{
David 'Digit' Turner0b7cd6c2009-07-10 00:54:05 +0200280 if (buf < end) {
281 if (buf+1 == end) {
282 *buf++ = 0;
283 } else {
284 *buf++ = (char) c;
285 *buf = 0;
286 }
287 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800288 return buf;
289}
290
291static char*
292format_str( char* buf, char* end, const char* str )
293{
294 int len = strlen(str);
295 int avail = end - buf;
296
297 if (len > avail)
298 len = avail;
299
300 memcpy( buf, str, len );
301 buf += len;
302
303 if (buf == end)
304 buf[-1] = 0;
305 else
306 buf[0] = 0;
307
308 return buf;
309}
310
311static char*
312format_unsigned( char* buf, char* end, unsigned val )
313{
314 char temp[16];
315 int nn;
316
317 for ( nn = 0; val != 0; nn++ ) {
318 int rem = val % 10;
319 temp[nn] = '0'+rem;
320 val /= 10;
321 }
322
323 if (nn == 0)
324 temp[nn++] = '0';
325
326 while (nn > 0)
327 buf = format_char(buf, end, temp[--nn]);
328
329 return buf;
330}
331
332static char*
333format_hex( char* buf, char* end, unsigned val, int ndigits )
334{
335 int shift = 4*ndigits;
336 static const char hex[16] = "0123456789abcdef";
337
338 while (shift >= 0) {
339 buf = format_char(buf, end, hex[(val >> shift) & 15]);
340 shift -= 4;
341 }
342 return buf;
343}
344
345static char*
346format_ip4( char* buf, char* end, uint32_t ip )
347{
348 buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
349 buf = format_char( buf, end, '.');
350 buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
351 buf = format_char( buf, end, '.');
352 buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
353 buf = format_char( buf, end, '.');
354 buf = format_unsigned( buf, end, (unsigned)(ip & 255));
355 return buf;
356}
357
358static char*
359format_ip6( char* buf, char* end, const uint8_t* ip6 )
360{
361 int nn;
362 for (nn = 0; nn < 8; nn++) {
363 int val = (ip6[0] << 16) | ip6[1];
364 ip6 += 2;
365 if (nn > 0)
366 buf = format_char(buf, end, ':');
367 if (val == 0)
368 continue;
369 buf = format_hex(buf, end, val, 4);
370 }
371 return buf;
372}
373
374const char*
375sock_address_to_string( const SockAddress* a )
376{
377 static char buf0[MAX_PATH];
David 'Digit' Turner0b7cd6c2009-07-10 00:54:05 +0200378 char *buf = buf0, *end = buf + sizeof(buf0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800379
380 switch (a->family) {
381 case SOCKET_INET:
382 buf = format_ip4( buf, end, a->u.inet.address );
383 buf = format_char( buf, end, ':' );
384 buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
385 break;
386
387 case SOCKET_IN6:
388 buf = format_ip6( buf, end, a->u.in6.address );
389 buf = format_char( buf, end, ':' );
390 buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
391 break;
392
393 case SOCKET_UNIX:
394 buf = format_str( buf, end, a->u._unix.path );
395 break;
396
397 default:
398 return NULL;
399 }
400
401 return buf0;
402}
403
404int
405sock_address_equal( const SockAddress* a, const SockAddress* b )
406{
407 if (a->family != b->family)
408 return 0;
409
410 switch (a->family) {
411 case SOCKET_INET:
412 return (a->u.inet.address == b->u.inet.address &&
413 a->u.inet.port == b->u.inet.port);
414
415 case SOCKET_IN6:
416 return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
417 a->u.in6.port == b->u.in6.port);
418
419 case SOCKET_UNIX:
420 return (!strcmp(a->u._unix.path, b->u._unix.path));
421
422 default:
423 return 0;
424 }
425}
426
427int
428sock_address_get_port( const SockAddress* a )
429{
430 switch (a->family) {
431 case SOCKET_INET:
432 return a->u.inet.port;
433 case SOCKET_IN6:
434 return a->u.in6.port;
435 default:
436 return -1;
437 }
438}
439
440void
441sock_address_set_port( SockAddress* a, uint16_t port )
442{
443 switch (a->family) {
444 case SOCKET_INET:
445 a->u.inet.port = port;
446 break;
447 case SOCKET_IN6:
448 a->u.in6.port = port;
449 break;
450 default:
451 ;
452 }
453}
454
455const char*
456sock_address_get_path( const SockAddress* a )
457{
458 if (a->family == SOCKET_UNIX)
459 return a->u._unix.path;
460 else
461 return NULL;
462}
463
464int
465sock_address_get_ip( const SockAddress* a )
466{
467 if (a->family == SOCKET_INET)
468 return a->u.inet.address;
469
470 return -1;
471}
472
473#if 0
474char*
475bufprint_sock_address( char* p, char* end, const SockAddress* a )
476{
477 switch (a->family) {
478 case SOCKET_INET:
479 {
480 uint32_t ip = a->u.inet.address;
481
482 return bufprint( p, end, "%d.%d.%d.%d:%d",
483 (ip >> 24) & 255, (ip >> 16) & 255,
484 (ip >> 8) & 255, ip & 255,
485 a->u.inet.port );
486 }
487 case SOCKET_IN6:
488 {
489 int nn = 0;
490 const char* column = "";
491 const uint8_t* tab = a->u.in6.address;
492 for (nn = 0; nn < 16; nn += 2) {
493 p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
494 column = ":";
495 }
496 return bufprint(p, end, ":%d", a->u.in6.port);
497 }
498 case SOCKET_UNIX:
499 {
500 return bufprint(p, end, "%s", a->u._unix.path);
501 }
502 default:
503 return p;
504 }
505}
506#endif
507
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700508static int
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200509sock_address_to_bsd( const SockAddress* a, sockaddr_storage* paddress, socklen_t *psize )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800510{
511 switch (a->family) {
512 case SOCKET_INET:
513 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700514 struct sockaddr_in* dst = paddress->in;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800515
516 *psize = sizeof(*dst);
517
518 memset( paddress, 0, *psize );
519
520 dst->sin_family = AF_INET;
521 dst->sin_port = htons(a->u.inet.port);
522 dst->sin_addr.s_addr = htonl(a->u.inet.address);
523 }
524 break;
525
526#if HAVE_IN6_SOCKETS
527 case SOCKET_IN6:
528 {
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700529 struct sockaddr_in6* dst = paddress->in6;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800530
531 *psize = sizeof(*dst);
532
533 memset( paddress, 0, *psize );
534
535 dst->sin6_family = AF_INET6;
536 dst->sin6_port = htons(a->u.in6.port);
537 memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
538 }
539 break;
540#endif /* HAVE_IN6_SOCKETS */
541
542#if HAVE_UNIX_SOCKETS
543 case SOCKET_UNIX:
544 {
545 int slen = strlen(a->u._unix.path);
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700546 struct sockaddr_un* dst = paddress->un;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800547
548 if (slen >= UNIX_PATH_MAX)
549 return -1;
550
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700551 memset( dst, 0, sizeof(*dst) );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800552
553 dst->sun_family = AF_LOCAL;
554 memcpy( dst->sun_path, a->u._unix.path, slen );
555 dst->sun_path[slen] = 0;
556
557 *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
558 }
559 break;
560#endif /* HAVE_UNIX_SOCKETS */
561
562 default:
563 return _set_errno(EINVAL);
564 }
565
566 return 0;
567}
568
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700569static int
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200570sock_address_from_bsd( SockAddress* a, const void* from, size_t fromlen )
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800571{
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200572 switch (((struct sockaddr *)from)->sa_family) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800573 case AF_INET:
574 {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200575 const struct sockaddr_in* src = from;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800576
577 if (fromlen < sizeof(*src))
578 return _set_errno(EINVAL);
579
580 a->family = SOCKET_INET;
581 a->u.inet.port = ntohs(src->sin_port);
582 a->u.inet.address = ntohl(src->sin_addr.s_addr);
583 }
584 break;
585
586#ifdef HAVE_IN6_SOCKETS
587 case AF_INET6:
588 {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200589 const struct sockaddr_in6* src = from;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800590
591 if (fromlen < sizeof(*src))
592 return _set_errno(EINVAL);
593
594 a->family = SOCKET_IN6;
595 a->u.in6.port = ntohs(src->sin6_port);
596 memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
597 }
598 break;
599#endif
600
601#ifdef HAVE_UNIX_SOCKETS
602 case AF_LOCAL:
603 {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200604 const struct sockaddr_un* src = from;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800605 char* end;
606
607 if (fromlen < sizeof(*src))
608 return _set_errno(EINVAL);
609
610 /* check that the path is zero-terminated */
611 end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
612 if (end == NULL)
613 return _set_errno(EINVAL);
614
615 a->family = SOCKET_UNIX;
616 a->u._unix.owner = 1;
617 a->u._unix.path = strdup(src->sun_path);
618 }
619 break;
620#endif
621
622 default:
623 return _set_errno(EINVAL);
624 }
625 return 0;
626}
627
628
629int
630sock_address_init_resolve( SockAddress* a, const char* hostname, uint16_t port, int preferIn6 )
631{
632 struct addrinfo hints[1];
633 struct addrinfo* res;
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200634 int ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800635
636 memset(hints, 0, sizeof(hints));
637 hints->ai_family = preferIn6 ? AF_INET6 : AF_UNSPEC;
638
David Turner669c4792009-04-13 17:58:45 -0700639 ret = getaddrinfo(hostname, NULL, hints, &res);
640 if (ret != 0) {
641 int err;
642
643 switch (ret) {
644 case EAI_AGAIN: /* server is down */
645 case EAI_FAIL: /* server is sick */
646 err = EHOSTDOWN;
647 break;
648
Nick Pellyf5be61d2009-04-24 15:28:40 -0700649#ifdef EAI_NODATA
David Turner669c4792009-04-13 17:58:45 -0700650 case EAI_NODATA:
Nick Pellyf5be61d2009-04-24 15:28:40 -0700651#endif
David Turner669c4792009-04-13 17:58:45 -0700652 case EAI_NONAME:
653 err = ENOENT;
654 break;
655
656 case EAI_MEMORY:
657 err = ENOMEM;
658 break;
659
660 default:
661 err = EINVAL;
662 }
663 return _set_errno(err);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800664 }
665
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200666 /* Parse the returned list of addresses. */
667 {
668 struct addrinfo* res_ipv4 = NULL;
669 struct addrinfo* res_ipv6 = NULL;
670 struct addrinfo* r;
671
672 /* If preferIn6 is false, we stop on the first IPv4 address,
673 * otherwise, we stop on the first IPv6 one
674 */
675 for (r = res; r != NULL; r = r->ai_next) {
676 if (r->ai_family == AF_INET && res_ipv4 == NULL) {
677 res_ipv4 = r;
678 if (!preferIn6)
679 break;
680 }
681 else if (r->ai_family == AF_INET6 && res_ipv6 == NULL) {
682 res_ipv6 = r;
683 if (preferIn6)
684 break;
685 }
686 }
687
688 /* Select the best address in 'r', which will be NULL
689 * if there is no corresponding address.
690 */
691 if (preferIn6) {
692 r = res_ipv6;
693 if (r == NULL)
694 r = res_ipv4;
695 } else {
696 r = res_ipv4;
697 if (r == NULL)
698 r = res_ipv6;
699 }
700
701 if (r == NULL) {
702 ret = _set_errno(ENOENT);
703 goto Exit;
704 }
705
706 /* Convert to a SockAddress */
707 ret = sock_address_from_bsd( a, r->ai_addr, r->ai_addrlen );
708 if (ret < 0)
709 goto Exit;
710 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800711
712 /* need to set the port */
713 switch (a->family) {
714 case SOCKET_INET: a->u.inet.port = port; break;
715 case SOCKET_IN6: a->u.in6.port = port; break;
716 default: ;
717 }
718
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +0200719Exit:
720 freeaddrinfo(res);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800721 return ret;
722}
723
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700724/* The Winsock headers for mingw lack some definitions */
725#ifndef AI_ADDRCONFIG
726# define AI_ADDRCONFIG 0
727#endif
728
729SockAddress**
730sock_address_list_create( const char* hostname,
731 const char* port,
732 unsigned flags )
733{
734 SockAddress** list = NULL;
735 SockAddress* addr;
736 int nn, count, ret;
737 struct addrinfo ai, *res, *e;
738
739 memset(&ai, 0, sizeof(ai));
740 ai.ai_flags |= AI_ADDRCONFIG;
741 ai.ai_family = PF_UNSPEC;
742
743 if (flags & SOCKET_LIST_FORCE_INET)
744 ai.ai_family = PF_INET;
745 else if (flags & SOCKET_LIST_FORCE_IN6)
746 ai.ai_family = PF_INET6;
747
748 if (flags & SOCKET_LIST_PASSIVE)
749 ai.ai_flags |= AI_PASSIVE;
750 else
751 ai.ai_flags |= AI_CANONNAME;
752
753 while (1) {
754 struct addrinfo hints = ai;
755
756 ret = getaddrinfo(hostname, port, &hints, &res);
757 if (ret == 0)
758 break;
759
760 switch (ret) {
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200761#ifdef EAI_ADDRFAMILY
762 case EAI_ADDRFAMILY:
763#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700764 case EAI_NODATA:
765 _set_errno(ENOENT);
766 break;
767 case EAI_FAMILY:
768 _set_errno(EAFNOSUPPORT);
769 break;
770 case EAI_AGAIN:
771 _set_errno(EAGAIN);
772 break;
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200773#ifdef EAI_SYSTEM
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700774 case EAI_SYSTEM:
775 if (errno == EINTR)
776 continue;
777 break;
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +0200778#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700779 default:
780 _set_errno(EINVAL);
781 }
782 return NULL;
783 }
784
785 /* allocate result list */
786 for (count = 0, e = res; e != NULL; e = e->ai_next)
787 count += 1;
788
David 'Digit' Turner18fe86e2010-10-19 08:07:11 +0200789 AARRAY_NEW(list, count+1);
790 AARRAY_NEW(addr, count);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700791
792 for (nn = 0, e = res; e != NULL; e = e->ai_next) {
793
794 ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
795 if (ret < 0)
796 continue;
797
798 list[nn++] = addr++;
799 }
800 list[nn] = NULL;
801 freeaddrinfo(res);
802 return list;
803}
804
Vladimir Chtchetkine50eef012010-11-24 08:30:47 -0800805SockAddress**
806sock_address_list_create2(const char* host_and_port, unsigned flags )
807{
808 char host_name[512];
809 const char* actual_host_name = "localhost";
810 // Parse host and port name.
811 const char* port_name = strchr(host_and_port, ':');
812 if (port_name != NULL) {
813 int to_copy = MIN(sizeof(host_name)-1, port_name - host_and_port);
814 if (to_copy != 0) {
815 memcpy(host_name, host_and_port, to_copy);
816 host_name[to_copy] = '\0';
817 actual_host_name = host_name;
818 port_name++;
819 } else {
820 return NULL;
821 }
822 } else {
823 port_name = host_and_port;
824 }
825 // Make sure that port_name is not empty.
826 if (port_name[0] == '\0') {
827 return NULL;
828 }
829 return sock_address_list_create(actual_host_name, port_name, flags);
830}
831
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700832void
833sock_address_list_free( SockAddress** list )
834{
835 int nn;
836 SockAddress* addr;
837
838 if (list == NULL)
839 return;
840
841 addr = list[0];
842 for (nn = 0; list[nn] != NULL; nn++) {
843 sock_address_done(list[nn]);
844 list[nn] = NULL;
845 }
David 'Digit' Turner18fe86e2010-10-19 08:07:11 +0200846 AFREE(addr);
847 AFREE(list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700848}
849
850int
851sock_address_get_numeric_info( SockAddress* a,
852 char* host,
853 size_t hostlen,
854 char* serv,
855 size_t servlen )
856{
857 struct sockaddr* saddr;
858 socklen_t slen;
859 int ret;
860
861 switch (a->family) {
862 case SOCKET_INET:
863 saddr = (struct sockaddr*) &a->u.inet.address;
864 slen = sizeof(a->u.inet.address);
865 break;
866
867#if HAVE_IN6_SOCKET
868 case SOCKET_IN6:
869 saddr = (struct sockaddr*) &a->u.in6.address;
870 slen = sizeof(a->u.in6.address);
871 break;
872#endif
873 default:
874 return _set_errno(EINVAL);
875 }
876
877 ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
878 NI_NUMERICHOST | NI_NUMERICSERV );
879
880 switch (ret) {
881 case 0:
882 break;
883 case EAI_AGAIN:
884 ret = EAGAIN;
885 break;
886 default:
887 ret = EINVAL;
888 }
889 return ret;
890}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800891
892int
893socket_create( SocketFamily family, SocketType type )
894{
895 int ret;
896 int sfamily = socket_family_to_bsd(family);
897 int stype = socket_type_to_bsd(type);
898
899 if (sfamily < 0 || stype < 0) {
900 return _set_errno(EINVAL);
901 }
902
903 QSOCKET_CALL(ret, socket(sfamily, stype, 0));
904 if (ret < 0)
905 return _fix_errno();
906
907 return ret;
908}
909
910
911int
912socket_create_inet( SocketType type )
913{
914 return socket_create( SOCKET_INET, type );
915}
916
917#if HAVE_IN6_SOCKETS
918int
919socket_create_in6 ( SocketType type )
920{
921 return socket_create( SOCKET_IN6, type );
922}
923#endif
924
925#if HAVE_UNIX_SOCKETS
926int
927socket_create_unix( SocketType type )
928{
929 return socket_create( SOCKET_UNIX, type );
930}
931#endif
932
933int socket_can_read(int fd)
934{
935#ifdef _WIN32
936 unsigned long opt;
937
938 if (ioctlsocket(fd, FIONREAD, &opt) < 0)
939 return 0;
940
941 return opt;
942#else
943 int opt;
944
945 if (ioctl(fd, FIONREAD, &opt) < 0)
946 return 0;
947
948 return opt;
949#endif
950}
951
952#define SOCKET_CALL(cmd) \
953 int ret; \
954 QSOCKET_CALL(ret, (cmd)); \
955 if (ret < 0) \
956 return _fix_errno(); \
957 return ret; \
958
959int
960socket_send(int fd, const void* buf, int buflen)
961{
962 SOCKET_CALL(send(fd, buf, buflen, 0))
963}
964
965int
966socket_send_oob( int fd, const void* buf, int buflen )
967{
968 SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
969}
970
971int
972socket_sendto(int fd, const void* buf, int buflen, const SockAddress* to)
973{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700974 sockaddr_storage sa;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800975 socklen_t salen;
976
977 if (sock_address_to_bsd(to, &sa, &salen) < 0)
978 return -1;
979
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700980 SOCKET_CALL(sendto(fd, buf, buflen, 0, sa.sa, salen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800981}
982
983int
984socket_recv(int fd, void* buf, int len)
985{
986 SOCKET_CALL(recv(fd, buf, len, 0));
987}
988
989int
990socket_recvfrom(int fd, void* buf, int len, SockAddress* from)
991{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700992 sockaddr_storage sa;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800993 socklen_t salen = sizeof(sa);
994 int ret;
995
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -0700996 QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,sa.sa,&salen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800997 if (ret < 0)
998 return _fix_errno();
999
1000 if (sock_address_from_bsd(from, &sa, salen) < 0)
1001 return -1;
1002
1003 return ret;
1004}
1005
1006int
1007socket_connect( int fd, const SockAddress* address )
1008{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001009 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001010 socklen_t addrlen;
1011
1012 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
1013 return -1;
1014
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001015 SOCKET_CALL(connect(fd,addr.sa,addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001016}
1017
1018int
1019socket_bind( int fd, const SockAddress* address )
1020{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001021 sockaddr_storage addr;
1022 socklen_t addrlen;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001023
1024 if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
1025 return -1;
1026
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001027 SOCKET_CALL(bind(fd, addr.sa, addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001028}
1029
1030int
1031socket_get_address( int fd, SockAddress* address )
1032{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001033 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001034 socklen_t addrlen = sizeof(addr);
1035 int ret;
1036
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001037 QSOCKET_CALL(ret, getsockname(fd, addr.sa, &addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001038 if (ret < 0)
1039 return _fix_errno();
1040
1041 return sock_address_from_bsd(address, &addr, addrlen);
1042}
1043
1044int
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001045socket_get_peer_address( int fd, SockAddress* address )
1046{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001047 sockaddr_storage addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001048 socklen_t addrlen = sizeof(addr);
1049 int ret;
1050
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001051 QSOCKET_CALL(ret, getpeername(fd, addr.sa, &addrlen));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001052 if (ret < 0)
1053 return _fix_errno();
1054
1055 return sock_address_from_bsd(address, &addr, addrlen);
1056}
1057
1058int
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001059socket_listen( int fd, int backlog )
1060{
1061 SOCKET_CALL(listen(fd, backlog));
1062}
1063
1064int
1065socket_accept( int fd, SockAddress* address )
1066{
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001067 sockaddr_storage addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001068 socklen_t addrlen = sizeof(addr);
1069 int ret;
1070
David 'Digit' Turnerb6f4df82010-08-25 09:03:09 -07001071 QSOCKET_CALL(ret, accept(fd, addr.sa, &addrlen));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001072 if (ret < 0)
1073 return _fix_errno();
1074
1075 if (address) {
1076 if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
1077 socket_close(ret);
1078 return -1;
1079 }
1080 }
1081 return ret;
1082}
1083
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001084static int
1085socket_getoption(int fd, int domain, int option, int defaut)
1086{
1087 int ret;
1088 while (1) {
1089#ifdef _WIN32
1090 DWORD opt = (DWORD)-1;
1091#else
1092 int opt = -1;
1093#endif
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001094 socklen_t optlen = sizeof(opt);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001095 ret = getsockopt(fd, domain, option, (char*)&opt, &optlen);
1096 if (ret == 0)
1097 return (int)opt;
1098 if (errno != EINTR)
1099 return defaut;
1100 }
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001101#undef OPT_CAST
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001102}
1103
1104
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001105SocketType socket_get_type(int fd)
1106{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001107 int so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
1108 return socket_type_from_bsd(so_type);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001109}
1110
1111int socket_set_nonblock(int fd)
1112{
1113#ifdef _WIN32
1114 unsigned long opt = 1;
1115 return ioctlsocket(fd, FIONBIO, &opt);
1116#else
1117 int flags = fcntl(fd, F_GETFL);
1118 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
1119#endif
1120}
1121
1122int socket_set_blocking(int fd)
1123{
1124#ifdef _WIN32
1125 unsigned long opt = 0;
1126 return ioctlsocket(fd, FIONBIO, &opt);
1127#else
1128 int flags = fcntl(fd, F_GETFL);
1129 return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
1130#endif
1131}
1132
1133static int
1134socket_setoption(int fd, int domain, int option, int _flag)
1135{
1136#ifdef _WIN32
1137 DWORD flag = (DWORD) _flag;
1138#else
1139 int flag = _flag;
1140#endif
1141 return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
1142}
1143
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001144int socket_set_xreuseaddr(int fd)
1145{
1146#ifdef _WIN32
1147 /* on Windows, SO_REUSEADDR is used to indicate that several programs can
1148 * bind to the same port. this is completely different from the Unix
1149 * semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
1150 * this.
1151 */
1152 return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
1153#else
1154 return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
1155#endif
1156}
1157
1158
1159int socket_set_oobinline(int fd)
1160{
1161 return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
1162}
1163
1164
1165int socket_set_nodelay(int fd)
1166{
1167 return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
1168}
1169
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001170int socket_set_ipv6only(int fd)
1171{
1172/* IPV6_ONLY is only supported since Vista on Windows,
1173 * and the Mingw headers lack its definition anyway.
1174 */
1175#if defined(_WIN32) && !defined(IPV6_V6ONLY)
1176 return 0;
1177#else
1178 return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001179#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001180}
1181
1182
1183int socket_get_error(int fd)
1184{
1185 return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
1186}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001187
1188#ifdef _WIN32
1189#include <stdlib.h>
1190
1191static void socket_cleanup(void)
1192{
1193 WSACleanup();
1194}
1195
1196int socket_init(void)
1197{
1198 WSADATA Data;
1199 int ret, err;
1200
1201 ret = WSAStartup(MAKEWORD(2,2), &Data);
1202 if (ret != 0) {
1203 err = WSAGetLastError();
1204 return -1;
1205 }
1206 atexit(socket_cleanup);
1207 return 0;
1208}
1209
1210#else /* !_WIN32 */
1211
1212int socket_init(void)
1213{
1214 return 0; /* nothing to do on Unix */
1215}
1216
1217#endif /* !_WIN32 */
1218
1219#ifdef _WIN32
1220
1221static void
1222socket_close_handler( void* _fd )
1223{
1224 int fd = (int)_fd;
1225 int ret;
1226 char buff[64];
1227
1228 /* we want to drain the read side of the socket before closing it */
1229 do {
1230 ret = recv( fd, buff, sizeof(buff), 0 );
1231 } while (ret < 0 && WSAGetLastError() == WSAEINTR);
1232
1233 if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
1234 return;
1235
1236 qemu_set_fd_handler( fd, NULL, NULL, NULL );
1237 closesocket( fd );
1238}
1239
1240void
1241socket_close( int fd )
1242{
1243 int old_errno = errno;
1244
1245 shutdown( fd, SD_BOTH );
1246 /* we want to drain the socket before closing it */
1247 qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
1248
1249 errno = old_errno;
1250}
1251
1252#else /* !_WIN32 */
1253
1254#include <unistd.h>
1255
1256void
1257socket_close( int fd )
1258{
1259 int old_errno = errno;
1260
1261 shutdown( fd, SHUT_RDWR );
1262 close( fd );
1263
1264 errno = old_errno;
1265}
1266
1267#endif /* !_WIN32 */
1268
1269
1270static int
1271socket_bind_server( int s, const SockAddress* to, SocketType type )
1272{
1273 socket_set_xreuseaddr(s);
1274
1275 if (socket_bind(s, to) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001276 D("could not bind server socket address %s: %s",
1277 sock_address_to_string(to), errno_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001278 goto FAIL;
1279 }
1280
1281 if (type == SOCKET_STREAM) {
1282 if (socket_listen(s, 4) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001283 D("could not listen server socket %s: %s",
1284 sock_address_to_string(to), errno_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001285 goto FAIL;
1286 }
1287 }
1288 return s;
1289
1290FAIL:
1291 socket_close(s);
1292 return -1;
1293}
1294
1295
1296static int
1297socket_connect_client( int s, const SockAddress* to )
1298{
1299 if (socket_connect(s, to) < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001300 D( "could not connect client socket to %s: %s\n",
1301 sock_address_to_string(to), errno_str );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001302 socket_close(s);
1303 return -1;
1304 }
1305
1306 socket_set_nonblock( s );
1307 return s;
1308}
1309
1310
1311static int
1312socket_in_server( int address, int port, SocketType type )
1313{
1314 SockAddress addr;
1315 int s;
1316
1317 sock_address_init_inet( &addr, address, port );
1318 s = socket_create_inet( type );
1319 if (s < 0)
1320 return -1;
1321
1322 return socket_bind_server( s, &addr, type );
1323}
1324
1325
1326static int
1327socket_in_client( SockAddress* to, SocketType type )
1328{
1329 int s;
1330
1331 s = socket_create_inet( type );
1332 if (s < 0) return -1;
1333
1334 return socket_connect_client( s, to );
1335}
1336
1337
1338int
1339socket_loopback_server( int port, SocketType type )
1340{
1341 return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
1342}
1343
1344int
1345socket_loopback_client( int port, SocketType type )
1346{
1347 SockAddress addr;
1348
1349 sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
1350 return socket_in_client( &addr, type );
1351}
1352
1353
1354int
1355socket_network_client( const char* host, int port, SocketType type )
1356{
1357 SockAddress addr;
1358
1359 if (sock_address_init_resolve( &addr, host, port, 0) < 0)
1360 return -1;
1361
1362 return socket_in_client( &addr, type );
1363}
1364
1365
1366int
1367socket_anyaddr_server( int port, SocketType type )
1368{
1369 return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
1370}
1371
1372int
1373socket_accept_any( int server_fd )
1374{
1375 int fd;
1376
1377 QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
1378 if (fd < 0) {
David 'Digit' Turner3e7a9282009-05-14 11:25:52 +02001379 D( "could not accept client connection from fd %d: %s",
1380 server_fd, errno_str );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001381 return -1;
1382 }
1383
1384 /* set to non-blocking */
1385 socket_set_nonblock( fd );
1386 return fd;
1387}
1388
1389
1390#if HAVE_UNIX_SOCKETS
1391
1392int
1393socket_unix_server( const char* name, SocketType type )
1394{
1395 SockAddress addr;
1396 int s, ret;
1397
1398 s = socket_create_unix( type );
1399 if (s < 0)
1400 return -1;
1401
1402 sock_address_init_unix( &addr, name );
1403
1404 do {
1405 ret = unlink( name );
1406 } while (ret < 0 && errno == EINTR);
1407
1408 ret = socket_bind_server( s, &addr, type );
1409
1410 sock_address_done( &addr );
1411 return ret;
1412}
1413
1414int
1415socket_unix_client( const char* name, SocketType type )
1416{
1417 SockAddress addr;
1418 int s, ret;
1419
1420 s = socket_create_unix(type);
1421 if (s < 0)
1422 return -1;
1423
1424 sock_address_init_unix( &addr, name );
1425
1426 ret = socket_connect_client( s, &addr );
1427
1428 sock_address_done( &addr );
1429 return ret;
1430}
1431
1432#endif /* HAVE_UNIX_SOCKETS */
1433
1434
1435
1436int
1437socket_pair(int *fd1, int *fd2)
1438{
1439#ifndef _WIN32
1440 int fds[2];
1441 int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
1442
1443 if (!ret) {
1444 socket_set_nonblock(fds[0]);
1445 socket_set_nonblock(fds[1]);
1446 *fd1 = fds[0];
1447 *fd2 = fds[1];
1448 }
1449 return ret;
1450#else /* _WIN32 */
1451 /* on Windows, select() only works with network sockets, which
1452 * means we absolutely cannot use Win32 PIPEs to implement
1453 * socket pairs with the current event loop implementation.
1454 * We're going to do like Cygwin: create a random pair
1455 * of localhost TCP sockets and connect them together
1456 */
1457 int s0, s1, s2, port;
1458 struct sockaddr_in sockin;
1459 socklen_t len;
1460
1461 /* first, create the 'server' socket.
1462 * a port number of 0 means 'any port between 1024 and 5000.
1463 * see Winsock bind() documentation for details */
1464 s0 = socket_loopback_server( 0, SOCK_STREAM );
1465 if (s0 < 0)
1466 return -1;
1467
1468 /* now connect a client socket to it, we first need to
1469 * extract the server socket's port number */
1470 len = sizeof sockin;
1471 if (getsockname(s0, (struct sockaddr*) &sockin, &len) < 0) {
1472 closesocket (s0);
1473 return -1;
1474 }
1475
1476 port = ntohs(sockin.sin_port);
1477 s2 = socket_loopback_client( port, SOCK_STREAM );
1478 if (s2 < 0) {
1479 closesocket(s0);
1480 return -1;
1481 }
1482
1483 /* we need to accept the connection on the server socket
1484 * this will create the second socket for the pair
1485 */
1486 len = sizeof sockin;
1487 s1 = accept(s0, (struct sockaddr*) &sockin, &len);
1488 if (s1 == INVALID_SOCKET) {
1489 closesocket (s0);
1490 closesocket (s2);
1491 return -1;
1492 }
1493 socket_set_nonblock(s1);
1494
1495 /* close server socket */
1496 closesocket(s0);
1497 *fd1 = s1;
1498 *fd2 = s2;
1499 return 0;
1500#endif /* _WIN32 */
1501}
1502
1503
1504
1505int
1506socket_mcast_inet_add_membership( int s, uint32_t ip )
1507{
1508 struct ip_mreq imr;
1509
1510 imr.imr_multiaddr.s_addr = htonl(ip);
1511 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1512
1513 if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001514 (const char *)&imr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001515 sizeof(struct ip_mreq)) < 0 )
1516 {
1517 return _fix_errno();
1518 }
1519 return 0;
1520}
1521
1522int
1523socket_mcast_inet_drop_membership( int s, uint32_t ip )
1524{
1525 struct ip_mreq imr;
1526
1527 imr.imr_multiaddr.s_addr = htonl(ip);
1528 imr.imr_interface.s_addr = htonl(INADDR_ANY);
1529
1530 if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
David 'Digit' Turner4e024bb2010-09-22 14:19:28 +02001531 (const char *)&imr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001532 sizeof(struct ip_mreq)) < 0 )
1533 {
1534 return _fix_errno();
1535 }
1536 return 0;
1537}
1538
1539int
1540socket_mcast_inet_set_loop( int s, int enabled )
1541{
1542 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
1543}
1544
1545int
1546socket_mcast_inet_set_ttl( int s, int ttl )
1547{
1548 return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
1549}
1550
1551
1552char*
1553host_name( void )
1554{
1555 static char buf[256]; /* 255 is the max host name length supported by DNS */
1556 int ret;
1557
1558 QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
1559
1560 if (ret < 0)
1561 return "localhost";
1562 else
1563 return buf;
1564}