1 /*****************************************************************
2 |
3 |   Neptune - Sockets :: BSD/Winsock Implementation
4 |
5 |   (c) 2001-2008 Gilles Boccon-Gibod
6 |   Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8  ****************************************************************/
9 
10 /*----------------------------------------------------------------------
11 |   includes
12 +---------------------------------------------------------------------*/
13 #if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_XBOX)) && !defined(__SYMBIAN32__)
14 #if !defined(__WINSOCK__)
15 #define __WINSOCK__
16 #endif
17 #endif
18 
19 #if defined(__WINSOCK__) && !defined(_XBOX)
20 #define STRICT
21 #define NPT_WIN32_USE_WINSOCK2
22 #ifdef NPT_WIN32_USE_WINSOCK2
23 /* it is important to include this in this order, because winsock.h and ws2tcpip.h */
24 /* have different definitions for the same preprocessor symbols, such as IP_ADD_MEMBERSHIP */
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 #else
28 #include <winsock.h>
29 #endif
30 #include <windows.h>
31 
32 // XBox
33 #elif defined(_XBOX)
34 #include <xtl.h>
35 #include <winsockx.h>
36 
37 #elif defined(__TCS__)
38 
39 // Trimedia includes
40 #include <sockets.h>
41 
42 #elif defined(__PSP__)
43 
44 // PSP includes
45 #include <psptypes.h>
46 #include <kernel.h>
47 #include <pspnet.h>
48 #include <pspnet_error.h>
49 #include <pspnet_inet.h>
50 #include <pspnet_resolver.h>
51 #include <pspnet_apctl.h>
52 #include <pspnet_ap_dialog_dummy.h>
53 #include <errno.h>
54 #include <wlan.h>
55 #include <pspnet/sys/socket.h>
56 #include <pspnet/sys/select.h>
57 #include <pspnet/netinet/in.h>
58 
59 #elif defined(__PPU__)
60 
61 // PS3 includes
62 #include <sys/types.h>
63 #include <sys/socket.h>
64 #include <sys/time.h>
65 #include <sys/select.h>
66 #include <netinet/in.h>
67 #include <netinet/tcp.h>
68 #include <netdb.h>
69 #include <fcntl.h>
70 #include <unistd.h>
71 #include <stdio.h>
72 #include <netex/net.h>
73 #include <netex/errno.h>
74 
75 #else
76 
77 // default includes
78 #include <sys/types.h>
79 #include <sys/socket.h>
80 #include <sys/select.h>
81 #include <sys/time.h>
82 #include <sys/ioctl.h>
83 #include <netinet/in.h>
84 #if !defined(__SYMBIAN32__)
85 #include <netinet/tcp.h>
86 #endif
87 #include <netdb.h>
88 #include <fcntl.h>
89 #include <unistd.h>
90 #include <string.h>
91 #include <stdio.h>
92 #include <errno.h>
93 #include <signal.h>
94 
95 #endif
96 
97 
98 #include "NptConfig.h"
99 #include "NptTypes.h"
100 #include "NptStreams.h"
101 #include "NptThreads.h"
102 #include "NptSockets.h"
103 #include "NptUtils.h"
104 #include "NptConstants.h"
105 #include "NptLogging.h"
106 
107 /*----------------------------------------------------------------------
108 |   logging
109 +---------------------------------------------------------------------*/
110 NPT_SET_LOCAL_LOGGER("neptune.sockets.bsd")
111 
112 /*----------------------------------------------------------------------
113 |   constants
114 +---------------------------------------------------------------------*/
115 const int NPT_TCP_SERVER_SOCKET_DEFAULT_LISTEN_COUNT = 20;
116 
117 /*----------------------------------------------------------------------
118 |   WinSock adaptation layer
119 +---------------------------------------------------------------------*/
120 #if defined(__WINSOCK__)
121 #if defined(_XBOX)
122 #include "NptXboxNetwork.h"
123 #define SO_ERROR    0x1007          /* unsupported */
124 #else
125 #include "NptWin32Network.h"
126 #endif
127 // force a reference to the initializer so that the linker does not optimize it out
128 static NPT_WinsockSystem& WinsockInitializer = NPT_WinsockSystem::Initializer;
129 
130 #if defined(SetPort)
131 #undef SetPort
132 #endif
133 
134 #if !defined(EWOULDBLOCK)
135 #define EWOULDBLOCK  WSAEWOULDBLOCK
136 #endif
137 #if !defined(EINPROGRESS)
138 #define EINPROGRESS  WSAEINPROGRESS
139 #endif
140 #if !defined(ECONNREFUSED)
141 #define ECONNREFUSED WSAECONNREFUSED
142 #endif
143 #if !defined(ECONNABORTED)
144 #define ECONNABORTED WSAECONNABORTED
145 #endif
146 #if !defined(ECONNRESET)
147 #define ECONNRESET   WSAECONNRESET
148 #endif
149 #if !defined(ETIMEDOUT)
150 #define ETIMEDOUT    WSAETIMEDOUT
151 #endif
152 #if !defined(ENETRESET)
153 #define ENETRESET    WSAENETRESET
154 #endif
155 #if !defined(EADDRINUSE)
156 #define EADDRINUSE   WSAEADDRINUSE
157 #endif
158 #if !defined(ENETDOWN)
159 #define ENETDOWN     WSAENETDOWN
160 #endif
161 #if !defined(ENETUNREACH)
162 #define ENETUNREACH  WSAENETUNREACH
163 #endif
164 #if !defined(EHOSTUNREACH)
165 #define EHOSTUNREACH WSAEHOSTUNREACH
166 #endif
167 #if !defined(ENOTCONN)
168 #define ENOTCONN     WSAENOTCONN
169 #endif
170 #if !defined(EAGAIN)
171 #define EAGAIN       WSAEWOULDBLOCK
172 #endif
173 #if !defined(EINTR)
174 #define EINTR        WSAEINTR
175 #endif
176 #if !defined(SHUT_RDWR)
177 #define SHUT_RDWR SD_BOTH
178 #endif
179 
180 #if !defined(__MINGW32__)
181 typedef int         ssize_t;
182 #endif
183 typedef int         socklen_t;
184 typedef char*       SocketBuffer;
185 typedef const char* SocketConstBuffer;
186 typedef char*       SocketOption;
187 typedef SOCKET      SocketFd;
188 
189 #define GetSocketError()                 WSAGetLastError()
190 #define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s) == INVALID_SOCKET)
191 #define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e) == SOCKET_ERROR)
192 #define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e) == SOCKET_ERROR)
193 #define NPT_BSD_SOCKET_INVALID_HANDLE    INVALID_SOCKET
194 
195 /*----------------------------------------------------------------------
196 |   Trimedia adaptation layer
197 +---------------------------------------------------------------------*/
198 #elif defined(__TCS__)  // trimedia PSOS w/ Target TCP
199 typedef void*       SocketBuffer;
200 typedef const void* SocketConstBuffer;
201 typedef void*       SocketOption;
202 typedef int         SocketFd;
203 
204 #define GetSocketError()                 errno
205 #define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s)  < 0)
206 #define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e)  < 0)
207 #define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e)  < 0)
208 #define NPT_BSD_SOCKET_INVALID_HANDLE    (-1)
209 
210 /*----------------------------------------------------------------------
211 |   PSP adaptation layer
212 +---------------------------------------------------------------------*/
213 #elif defined(__PSP__)
214 typedef SceNetInetSocklen_t socklen_t;
215 #define timeval SceNetInetTimeval
216 #define inet_addr sceNetInetInetAddr
217 #define select sceNetInetSelect
218 #define socket sceNetInetSocket
219 #define connect sceNetInetConnect
220 #define bind sceNetInetBind
221 #define accept sceNetInetAccept
222 #define getpeername sceNetInetGetpeername
223 #define getsockopt sceNetInetGetsockopt
224 #define setsockopt sceNetInetSetsockopt
225 #define listen sceNetInetListen
226 #define getsockname sceNetInetGetsockname
227 #define sockaddr SceNetInetSockaddr
228 #define sockaddr_in SceNetInetSockaddrIn
229 #define in_addr SceNetInetInAddr
230 #define send  sceNetInetSend
231 #define sendto sceNetInetSendto
232 #define recv  sceNetInetRecv
233 #define recvfrom sceNetInetRecvfrom
234 #define closesocket sceNetInetClose
235 #define htonl sceNetHtonl
236 #define htons sceNetHtons
237 #define ntohl sceNetNtohl
238 #define ntohs sceNetNtohs
239 #define SOL_SOCKET SCE_NET_INET_SOL_SOCKET
240 #define AF_INET SCE_NET_INET_AF_INET
241 #define SOCK_STREAM SCE_NET_INET_SOCK_STREAM
242 #define SOCK_DGRAM SCE_NET_INET_SOCK_DGRAM
243 #define SO_BROADCAST SCE_NET_INET_SO_BROADCAST
244 #define SO_ERROR SCE_NET_INET_SO_ERROR
245 #define IPPROTO_IP SCE_NET_INET_IPPROTO_IP
246 #define IP_ADD_MEMBERSHIP SCE_NET_INET_IP_ADD_MEMBERSHIP
247 #define IP_MULTICAST_IF SCE_NET_INET_IP_MULTICAST_IF
248 #define IP_MULTICAST_TTL SCE_NET_INET_IP_MULTICAST_TTL
249 #define SO_REUSEADDR SCE_NET_INET_SO_REUSEADDR
250 #define INADDR_ANY SCE_NET_INET_INADDR_ANY
251 #define ip_mreq SceNetInetIpMreq
252 #ifdef fd_set
253 #undef fd_set
254 #endif
255 #define fd_set SceNetInetFdSet
256 #ifdef FD_ZERO
257 #undef FD_ZERO
258 #endif
259 #define FD_ZERO SceNetInetFD_ZERO
260 #ifdef FD_SET
261 #undef FD_SET
262 #endif
263 #define FD_SET SceNetInetFD_SET
264 #ifdef FD_CLR
265 #undef FD_CLR
266 #endif
267 #define FD_CLR SceNetInetFD_CLR
268 #ifdef FD_ISSET
269 #undef FD_ISSET
270 #endif
271 #define FD_ISSET SceNetInetFD_ISSET
272 
273 #define RESOLVER_TIMEOUT (5 * 1000 * 1000)
274 #define RESOLVER_RETRY    5
275 
276 typedef void*       SocketBuffer;
277 typedef const void* SocketConstBuffer;
278 typedef void*       SocketOption;
279 typedef int         SocketFd;
280 
281 #define GetSocketError()                 sceNetInetGetErrno()
282 #define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s) < 0)
283 #define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e) < 0)
284 #define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e) < 0)
285 #define NPT_BSD_SOCKET_INVALID_HANDLE    (-1)
286 
287 /*----------------------------------------------------------------------
288 |   PS3 adaptation layer
289 +---------------------------------------------------------------------*/
290 #elif defined(__PPU__)
291 #undef EWOULDBLOCK
292 #undef ECONNREFUSED
293 #undef ECONNABORTED
294 #undef ECONNRESET
295 #undef ETIMEDOUT
296 #undef ENETRESET
297 #undef EADDRINUSE
298 #undef ENETDOWN
299 #undef ENETUNREACH
300 #undef EAGAIN
301 #undef EINTR
302 #undef EINPROGRESS
303 
304 #define EWOULDBLOCK   SYS_NET_EWOULDBLOCK
305 #define ECONNREFUSED  SYS_NET_ECONNREFUSED
306 #define ECONNABORTED  SYS_NET_ECONNABORTED
307 #define ECONNRESET    SYS_NET_ECONNRESET
308 #define ETIMEDOUT     SYS_NET_ETIMEDOUT
309 #define ENETRESET     SYS_NET_ENETRESET
310 #define EADDRINUSE    SYS_NET_EADDRINUSE
311 #define ENETDOWN      SYS_NET_ENETDOWN
312 #define ENETUNREACH   SYS_NET_ENETUNREACH
313 #define EAGAIN        SYS_NET_EAGAIN
314 #define EINTR         SYS_NET_EINTR
315 #define EINPROGRESS   SYS_NET_EINPROGRESS
316 
317 typedef void*        SocketBuffer;
318 typedef const void*  SocketConstBuffer;
319 typedef void*        SocketOption;
320 typedef int          SocketFd;
321 
322 #define closesocket  socketclose
323 #define select       socketselect
324 
325 #define GetSocketError()                 sys_net_errno
326 #define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s) < 0)
327 #define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e) < 0)
328 #define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e) < 0)
329 #define NPT_BSD_SOCKET_INVALID_HANDLE    (-1)
330 
331 // network initializer
332 static struct NPT_Ps3NetworkInitializer {
NPT_Ps3NetworkInitializerNPT_Ps3NetworkInitializer333     NPT_Ps3NetworkInitializer() {
334         sys_net_initialize_network();
335     }
~NPT_Ps3NetworkInitializerNPT_Ps3NetworkInitializer336     ~NPT_Ps3NetworkInitializer() {
337         sys_net_finalize_network();
338     }
339 } Ps3NetworkInitializer;
340 
341 /*----------------------------------------------------------------------
342 |   Default adaptation layer
343 +---------------------------------------------------------------------*/
344 #else
345 typedef void*       SocketBuffer;
346 typedef const void* SocketConstBuffer;
347 typedef void*       SocketOption;
348 typedef int         SocketFd;
349 
350 #define closesocket  close
351 #define ioctlsocket  ioctl
352 
353 #define GetSocketError()                 errno
354 #define NPT_BSD_SOCKET_IS_INVALID(_s)    ((_s)  < 0)
355 #define NPT_BSD_SOCKET_CALL_FAILED(_e)   ((_e)  < 0)
356 #define NPT_BSD_SOCKET_SELECT_FAILED(_e) ((_e)  < 0)
357 #define NPT_BSD_SOCKET_INVALID_HANDLE    (-1)
358 
359 #endif
360 
361 /*----------------------------------------------------------------------
362 |   IPv6 support
363 +---------------------------------------------------------------------*/
364 #if defined(NPT_CONFIG_ENABLE_IPV6)
365 #include <arpa/inet.h>
366 
367 #define NPT_SOCKETS_PF_INET PF_INET6
368 typedef union {
369     struct sockaddr         sa;
370     struct sockaddr_in      sa_in;
371     struct sockaddr_in6     sa_in6;
372     struct sockaddr_storage sa_storage;
373 } NPT_sockaddr_in;
374 
375 #else
376 
377 #define NPT_SOCKETS_PF_INET PF_INET
378 typedef union {
379     struct sockaddr    sa;
380     struct sockaddr_in sa_in;
381 } NPT_sockaddr_in;
382 
383 #endif
384 
385 #if defined(NPT_CONFIG_ENABLE_IPV6)
386 /*----------------------------------------------------------------------
387 |   SocketAddressToInetAddress
388 +---------------------------------------------------------------------*/
389 static void
SocketAddressToInetAddress(const NPT_SocketAddress & socket_address,NPT_sockaddr_in & inet_address,socklen_t & inet_address_length)390 SocketAddressToInetAddress(const NPT_SocketAddress& socket_address,
391                            NPT_sockaddr_in&         inet_address,
392                            socklen_t&               inet_address_length)
393 {
394     // initialize the structure
395     NPT_SetMemory(&inet_address, 0, sizeof(inet_address));
396 
397     // setup the structure
398     inet_address_length = sizeof(sockaddr_in6);
399     inet_address.sa_in6.sin6_len      = inet_address_length;
400     inet_address.sa_in6.sin6_family   = AF_INET6;
401     inet_address.sa_in6.sin6_port     = htons(socket_address.GetPort());
402     inet_address.sa_in6.sin6_scope_id = socket_address.GetIpAddress().GetScopeId();
403 
404     NPT_IpAddress::Type type = socket_address.GetIpAddress().GetType();
405     if (type == NPT_IpAddress::IPV6) {
406         NPT_CopyMemory(inet_address.sa_in6.sin6_addr.s6_addr, socket_address.GetIpAddress().AsBytes(), 16);
407     } else {
408         NPT_SetMemory(&inet_address.sa_in6.sin6_addr.s6_addr[0], 0, 10);
409         inet_address.sa_in6.sin6_addr.s6_addr[10] = 0xFF;
410         inet_address.sa_in6.sin6_addr.s6_addr[11] = 0xFF;
411         NPT_CopyMemory(&inet_address.sa_in6.sin6_addr.s6_addr[12], socket_address.GetIpAddress().AsBytes(), 4);
412     }
413 }
414 
415 /*----------------------------------------------------------------------
416 |   InetAddressToSocketAddress
417 +---------------------------------------------------------------------*/
418 static void
InetAddressToSocketAddress(const NPT_sockaddr_in & inet_address,NPT_SocketAddress & socket_address)419 InetAddressToSocketAddress(const NPT_sockaddr_in& inet_address,
420                            NPT_SocketAddress&     socket_address)
421 {
422     // setup the structure
423     socket_address.SetPort(inet_address.sa_in6.sin6_port);
424     if (inet_address.sa.sa_family == AF_INET6) {
425         socket_address.SetPort(ntohs(inet_address.sa_in6.sin6_port));
426         socket_address.SetIpAddress(NPT_IpAddress(NPT_IpAddress::IPV6, inet_address.sa_in6.sin6_addr.s6_addr, 16));
427     } else {
428         socket_address.SetPort(ntohs(inet_address.sa_in.sin_port));
429         socket_address.SetIpAddress(NPT_IpAddress(ntohl(inet_address.sa_in.sin_addr.s_addr)));
430     }
431 }
432 #else
433 /*----------------------------------------------------------------------
434 |   SocketAddressToInetAddress
435 +---------------------------------------------------------------------*/
436 static void
SocketAddressToInetAddress(const NPT_SocketAddress & socket_address,NPT_sockaddr_in & inet_address,socklen_t & inet_address_length)437 SocketAddressToInetAddress(const NPT_SocketAddress& socket_address,
438                            NPT_sockaddr_in&         inet_address,
439                            socklen_t&               inet_address_length)
440 {
441     // initialize the structure
442     NPT_SetMemory(&inet_address, 0, sizeof(inet_address));
443     inet_address_length = sizeof(sockaddr_in);
444 
445 #if defined(NPT_CONFIG_HAVE_SOCKADDR_IN_SIN_LEN)
446     inet_address.sa_in.sin_len = sizeof(inet_address);
447 #endif
448 
449     // setup the structure
450     inet_address.sa_in.sin_family      = AF_INET;
451     inet_address.sa_in.sin_port        = htons(socket_address.GetPort());
452     inet_address.sa_in.sin_addr.s_addr = htonl(socket_address.GetIpAddress().AsLong());
453 }
454 
455 /*----------------------------------------------------------------------
456 |   InetAddressToSocketAddress
457 +---------------------------------------------------------------------*/
458 static void
InetAddressToSocketAddress(const NPT_sockaddr_in & inet_address,NPT_SocketAddress & socket_address)459 InetAddressToSocketAddress(const NPT_sockaddr_in& inet_address,
460                            NPT_SocketAddress&     socket_address)
461 {
462     socket_address.SetPort(ntohs(inet_address.sa_in.sin_port));
463     socket_address.SetIpAddress(NPT_IpAddress(ntohl(inet_address.sa_in.sin_addr.s_addr)));
464 }
465 #endif
466 
467 /*----------------------------------------------------------------------
468 |   MapErrorCode
469 +---------------------------------------------------------------------*/
470 static NPT_Result
MapErrorCode(int error)471 MapErrorCode(int error)
472 {
473     switch (error) {
474         case ECONNRESET:
475         case ENETRESET:
476             return NPT_ERROR_CONNECTION_RESET;
477 
478         case ECONNABORTED:
479             return NPT_ERROR_CONNECTION_ABORTED;
480 
481         case ECONNREFUSED:
482             return NPT_ERROR_CONNECTION_REFUSED;
483 
484         case ETIMEDOUT:
485             return NPT_ERROR_TIMEOUT;
486 
487         case EADDRINUSE:
488             return NPT_ERROR_ADDRESS_IN_USE;
489 
490         case ENETDOWN:
491             return NPT_ERROR_NETWORK_DOWN;
492 
493         case ENETUNREACH:
494             return NPT_ERROR_NETWORK_UNREACHABLE;
495 
496         case EHOSTUNREACH:
497             return NPT_ERROR_HOST_UNREACHABLE;
498 
499         case EINPROGRESS:
500         case EAGAIN:
501 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
502         case EWOULDBLOCK:
503 #endif
504             return NPT_ERROR_WOULD_BLOCK;
505 
506 #if defined(EPIPE)
507         case EPIPE:
508             return NPT_ERROR_CONNECTION_RESET;
509 #endif
510 
511 #if defined(ENOTCONN)
512         case ENOTCONN:
513             return NPT_ERROR_NOT_CONNECTED;
514 #endif
515 
516 #if defined(EINTR)
517         case EINTR:
518             return NPT_ERROR_INTERRUPTED;
519 #endif
520 
521 #if defined(EACCES)
522         case EACCES:
523             return NPT_ERROR_PERMISSION_DENIED;
524 #endif
525 
526         default:
527             return NPT_ERROR_ERRNO(error);
528     }
529 }
530 
531 #if defined(_XBOX)
532 
533 struct hostent {
534     char    * h_name;           /* official name of host */
535     char    * * h_aliases;      /* alias list */
536     short   h_addrtype;         /* host address type */
537     short   h_length;           /* length of address */
538     char    * * h_addr_list;    /* list of addresses */
539 #define h_addr  h_addr_list[0]  /* address, for backward compat */
540 };
541 
542 typedef struct {
543     struct hostent server;
544     char name[128];
545     char addr[16];
546     char* addr_list[4];
547 } HostEnt;
548 
549 /*----------------------------------------------------------------------
550 |   gethostbyname
551 +---------------------------------------------------------------------*/
552 static struct hostent*
gethostbyname(const char * name)553 gethostbyname(const char* name)
554 {
555     struct hostent* host = NULL;
556     HostEnt*        host_entry = new HostEnt;
557     WSAEVENT        hEvent = WSACreateEvent();
558     XNDNS*          pDns = NULL;
559 
560     INT err = XNetDnsLookup(name, hEvent, &pDns);
561     WaitForSingleObject(hEvent, INFINITE);
562     if (pDns) {
563         if (pDns->iStatus == 0) {
564             strcpy(host_entry->name, name);
565             host_entry->addr_list[0] = host_entry->addr;
566             memcpy(host_entry->addr, &(pDns->aina[0].s_addr), 4);
567             host_entry->server.h_name = host_entry->name;
568             host_entry->server.h_aliases = 0;
569             host_entry->server.h_addrtype = AF_INET;
570             host_entry->server.h_length = 4;
571             host_entry->server.h_addr_list = new char*[4];
572 
573             host_entry->server.h_addr_list[0] = host_entry->addr_list[0];
574             host_entry->server.h_addr_list[1] = 0;
575 
576             host = (struct hostent*)host_entry;
577         }
578         XNetDnsRelease(pDns);
579     }
580     WSACloseEvent(hEvent);
581     return host;
582 };
583 
584 #endif // _XBOX
585 
586 #if defined(__WINSOCK__)
587 /*----------------------------------------------------------------------
588 |   socketpair
589 +---------------------------------------------------------------------*/
590 static int
socketpair(int,int,int,SOCKET sockets[2])591 socketpair(int, int, int, SOCKET sockets[2]) // we ignore the first two params: we only use this for a strictly limited case
592 {
593 	int result = 0;
594     socklen_t name_length = 0;
595 	int reuse = 1;
596 
597 	// initialize with default values
598 	sockets[0] = INVALID_SOCKET;
599 	sockets[1] = INVALID_SOCKET;
600 
601 	// create a listener socket and bind to the loopback address, any port
602 	SOCKET listener = socket(PF_INET, SOCK_STREAM, 0);
603 	if (listener == INVALID_SOCKET) goto fail;
604 
605 	// bind the listener and listen for connections
606 	struct sockaddr_in inet_address;
607 	memset(&inet_address, 0, sizeof(inet_address));
608 	inet_address.sin_family = AF_INET;
609 	inet_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
610 	setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
611 	result = bind(listener, (const sockaddr*)&inet_address, sizeof(inet_address));
612 	if (result != 0) goto fail;
613 	listen(listener, 1);
614 
615 	// read the port that was assigned to the listener socket
616     name_length = sizeof(inet_address);
617     result = getsockname(listener, (struct sockaddr*)&inet_address, &name_length);
618 	if (result != 0) goto fail;
619 
620 	// create the first socket
621 	sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
622 	if (sockets[0] == INVALID_SOCKET) goto fail;
623 
624 	// connect the first socket
625 	result = connect(sockets[0], (const sockaddr*)&inet_address, sizeof(inet_address));
626 	if (result != 0) goto fail;
627 
628 	// accept the connection, resulting in the second socket
629 	name_length = sizeof(inet_address);
630 	sockets[1] = accept(listener, (sockaddr*)&inet_address, &name_length);
631 	if (result != 0) goto fail;
632 
633 	// we don't need the listener anymore
634 	closesocket(listener);
635 	return 0;
636 
637 fail:
638 	result = MapErrorCode(GetSocketError());
639 	if (listener   != INVALID_SOCKET) closesocket(listener);
640 	if (sockets[0] != INVALID_SOCKET) closesocket(sockets[0]);
641 	if (sockets[1] != INVALID_SOCKET) closesocket(sockets[1]);
642 	sockets[0] = sockets[1] = INVALID_SOCKET;
643 	return result;
644 }
645 #endif
646 
647 /*----------------------------------------------------------------------
648 |   NPT_Hash<NPT_Thread::ThreadId>
649 +---------------------------------------------------------------------*/
650 template <>
651 struct NPT_Hash<NPT_Thread::ThreadId>
652 {
operator ()NPT_Hash653     NPT_UInt32 operator()(NPT_Thread::ThreadId id) const {
654         return (NPT_UInt32)(id & 0xFFFFFFFF);
655     }
656 };
657 
658 /*----------------------------------------------------------------------
659 |   NPT_IpAddress::ResolveName
660 +---------------------------------------------------------------------*/
661 NPT_Result
ResolveName(const char * name,NPT_Timeout)662 NPT_IpAddress::ResolveName(const char* name, NPT_Timeout)
663 {
664     // check parameters
665     if (name == NULL || name[0] == '\0') return NPT_ERROR_HOST_UNKNOWN;
666 
667 #if !defined(NPT_CONFIG_ENABLE_IPV6)
668     // handle numerical addrs
669     NPT_IpAddress numerical_address;
670     if (NPT_SUCCEEDED(numerical_address.Parse(name))) {
671         /* the name is a numerical IP addr */
672         *this = numerical_address;
673         return NPT_SUCCESS;
674     }
675 #endif
676 
677     // resolve the name into a list of addresses
678     NPT_List<NPT_IpAddress> addresses;
679     NPT_Result result = NPT_NetworkNameResolver::Resolve(name, addresses);
680     if (NPT_FAILED(result)) return result;
681     if (addresses.GetItemCount() < 1) {
682         return NPT_ERROR_NO_SUCH_NAME;
683     }
684 
685     // pick the first address
686     *this = *(addresses.GetFirstItem());
687 
688     return NPT_SUCCESS;
689 }
690 
691 /*----------------------------------------------------------------------
692 |   NPT_BsdSocketFd
693 +---------------------------------------------------------------------*/
694 class NPT_BsdSocketFd
695 {
696 public:
697     // constructors and destructor
NPT_BsdSocketFd(SocketFd fd,NPT_Flags flags)698     NPT_BsdSocketFd(SocketFd fd, NPT_Flags flags) :
699       m_SocketFd(fd),
700       m_ReadTimeout(NPT_TIMEOUT_INFINITE),
701       m_WriteTimeout(NPT_TIMEOUT_INFINITE),
702       m_Position(0),
703       m_Cancelled(false),
704       m_Cancellable((flags & NPT_SOCKET_FLAG_CANCELLABLE) != 0) {
705         // always use non-blocking mode
706         SetBlockingMode(false);
707 
708         // cancellation support
709         if (flags & NPT_SOCKET_FLAG_CANCELLABLE) {
710             int result = socketpair(AF_UNIX, SOCK_DGRAM, 0, m_CancelFds);
711             if (result != 0) {
712                 NPT_LOG_WARNING_1("socketpair failed (%d)", GetSocketError());
713                 m_CancelFds[0] = m_CancelFds[1] = -1;
714                 m_Cancellable = false;
715             }
716         } else {
717             m_CancelFds[0] = m_CancelFds[1] = NPT_BSD_SOCKET_INVALID_HANDLE;
718         }
719     }
~NPT_BsdSocketFd()720     ~NPT_BsdSocketFd() {
721         if (m_Cancellable) {
722             if (!NPT_BSD_SOCKET_IS_INVALID(m_CancelFds[0])) closesocket(m_CancelFds[0]);
723             if (!NPT_BSD_SOCKET_IS_INVALID(m_CancelFds[1])) closesocket(m_CancelFds[1]);
724         }
725         closesocket(m_SocketFd);
726     }
727 
728     // methods
729     NPT_Result SetBlockingMode(bool blocking);
730     NPT_Result WaitUntilReadable();
731     NPT_Result WaitUntilWriteable();
732     NPT_Result WaitForCondition(bool readable, bool writeable, bool async_connect, NPT_Timeout timeout);
733     NPT_Result Cancel(bool do_shutdown);
734 
735     // members
736     SocketFd          m_SocketFd;
737     NPT_Timeout       m_ReadTimeout;
738     NPT_Timeout       m_WriteTimeout;
739     NPT_Position      m_Position;
740     volatile bool     m_Cancelled;
741     bool              m_Cancellable;
742     SocketFd          m_CancelFds[2];
743 
744 private:
745     // methods
746     friend class NPT_BsdTcpServerSocket;
747     friend class NPT_BsdTcpClientSocket;
748 };
749 
750 typedef NPT_Reference<NPT_BsdSocketFd> NPT_BsdSocketFdReference;
751 
752 /*----------------------------------------------------------------------
753 |   NPT_BsdBlockerSocket
754 +---------------------------------------------------------------------*/
755 class NPT_BsdBlockerSocket {
756 public:
NPT_BsdBlockerSocket(NPT_BsdSocketFd * fd)757     NPT_BsdBlockerSocket(NPT_BsdSocketFd* fd) {
758         Set(NPT_Thread::GetCurrentThreadId(), fd);
759     }
~NPT_BsdBlockerSocket()760     ~NPT_BsdBlockerSocket() {
761         Set(NPT_Thread::GetCurrentThreadId(), NULL);
762     }
763 
764     static NPT_Result Cancel(NPT_Thread::ThreadId id);
765 
766 private:
767     static NPT_Result Set(NPT_Thread::ThreadId id, NPT_BsdSocketFd* fd);
768 
769     static NPT_Mutex MapLock;
770     static NPT_HashMap<NPT_Thread::ThreadId, NPT_BsdSocketFd*> Map;
771 };
772 
773 /*----------------------------------------------------------------------
774 |   NPT_BsdBlockerSocket::MapLock
775 +---------------------------------------------------------------------*/
776 NPT_Mutex NPT_BsdBlockerSocket::MapLock;
777 
778 /*----------------------------------------------------------------------
779 |   NPT_BsdBlockerSocket::Map
780 +---------------------------------------------------------------------*/
781 NPT_HashMap<NPT_Thread::ThreadId, NPT_BsdSocketFd*> NPT_BsdBlockerSocket::Map;
782 
783 /*----------------------------------------------------------------------
784 |   NPT_BsdBlockerSocket::Set
785 +---------------------------------------------------------------------*/
786 NPT_Result
Set(NPT_Thread::ThreadId id,NPT_BsdSocketFd * fd)787 NPT_BsdBlockerSocket::Set(NPT_Thread::ThreadId id, NPT_BsdSocketFd* fd)
788 {
789     NPT_AutoLock synchronized(MapLock);
790 
791     if (fd) {
792         return Map.Put(id, fd);
793     } else {
794         return Map.Erase(id);
795     }
796 }
797 
798 /*----------------------------------------------------------------------
799 |   NPT_BsdBlockerSocket::Cancel
800 +---------------------------------------------------------------------*/
801 NPT_Result
Cancel(NPT_Thread::ThreadId id)802 NPT_BsdBlockerSocket::Cancel(NPT_Thread::ThreadId id)
803 {
804     NPT_AutoLock synchronized(MapLock);
805 
806     NPT_BsdSocketFd** fd = NULL;
807     NPT_Result result = Map.Get(id, fd);
808     if (NPT_SUCCEEDED(result) && fd && *fd) {
809         (*fd)->Cancel(true);
810     }
811 
812     return result;
813 }
814 
815 /*----------------------------------------------------------------------
816 |   NPT_Socket::CancelBlockerSocket
817 +---------------------------------------------------------------------*/
818 NPT_Result
CancelBlockerSocket(NPT_Thread::ThreadId thread_id)819 NPT_Socket::CancelBlockerSocket(NPT_Thread::ThreadId thread_id)
820 {
821     return NPT_BsdBlockerSocket::Cancel(thread_id);
822 }
823 
824 
825 #if defined(__WINSOCK__) || defined(__TCS__)
826 /*----------------------------------------------------------------------
827 |   NPT_BsdSocketFd::SetBlockingMode
828 +---------------------------------------------------------------------*/
829 NPT_Result
SetBlockingMode(bool blocking)830 NPT_BsdSocketFd::SetBlockingMode(bool blocking)
831 {
832     unsigned long args = blocking?0:1;
833     if (ioctlsocket(m_SocketFd, FIONBIO, &args)) {
834         return NPT_ERROR_SOCKET_CONTROL_FAILED;
835     }
836     return NPT_SUCCESS;
837 }
838 #elif defined(__PSP__) || defined(__PPU__)
839 /*----------------------------------------------------------------------
840 |   NPT_BsdSocketFd::SetBlockingMode
841 +---------------------------------------------------------------------*/
842 NPT_Result
SetBlockingMode(bool blocking)843 NPT_BsdSocketFd::SetBlockingMode(bool blocking)
844 {
845     int args = blocking?0:1;
846     if (setsockopt(m_SocketFd, SOL_SOCKET, SO_NBIO, &args, sizeof(args))) {
847         return NPT_ERROR_SOCKET_CONTROL_FAILED;
848     }
849     return NPT_SUCCESS;
850 }
851 #else
852 /*----------------------------------------------------------------------
853 |   NPT_BsdSocketFd::SetBlockingMode
854 +---------------------------------------------------------------------*/
855 NPT_Result
SetBlockingMode(bool blocking)856 NPT_BsdSocketFd::SetBlockingMode(bool blocking)
857 {
858     int flags = fcntl(m_SocketFd, F_GETFL, 0);
859     if (blocking) {
860         flags &= ~O_NONBLOCK;
861     } else {
862         flags |= O_NONBLOCK;
863     }
864     if (fcntl(m_SocketFd, F_SETFL, flags)) {
865         return NPT_ERROR_SOCKET_CONTROL_FAILED;
866     }
867     return NPT_SUCCESS;
868 }
869 #endif
870 
871 /*----------------------------------------------------------------------
872 |   NPT_BsdSocketFd::WaitUntilReadable
873 +---------------------------------------------------------------------*/
874 NPT_Result
WaitUntilReadable()875 NPT_BsdSocketFd::WaitUntilReadable()
876 {
877     return WaitForCondition(true, false, false, m_ReadTimeout);
878 }
879 
880 /*----------------------------------------------------------------------
881 |   NPT_BsdSocketFd::WaitUntilWriteable
882 +---------------------------------------------------------------------*/
883 NPT_Result
WaitUntilWriteable()884 NPT_BsdSocketFd::WaitUntilWriteable()
885 {
886     return WaitForCondition(false, true, false, m_WriteTimeout);
887 }
888 
889 /*----------------------------------------------------------------------
890 |   NPT_BsdSocketFd::WaitForCondition
891 +---------------------------------------------------------------------*/
892 NPT_Result
WaitForCondition(bool wait_for_readable,bool wait_for_writeable,bool async_connect,NPT_Timeout timeout)893 NPT_BsdSocketFd::WaitForCondition(bool        wait_for_readable,
894                                   bool        wait_for_writeable,
895                                   bool        async_connect,
896                                   NPT_Timeout timeout)
897 {
898     // wait for incoming connection
899     NPT_Result result = NPT_SUCCESS;
900     int        max_fd = (int)m_SocketFd;
901     fd_set read_set;
902     fd_set write_set;
903     fd_set except_set;
904     FD_ZERO(&read_set);
905     if (wait_for_readable) FD_SET(m_SocketFd, &read_set);
906     FD_ZERO(&write_set);
907     if (wait_for_writeable) FD_SET(m_SocketFd, &write_set);
908     FD_ZERO(&except_set);
909     FD_SET(m_SocketFd, &except_set);
910 
911     // if the socket is cancellable, add it to the blocker map so a thread can cancel it
912     NPT_BsdBlockerSocket blocker(this);
913 
914     // setup the cancel fd
915     if (m_Cancellable && timeout) {
916         if ((int)m_CancelFds[1] > max_fd) max_fd = m_CancelFds[1];
917         FD_SET(m_CancelFds[1], &read_set);
918     }
919 
920     struct timeval timeout_value;
921     if (timeout != NPT_TIMEOUT_INFINITE) {
922         timeout_value.tv_sec = timeout/1000;
923         timeout_value.tv_usec = 1000*(timeout-1000*(timeout/1000));
924     };
925 
926     NPT_LOG_FINER_2("waiting for condition (%s %s)",
927                     wait_for_readable?"read":"",
928                     wait_for_writeable?"write":"");
929     int io_result;
930     do {
931         io_result = select(max_fd+1,
932                            &read_set, &write_set, &except_set,
933                            timeout == NPT_TIMEOUT_INFINITE ?
934                            NULL : &timeout_value);
935         NPT_LOG_FINER_1("select returned %d", io_result);
936     } while (NPT_BSD_SOCKET_SELECT_FAILED(io_result) && GetSocketError() == EINTR);
937 
938     if (m_Cancelled) return NPT_ERROR_CANCELLED;
939 
940     if (io_result == 0) {
941         if (timeout == 0) {
942             // non-blocking call
943             result = NPT_ERROR_WOULD_BLOCK;
944         } else {
945             // timeout
946             result = NPT_ERROR_TIMEOUT;
947         }
948     } else if (NPT_BSD_SOCKET_SELECT_FAILED(io_result)) {
949         result = MapErrorCode(GetSocketError());
950     } else if ((wait_for_readable  && FD_ISSET(m_SocketFd, &read_set)) ||
951                (wait_for_writeable && FD_ISSET(m_SocketFd, &write_set))) {
952         if (async_connect) {
953             // get error status from socket
954             // (some systems return the error in errno, others
955             //  return it in the buffer passed to getsockopt)
956             int error = 0;
957             socklen_t length = sizeof(error);
958             io_result = getsockopt(m_SocketFd,
959                                    SOL_SOCKET,
960                                    SO_ERROR,
961                                    (SocketOption)&error,
962                                    &length);
963             if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
964                 result = MapErrorCode(GetSocketError());
965             } else if (error) {
966                 result = MapErrorCode(error);
967             } else {
968                 result = NPT_SUCCESS;
969             }
970         } else {
971             result = NPT_SUCCESS;
972         }
973     } else if (FD_ISSET(m_SocketFd, &except_set)) {
974         NPT_LOG_FINE("select socket exception is set");
975 
976         int error = 0;
977         socklen_t length = sizeof(error);
978         io_result = getsockopt(m_SocketFd,
979                                 SOL_SOCKET,
980                                 SO_ERROR,
981                                 (SocketOption)&error,
982                                 &length);
983         if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
984             result = MapErrorCode(GetSocketError());
985         } else if (error) {
986             result = MapErrorCode(error);
987         } else {
988             result = NPT_FAILURE;
989         }
990     } else {
991         // should not happen
992         NPT_LOG_FINE("unexected select state");
993         result = NPT_ERROR_INTERNAL;
994     }
995 
996     if (NPT_FAILED(result)) {
997         NPT_LOG_FINER_1("select result = %d", result);
998     }
999     return result;
1000 }
1001 
1002 /*----------------------------------------------------------------------
1003 |   NPT_BsdSocketFd::Cancel
1004 +---------------------------------------------------------------------*/
1005 NPT_Result
Cancel(bool do_shutdown)1006 NPT_BsdSocketFd::Cancel(bool do_shutdown)
1007 {
1008     // mark the socket as cancelled
1009     m_Cancelled = true;
1010 
1011     // force a shutdown if requested
1012     if (do_shutdown) {
1013         int result = shutdown(m_SocketFd, SHUT_RDWR);
1014         if (NPT_BSD_SOCKET_CALL_FAILED(result)) {
1015             NPT_LOG_FINE_1("shutdown failed (%d)", MapErrorCode(GetSocketError()));
1016         }
1017     }
1018 
1019     // unblock waiting selects
1020     if (m_Cancellable) {
1021         char dummy = 0;
1022         send(m_CancelFds[0], &dummy, 1, 0);
1023     }
1024 
1025     return NPT_SUCCESS;
1026 }
1027 
1028 /*----------------------------------------------------------------------
1029 |   NPT_BsdSocketStream
1030 +---------------------------------------------------------------------*/
1031 class NPT_BsdSocketStream
1032 {
1033  public:
1034     // methods
NPT_BsdSocketStream(NPT_BsdSocketFdReference & socket_fd)1035     NPT_BsdSocketStream(NPT_BsdSocketFdReference& socket_fd) :
1036        m_SocketFdReference(socket_fd) {}
1037 
1038     // NPT_InputStream and NPT_OutputStream methods
Seek(NPT_Position)1039     NPT_Result Seek(NPT_Position) { return NPT_ERROR_NOT_SUPPORTED; }
Tell(NPT_Position & where)1040     NPT_Result Tell(NPT_Position& where) {
1041         where = 0;
1042         return NPT_SUCCESS;
1043     }
1044 
1045  protected:
1046     // destructor
~NPT_BsdSocketStream()1047      virtual ~NPT_BsdSocketStream() {}
1048 
1049     // members
1050     NPT_BsdSocketFdReference m_SocketFdReference;
1051 };
1052 
1053 /*----------------------------------------------------------------------
1054 |   NPT_BsdSocketInputStream
1055 +---------------------------------------------------------------------*/
1056 class NPT_BsdSocketInputStream : public NPT_InputStream,
1057                                  private NPT_BsdSocketStream
1058 {
1059 public:
1060     // constructors and destructor
NPT_BsdSocketInputStream(NPT_BsdSocketFdReference & socket_fd)1061     NPT_BsdSocketInputStream(NPT_BsdSocketFdReference& socket_fd) :
1062       NPT_BsdSocketStream(socket_fd) {}
1063 
1064     // NPT_InputStream methods
1065     NPT_Result Read(void*     buffer,
1066                     NPT_Size  bytes_to_read,
1067                     NPT_Size* bytes_read);
Seek(NPT_Position offset)1068     NPT_Result Seek(NPT_Position offset) {
1069         return NPT_BsdSocketStream::Seek(offset); }
Tell(NPT_Position & where)1070     NPT_Result Tell(NPT_Position& where) {
1071         return NPT_BsdSocketStream::Tell(where);
1072     }
1073     NPT_Result GetSize(NPT_LargeSize& size);
1074     NPT_Result GetAvailable(NPT_LargeSize& available);
1075 };
1076 
1077 /*----------------------------------------------------------------------
1078 |   NPT_BsdSocketInputStream::Read
1079 +---------------------------------------------------------------------*/
1080 NPT_Result
Read(void * buffer,NPT_Size bytes_to_read,NPT_Size * bytes_read)1081 NPT_BsdSocketInputStream::Read(void*     buffer,
1082                                NPT_Size  bytes_to_read,
1083                                NPT_Size* bytes_read)
1084 {
1085     // if we're blocking, wait until the socket is readable
1086     if (m_SocketFdReference->m_ReadTimeout) {
1087         NPT_Result result = m_SocketFdReference->WaitUntilReadable();
1088         if (result != NPT_SUCCESS) return result;
1089     }
1090 
1091     // read from the socket
1092     NPT_LOG_FINEST_1("reading %d from socket", (int)bytes_to_read);
1093     ssize_t nb_read = recv(m_SocketFdReference->m_SocketFd,
1094                            (SocketBuffer)buffer,
1095                            bytes_to_read, 0);
1096     NPT_LOG_FINEST_1("recv returned %d", (int)nb_read);
1097 
1098     if (nb_read <= 0) {
1099         if (bytes_read) *bytes_read = 0;
1100         if (m_SocketFdReference->m_Cancelled) return NPT_ERROR_CANCELLED;
1101 
1102         if (nb_read == 0) {
1103             NPT_LOG_FINE("socket end of stream");
1104             return NPT_ERROR_EOS;
1105         } else {
1106             NPT_Result result = MapErrorCode(GetSocketError());
1107             NPT_LOG_FINE_1("socket result = %d", result);
1108             return result;
1109         }
1110     }
1111 
1112     // update position and return
1113     if (bytes_read) *bytes_read = (NPT_Size)nb_read;
1114     m_SocketFdReference->m_Position += nb_read;
1115     return NPT_SUCCESS;
1116 }
1117 
1118 /*----------------------------------------------------------------------
1119 |   NPT_BsdSocketInputStream::GetSize
1120 +---------------------------------------------------------------------*/
1121 NPT_Result
GetSize(NPT_LargeSize & size)1122 NPT_BsdSocketInputStream::GetSize(NPT_LargeSize& size)
1123 {
1124     // generic socket streams have no size
1125     size = 0;
1126     return NPT_ERROR_NOT_SUPPORTED;
1127 }
1128 
1129 #if defined(__PPU__)
1130 /*----------------------------------------------------------------------
1131 |   NPT_BsdSocketInputStream::GetAvailable
1132 +---------------------------------------------------------------------*/
1133 NPT_Result
GetAvailable(NPT_LargeSize &)1134 NPT_BsdSocketInputStream::GetAvailable(NPT_LargeSize&)
1135 {
1136     return NPT_ERROR_NOT_SUPPORTED;
1137 }
1138 #else
1139 /*----------------------------------------------------------------------
1140 |   NPT_BsdSocketInputStream::GetAvailable
1141 +---------------------------------------------------------------------*/
1142 NPT_Result
GetAvailable(NPT_LargeSize & available)1143 NPT_BsdSocketInputStream::GetAvailable(NPT_LargeSize& available)
1144 {
1145     unsigned long ready = 0;
1146     int io_result = ioctlsocket(m_SocketFdReference->m_SocketFd, FIONREAD, &ready);
1147     if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
1148         available = 0;
1149         return NPT_ERROR_SOCKET_CONTROL_FAILED;
1150     } else {
1151         available = ready;
1152         if (available == 0) {
1153             // check if the socket is disconnected
1154             NPT_Result result = m_SocketFdReference->WaitForCondition(true, false, false, 0);
1155             if (result == NPT_ERROR_WOULD_BLOCK) {
1156                 return NPT_SUCCESS;
1157             } else {
1158                 available = 1; // pretend that there's data available
1159             }
1160         }
1161         return NPT_SUCCESS;
1162     }
1163 }
1164 #endif
1165 
1166 /*----------------------------------------------------------------------
1167 |   NPT_BsdSocketOutputStream
1168 +---------------------------------------------------------------------*/
1169 class NPT_BsdSocketOutputStream : public NPT_OutputStream,
1170                                   private NPT_BsdSocketStream
1171 {
1172 public:
1173     // constructors and destructor
NPT_BsdSocketOutputStream(NPT_BsdSocketFdReference & socket_fd)1174     NPT_BsdSocketOutputStream(NPT_BsdSocketFdReference& socket_fd) :
1175         NPT_BsdSocketStream(socket_fd) {}
1176 
1177     // NPT_OutputStream methods
1178     NPT_Result Write(const void* buffer,
1179                      NPT_Size    bytes_to_write,
1180                      NPT_Size*   bytes_written);
Seek(NPT_Position offset)1181     NPT_Result Seek(NPT_Position offset) {
1182         return NPT_BsdSocketStream::Seek(offset); }
Tell(NPT_Position & where)1183     NPT_Result Tell(NPT_Position& where) {
1184         return NPT_BsdSocketStream::Tell(where);
1185     }
1186     NPT_Result Flush();
1187 };
1188 
1189 /*----------------------------------------------------------------------
1190 |   NPT_BsdSocketOutputStream::Write
1191 +---------------------------------------------------------------------*/
1192 NPT_Result
Write(const void * buffer,NPT_Size bytes_to_write,NPT_Size * bytes_written)1193 NPT_BsdSocketOutputStream::Write(const void*  buffer,
1194                                  NPT_Size     bytes_to_write,
1195                                  NPT_Size*    bytes_written)
1196 {
1197     // FIXME: A temporary hack to get to the Cancel method
1198     if (buffer == NULL) {
1199         NPT_LOG_INFO("Cancelling BSD socket output stream through write...");
1200 
1201         m_SocketFdReference->Cancel(true);
1202 
1203         NPT_LOG_INFO("Done cancelling BSD socket output stream through write.");
1204         return NPT_SUCCESS;
1205     }
1206 
1207     int tries_left = 100;
1208     for (;;) {
1209         // if we're blocking, wait until the socket is writeable
1210         if (m_SocketFdReference->m_WriteTimeout) {
1211             NPT_Result result = m_SocketFdReference->WaitUntilWriteable();
1212             if (result != NPT_SUCCESS) return result;
1213         }
1214 
1215         int flags = 0;
1216     #if defined(MSG_NOSIGNAL)
1217         // for some BSD stacks, ask for EPIPE to be returned instead
1218         // of sending a SIGPIPE signal to the process
1219         flags |= MSG_NOSIGNAL;
1220     #endif
1221 
1222         // write to the socket
1223         NPT_LOG_FINEST_1("writing %d to socket", (int)bytes_to_write);
1224         ssize_t nb_written = send(m_SocketFdReference->m_SocketFd,
1225                                   (SocketConstBuffer)buffer,
1226                                   bytes_to_write, flags);
1227         NPT_LOG_FINEST_1("send returned %d", (int)nb_written);
1228 
1229         if (nb_written <= 0) {
1230             if (bytes_written) *bytes_written = 0;
1231             if (m_SocketFdReference->m_Cancelled) return NPT_ERROR_CANCELLED;
1232 
1233             if (nb_written == 0) {
1234                 NPT_LOG_FINE("connection reset");
1235                 return NPT_ERROR_CONNECTION_RESET;
1236             } else {
1237                 NPT_Result result = MapErrorCode(GetSocketError());
1238                 NPT_LOG_FINE_1("socket result = %d", result);
1239                     if (m_SocketFdReference->m_WriteTimeout && result == NPT_ERROR_WOULD_BLOCK) {
1240                         // Well, the socket was writeable but then failed with "would block"
1241                         // Loop back and try again, a certain number of times only...
1242                         NPT_LOG_FINE_1("Socket failed with 'would block' even though writeable?! Tries left: %d", tries_left);
1243                         if (--tries_left < 0) {
1244                             NPT_LOG_SEVERE("Failed to send any data, send kept returning with 'would block' even though timeout is not 0");
1245                             return NPT_ERROR_WRITE_FAILED;
1246                         }
1247                         continue;
1248                     }
1249                 return result;
1250             }
1251         }
1252 
1253         // update position and return
1254         if (bytes_written) *bytes_written = (NPT_Size)nb_written;
1255         m_SocketFdReference->m_Position += nb_written;
1256         return NPT_SUCCESS;
1257     }
1258 }
1259 
1260 /*----------------------------------------------------------------------
1261 |   NPT_BsdSocketOutputStream::Flush
1262 +---------------------------------------------------------------------*/
1263 NPT_Result
Flush()1264 NPT_BsdSocketOutputStream::Flush()
1265 {
1266     int       args = 0;
1267     socklen_t size = sizeof(args);
1268 
1269     NPT_LOG_FINEST("flushing socket");
1270 
1271     // get the value of the nagle algorithm
1272     if (getsockopt(m_SocketFdReference->m_SocketFd,
1273                   IPPROTO_TCP,
1274                   TCP_NODELAY,
1275                   (char*)&args,
1276                   &size)) {
1277         return NPT_ERROR_GETSOCKOPT_FAILED;
1278     }
1279 
1280     // return now if nagle was already off
1281     if (args == 1) return NPT_SUCCESS;
1282 
1283     // disable the nagle algorithm
1284     args = 1;
1285     if (setsockopt(m_SocketFdReference->m_SocketFd,
1286                    IPPROTO_TCP,
1287                    TCP_NODELAY,
1288                    (const char*)&args,
1289                    sizeof(args))) {
1290         return NPT_ERROR_SETSOCKOPT_FAILED;
1291     }
1292 
1293     // send an empty buffer to flush
1294     int flags = 0;
1295 #if defined(MSG_NOSIGNAL)
1296     // for some BSD stacks, ask for EPIPE to be returned instead
1297     // of sending a SIGPIPE signal to the process
1298     flags |= MSG_NOSIGNAL;
1299 #endif
1300     char dummy = 0;
1301     send(m_SocketFdReference->m_SocketFd, &dummy, 0, flags);
1302 
1303     // restore the nagle algorithm to its original setting
1304     args = 0;
1305     if (setsockopt(m_SocketFdReference->m_SocketFd,
1306                    IPPROTO_TCP,
1307                    TCP_NODELAY,
1308                    (const char*)&args,
1309                    sizeof(args))) {
1310         return NPT_ERROR_SETSOCKOPT_FAILED;
1311     }
1312 
1313     return NPT_SUCCESS;
1314 }
1315 
1316 /*----------------------------------------------------------------------
1317 |   NPT_BsdSocket
1318 +---------------------------------------------------------------------*/
1319 class NPT_BsdSocket : public NPT_SocketInterface
1320 {
1321  public:
1322     // constructors and destructor
1323              NPT_BsdSocket(SocketFd fd, NPT_Flags flags);
1324     virtual ~NPT_BsdSocket();
1325 
1326     // methods
1327     NPT_Result RefreshInfo();
1328 
1329     // NPT_SocketInterface methods
1330     NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true);
1331     NPT_Result Connect(const NPT_SocketAddress& address, NPT_Timeout timeout);
1332     NPT_Result WaitForConnection(NPT_Timeout timeout);
1333     NPT_Result GetInputStream(NPT_InputStreamReference& stream);
1334     NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
1335     NPT_Result GetInfo(NPT_SocketInfo& info);
1336     NPT_Result SetReadTimeout(NPT_Timeout timeout);
1337     NPT_Result SetWriteTimeout(NPT_Timeout timeout);
1338     NPT_Result Cancel(bool shutdown);
1339 
1340  protected:
1341     // members
1342     NPT_BsdSocketFdReference m_SocketFdReference;
1343     NPT_SocketInfo           m_Info;
1344 };
1345 
1346 /*----------------------------------------------------------------------
1347 |   NPT_BsdSocket::NPT_BsdSocket
1348 +---------------------------------------------------------------------*/
NPT_BsdSocket(SocketFd fd,NPT_Flags flags)1349 NPT_BsdSocket::NPT_BsdSocket(SocketFd fd, NPT_Flags flags) :
1350     m_SocketFdReference(new NPT_BsdSocketFd(fd, flags))
1351 {
1352     // disable the SIGPIPE signal
1353 #if defined(SO_NOSIGPIPE)
1354     int option = 1;
1355     (void)setsockopt(m_SocketFdReference->m_SocketFd,
1356                      SOL_SOCKET,
1357                      SO_NOSIGPIPE,
1358                      (SocketOption)&option,
1359                      sizeof(option));
1360 #elif defined(SIGPIPE)
1361     signal(SIGPIPE, SIG_IGN);
1362 #endif
1363 
1364     RefreshInfo();
1365 }
1366 
1367 /*----------------------------------------------------------------------
1368 |   NPT_BsdSocket::~NPT_BsdSocket
1369 +---------------------------------------------------------------------*/
~NPT_BsdSocket()1370 NPT_BsdSocket::~NPT_BsdSocket()
1371 {
1372     // release the socket fd reference
1373     m_SocketFdReference = NULL;
1374 }
1375 
1376 /*----------------------------------------------------------------------
1377 |   NPT_BsdSocket::Bind
1378 +---------------------------------------------------------------------*/
1379 NPT_Result
Bind(const NPT_SocketAddress & address,bool reuse_address)1380 NPT_BsdSocket::Bind(const NPT_SocketAddress& address, bool reuse_address)
1381 {
1382     // set socket options
1383     if (reuse_address) {
1384         NPT_LOG_FINE("setting SO_REUSEADDR option on socket");
1385         int option = 1;
1386         if (setsockopt(m_SocketFdReference->m_SocketFd,
1387                        SOL_SOCKET,
1388                        SO_REUSEADDR,
1389                        (SocketOption)&option,
1390                        sizeof(option))) {
1391             return MapErrorCode(GetSocketError());
1392         }
1393     }
1394 
1395     // convert the address
1396     NPT_sockaddr_in inet_address;
1397     socklen_t       inet_address_length;
1398     SocketAddressToInetAddress(address, inet_address, inet_address_length);
1399 
1400 #if defined(_XBOX)
1401     if( address.GetIpAddress().AsLong() != NPT_IpAddress::Any.AsLong() ) {
1402         // Xbox can't bind to specific address, defaulting to ANY
1403         SocketAddressToInetAddress(NPT_SocketAddress(NPT_IpAddress::Any, address.GetPort()), &inet_address);
1404     }
1405 #endif
1406 
1407     // bind the socket
1408     if (bind(m_SocketFdReference->m_SocketFd,
1409              &inet_address.sa,
1410              inet_address_length) < 0) {
1411         return MapErrorCode(GetSocketError());
1412     }
1413 
1414     // refresh socket info
1415     RefreshInfo();
1416 
1417     return NPT_SUCCESS;
1418 }
1419 
1420 /*----------------------------------------------------------------------
1421 |   NPT_BsdSocket::Connect
1422 +---------------------------------------------------------------------*/
1423 NPT_Result
Connect(const NPT_SocketAddress &,NPT_Timeout)1424 NPT_BsdSocket::Connect(const NPT_SocketAddress&, NPT_Timeout)
1425 {
1426     // this is unsupported unless overridden in a derived class
1427     return NPT_ERROR_NOT_SUPPORTED;
1428 }
1429 
1430 /*----------------------------------------------------------------------
1431 |   NPT_BsdSocket::WaitForConnection
1432 +---------------------------------------------------------------------*/
1433 NPT_Result
WaitForConnection(NPT_Timeout)1434 NPT_BsdSocket::WaitForConnection(NPT_Timeout)
1435 {
1436     // this is unsupported unless overridden in a derived class
1437     return NPT_ERROR_NOT_SUPPORTED;
1438 }
1439 
1440 /*----------------------------------------------------------------------
1441 |   NPT_BsdSocket::GetInputStream
1442 +---------------------------------------------------------------------*/
1443 NPT_Result
GetInputStream(NPT_InputStreamReference & stream)1444 NPT_BsdSocket::GetInputStream(NPT_InputStreamReference& stream)
1445 {
1446     // default value
1447     stream = NULL;
1448 
1449     // check that we have a socket
1450     if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
1451 
1452     // create a stream
1453     stream = new NPT_BsdSocketInputStream(m_SocketFdReference);
1454 
1455     return NPT_SUCCESS;
1456 }
1457 
1458 /*----------------------------------------------------------------------
1459 |   NPT_BsdSocket::GetOutputStream
1460 +---------------------------------------------------------------------*/
1461 NPT_Result
GetOutputStream(NPT_OutputStreamReference & stream)1462 NPT_BsdSocket::GetOutputStream(NPT_OutputStreamReference& stream)
1463 {
1464     // default value
1465     stream = NULL;
1466 
1467     // check that the file is open
1468     if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
1469 
1470     // create a stream
1471     stream = new NPT_BsdSocketOutputStream(m_SocketFdReference);
1472 
1473     return NPT_SUCCESS;
1474 }
1475 
1476 /*----------------------------------------------------------------------
1477 |   NPT_BsdSocket::GetInfo
1478 +---------------------------------------------------------------------*/
1479 NPT_Result
GetInfo(NPT_SocketInfo & info)1480 NPT_BsdSocket::GetInfo(NPT_SocketInfo& info)
1481 {
1482     // return the cached info
1483     info = m_Info;
1484 
1485     return NPT_SUCCESS;
1486 }
1487 
1488 /*----------------------------------------------------------------------
1489 |   NPT_BsdSocket::RefreshInfo
1490 +---------------------------------------------------------------------*/
1491 NPT_Result
RefreshInfo()1492 NPT_BsdSocket::RefreshInfo()
1493 {
1494     // check that we have a socket
1495     if (m_SocketFdReference.IsNull()) return NPT_ERROR_INVALID_STATE;
1496 
1497     // get the local socket addr
1498     NPT_sockaddr_in inet_address;
1499     socklen_t       inet_address_length = sizeof(inet_address);
1500     if (getsockname(m_SocketFdReference->m_SocketFd,
1501                     &inet_address.sa,
1502                     &inet_address_length) == 0) {
1503         InetAddressToSocketAddress(inet_address, m_Info.local_address);
1504     }
1505 
1506     // get the peer socket addr
1507     if (getpeername(m_SocketFdReference->m_SocketFd,
1508                     &inet_address.sa,
1509                     &inet_address_length) == 0) {
1510         InetAddressToSocketAddress(inet_address, m_Info.remote_address);
1511     }
1512 
1513     return NPT_SUCCESS;
1514 }
1515 
1516 /*----------------------------------------------------------------------
1517 |   NPT_BsdSocket::SetReadTimeout
1518 +---------------------------------------------------------------------*/
1519 NPT_Result
SetReadTimeout(NPT_Timeout timeout)1520 NPT_BsdSocket::SetReadTimeout(NPT_Timeout timeout)
1521 {
1522     m_SocketFdReference->m_ReadTimeout = timeout;
1523     return NPT_SUCCESS;
1524 }
1525 
1526 /*----------------------------------------------------------------------
1527 |   NPT_BsdSocket::SetWriteTimeout
1528 +---------------------------------------------------------------------*/
1529 NPT_Result
SetWriteTimeout(NPT_Timeout timeout)1530 NPT_BsdSocket::SetWriteTimeout(NPT_Timeout timeout)
1531 {
1532     m_SocketFdReference->m_WriteTimeout = timeout;
1533     setsockopt(m_SocketFdReference->m_SocketFd,
1534                SOL_SOCKET,
1535                SO_SNDTIMEO,
1536                (SocketOption)&timeout,
1537                sizeof(timeout));
1538     return NPT_SUCCESS;
1539 }
1540 
1541 /*----------------------------------------------------------------------
1542 |   NPT_BsdSocket::Cancel
1543 +---------------------------------------------------------------------*/
1544 NPT_Result
Cancel(bool do_shutdown)1545 NPT_BsdSocket::Cancel(bool do_shutdown)
1546 {
1547     return m_SocketFdReference->Cancel(do_shutdown);
1548 }
1549 
1550 /*----------------------------------------------------------------------
1551 |   NPT_Socket::~NPT_Socket
1552 +---------------------------------------------------------------------*/
~NPT_Socket()1553 NPT_Socket::~NPT_Socket()
1554 {
1555     delete m_SocketDelegate;
1556 }
1557 
1558 /*----------------------------------------------------------------------
1559 |   NPT_BsdUdpSocket
1560 +---------------------------------------------------------------------*/
1561 class NPT_BsdUdpSocket : public    NPT_UdpSocketInterface,
1562                          protected NPT_BsdSocket
1563 
1564 {
1565  public:
1566     // constructor and destructor
1567              NPT_BsdUdpSocket(NPT_Flags flags);
~NPT_BsdUdpSocket()1568     virtual ~NPT_BsdUdpSocket() {}
1569 
1570     // NPT_SocketInterface methods
1571     NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true);
1572     NPT_Result Connect(const NPT_SocketAddress& address,
1573                        NPT_Timeout              timeout);
1574 
1575     // NPT_UdpSocketInterface methods
1576     NPT_Result Send(const NPT_DataBuffer&    packet,
1577                     const NPT_SocketAddress* address);
1578     NPT_Result Receive(NPT_DataBuffer&     packet,
1579                        NPT_SocketAddress*  address);
1580 
1581     // friends
1582     friend class NPT_UdpSocket;
1583 };
1584 
1585 /*----------------------------------------------------------------------
1586 |   NPT_BsdUdpSocket::NPT_BsdUdpSocket
1587 +---------------------------------------------------------------------*/
NPT_BsdUdpSocket(NPT_Flags flags)1588 NPT_BsdUdpSocket::NPT_BsdUdpSocket(NPT_Flags flags) :
1589     NPT_BsdSocket(socket(NPT_SOCKETS_PF_INET, SOCK_DGRAM, 0), flags)
1590 {
1591     // set default socket options
1592     int option = 1;
1593     (void)setsockopt(m_SocketFdReference->m_SocketFd,
1594                      SOL_SOCKET,
1595                      SO_BROADCAST,
1596                      (SocketOption)&option,
1597                      sizeof(option));
1598 
1599 #if defined(_XBOX)
1600     // set flag on the socket to allow sending of multicast
1601     if (!NPT_BSD_SOCKET_IS_INVALID(m_SocketFdReference->m_SocketFd)) {
1602         *(DWORD*)((char*)m_SocketFdReference->m_SocketFd+0xc) |= 0x02000000;
1603     }
1604 #endif
1605 }
1606 
1607 /*----------------------------------------------------------------------
1608 |   NPT_BsdUdpSocket::Bind
1609 +---------------------------------------------------------------------*/
1610 NPT_Result
Bind(const NPT_SocketAddress & address,bool reuse_address)1611 NPT_BsdUdpSocket::Bind(const NPT_SocketAddress& address, bool reuse_address)
1612 {
1613     if (reuse_address) {
1614 #if defined(SO_REUSEPORT)
1615         // some implementations (BSD 4.4) need this in addition to SO_REUSEADDR
1616         NPT_LOG_FINE("setting SO_REUSEPORT option on socket");
1617         int option = 1;
1618         if (setsockopt(m_SocketFdReference->m_SocketFd,
1619                        SOL_SOCKET,
1620                        SO_REUSEPORT,
1621                        (SocketOption)&option,
1622                        sizeof(option))) {
1623             return MapErrorCode(GetSocketError());
1624         }
1625 #endif
1626     }
1627     // call the inherited method
1628     return NPT_BsdSocket::Bind(address, reuse_address);
1629 }
1630 
1631 /*----------------------------------------------------------------------
1632 |   NPT_BsdUdpSocket::Connect
1633 +---------------------------------------------------------------------*/
1634 NPT_Result
Connect(const NPT_SocketAddress & address,NPT_Timeout)1635 NPT_BsdUdpSocket::Connect(const NPT_SocketAddress& address,
1636                           NPT_Timeout /* ignored */)
1637 {
1638     // setup an address structure
1639     NPT_sockaddr_in inet_address;
1640     socklen_t       inet_address_length;
1641     SocketAddressToInetAddress(address, inet_address, inet_address_length);
1642 
1643     // connect so that we can have some addr bound to the socket
1644     NPT_LOG_FINE_2("connecting to %s, port %d",
1645                    address.GetIpAddress().ToString().GetChars(),
1646                    address.GetPort());
1647     int io_result = connect(m_SocketFdReference->m_SocketFd,
1648                             &inet_address.sa,
1649                             inet_address_length);
1650     if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
1651         NPT_Result result = MapErrorCode(GetSocketError());
1652         NPT_LOG_FINE_1("socket error %d", result);
1653         return result;
1654     }
1655 
1656     // refresh socket info
1657     RefreshInfo();
1658 
1659     return NPT_SUCCESS;
1660 }
1661 
1662 /*----------------------------------------------------------------------
1663 |   NPT_BsdUdpSocket::Send
1664 +---------------------------------------------------------------------*/
1665 NPT_Result
Send(const NPT_DataBuffer & packet,const NPT_SocketAddress * address)1666 NPT_BsdUdpSocket::Send(const NPT_DataBuffer&    packet,
1667                        const NPT_SocketAddress* address)
1668 {
1669     // get the packet buffer
1670     const NPT_Byte* buffer        = packet.GetData();
1671     ssize_t         buffer_length = packet.GetDataSize();
1672 
1673     // if we're blocking, wait until the socket is writeable
1674     if (m_SocketFdReference->m_WriteTimeout) {
1675         NPT_Result result = m_SocketFdReference->WaitUntilWriteable();
1676         if (result != NPT_SUCCESS) return result;
1677     }
1678 
1679     // send the packet buffer
1680     ssize_t io_result;
1681     if (address) {
1682         // send to the specified address
1683 
1684         // setup an address structure
1685         NPT_sockaddr_in inet_address;
1686         socklen_t       inet_address_length;
1687         SocketAddressToInetAddress(*address, inet_address, inet_address_length);
1688 
1689         // send the data
1690         NPT_LOG_FINEST_2("sending datagram to %s port %d",
1691                          address->GetIpAddress().ToString().GetChars(),
1692                          address->GetPort());
1693         io_result = sendto(m_SocketFdReference->m_SocketFd,
1694                            (SocketConstBuffer)buffer,
1695                            buffer_length,
1696                            0,
1697                            &inet_address.sa,
1698                            inet_address_length);
1699     } else {
1700         int flags = 0;
1701 #if defined(MSG_NOSIGNAL)
1702         // for some BSD stacks, ask for EPIPE to be returned instead
1703         // of sending a SIGPIPE signal to the process
1704         flags |= MSG_NOSIGNAL;
1705 #endif
1706 
1707         // send to whichever addr the socket is connected
1708         NPT_LOG_FINEST("sending datagram");
1709         io_result = send(m_SocketFdReference->m_SocketFd,
1710                          (SocketConstBuffer)buffer,
1711                          buffer_length,
1712                          flags);
1713     }
1714 
1715     // check result
1716     NPT_LOG_FINEST_1("send/sendto returned %d", (int)io_result);
1717     if (m_SocketFdReference->m_Cancelled) return NPT_ERROR_CANCELLED;
1718     if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
1719         NPT_Result result = MapErrorCode(GetSocketError());
1720         NPT_LOG_FINE_1("socket error %d", result);
1721         return result;
1722     }
1723 
1724     // update position and return
1725     m_SocketFdReference->m_Position += buffer_length;
1726     return NPT_SUCCESS;
1727 }
1728 
1729 /*----------------------------------------------------------------------
1730 |   NPT_BsdUdpSocket::Receive
1731 +---------------------------------------------------------------------*/
1732 NPT_Result
Receive(NPT_DataBuffer & packet,NPT_SocketAddress * address)1733 NPT_BsdUdpSocket::Receive(NPT_DataBuffer&    packet,
1734                           NPT_SocketAddress* address)
1735 {
1736     // get the packet buffer
1737     NPT_Byte* buffer      = packet.UseData();
1738     ssize_t   buffer_size = packet.GetBufferSize();
1739 
1740     // check that we have some space to receive
1741     if (buffer_size == 0) return NPT_ERROR_INVALID_PARAMETERS;
1742 
1743     // if we're blocking, wait until the socket is readable
1744     if (m_SocketFdReference->m_ReadTimeout) {
1745         NPT_Result result = m_SocketFdReference->WaitUntilReadable();
1746         if (result != NPT_SUCCESS) return result;
1747     }
1748 
1749     // receive a packet
1750     ssize_t io_result = 0;
1751     if (address) {
1752         NPT_sockaddr_in inet_address;
1753         socklen_t       inet_address_length = sizeof(inet_address);
1754 
1755         NPT_LOG_FINEST_2("receiving dagagram from %s port %d",
1756                          address->GetIpAddress().ToString().GetChars(),
1757                          address->GetPort());
1758         io_result = recvfrom(m_SocketFdReference->m_SocketFd,
1759                              (SocketBuffer)buffer,
1760                              buffer_size,
1761                              0,
1762                              &inet_address.sa,
1763                              &inet_address_length);
1764 
1765         // convert the address format
1766         if (!NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
1767             InetAddressToSocketAddress(inet_address, *address);
1768         }
1769     } else {
1770         NPT_LOG_FINEST("receiving datagram");
1771         io_result = recv(m_SocketFdReference->m_SocketFd,
1772                          (SocketBuffer)buffer,
1773                          buffer_size,
1774                          0);
1775     }
1776 
1777     // check result
1778     NPT_LOG_FINEST_1("recv/recvfrom returned %d", (int)io_result);
1779     if (m_SocketFdReference->m_Cancelled) {
1780         packet.SetDataSize(0);
1781         return NPT_ERROR_CANCELLED;
1782     }
1783     if (NPT_BSD_SOCKET_CALL_FAILED(io_result)) {
1784         NPT_Result result = MapErrorCode(GetSocketError());
1785         NPT_LOG_FINE_1("socket error %d", result);
1786         packet.SetDataSize(0);
1787         return result;
1788     }
1789 
1790     // update position and return
1791     packet.SetDataSize((NPT_Size)io_result);
1792     m_SocketFdReference->m_Position += io_result;
1793     return NPT_SUCCESS;
1794 }
1795 
1796 /*----------------------------------------------------------------------
1797 |   NPT_UdpSocket::NPT_UdpSocket
1798 +---------------------------------------------------------------------*/
NPT_UdpSocket(NPT_Flags flags)1799 NPT_UdpSocket::NPT_UdpSocket(NPT_Flags flags)
1800 {
1801     NPT_BsdUdpSocket* delegate = new NPT_BsdUdpSocket(flags);
1802     m_SocketDelegate    = delegate;
1803     m_UdpSocketDelegate = delegate;
1804 }
1805 
1806 /*----------------------------------------------------------------------
1807 |   NPT_UdpSocket::NPT_UdpSocket
1808 +---------------------------------------------------------------------*/
NPT_UdpSocket(NPT_UdpSocketInterface * delegate)1809 NPT_UdpSocket::NPT_UdpSocket(NPT_UdpSocketInterface* delegate) :
1810     m_UdpSocketDelegate(delegate)
1811 {
1812 }
1813 
1814 /*----------------------------------------------------------------------
1815 |   NPT_UdpSocket::~NPT_UdpSocket
1816 +---------------------------------------------------------------------*/
~NPT_UdpSocket()1817 NPT_UdpSocket::~NPT_UdpSocket()
1818 {
1819     delete m_UdpSocketDelegate;
1820 
1821     // set the delegate pointers to NULL because it is shared by the
1822     // base classes, and we only want to delete the object once
1823     m_UdpSocketDelegate = NULL;
1824     m_SocketDelegate    = NULL;
1825 }
1826 
1827 /*----------------------------------------------------------------------
1828 |   NPT_BsdUdpMulticastSocket
1829 +---------------------------------------------------------------------*/
1830 class NPT_BsdUdpMulticastSocket : public    NPT_UdpMulticastSocketInterface,
1831                                   protected NPT_BsdUdpSocket
1832 
1833 {
1834  public:
1835     // methods
1836      NPT_BsdUdpMulticastSocket(NPT_Flags flags);
1837     ~NPT_BsdUdpMulticastSocket();
1838 
1839     // NPT_UdpMulticastSocketInterface methods
1840     NPT_Result JoinGroup(const NPT_IpAddress& group,
1841                          const NPT_IpAddress& iface);
1842     NPT_Result LeaveGroup(const NPT_IpAddress& group,
1843                           const NPT_IpAddress& iface);
1844     NPT_Result SetTimeToLive(unsigned char ttl);
1845     NPT_Result SetInterface(const NPT_IpAddress& iface);
1846 
1847     // friends
1848     friend class NPT_UdpMulticastSocket;
1849 };
1850 
1851 /*----------------------------------------------------------------------
1852 |   NPT_BsdUdpMulticastSocket::NPT_BsdUdpMulticastSocket
1853 +---------------------------------------------------------------------*/
NPT_BsdUdpMulticastSocket(NPT_Flags flags)1854 NPT_BsdUdpMulticastSocket::NPT_BsdUdpMulticastSocket(NPT_Flags flags) :
1855     NPT_BsdUdpSocket(flags)
1856 {
1857 #if !defined(_XBOX)
1858     int option = 1;
1859     setsockopt(m_SocketFdReference->m_SocketFd,
1860                IPPROTO_IP,
1861                IP_MULTICAST_LOOP,
1862                (SocketOption)&option,
1863                sizeof(option));
1864 #endif
1865 }
1866 
1867 /*----------------------------------------------------------------------
1868 |   NPT_BsdUdpMulticastSocket::~NPT_BsdUdpMulticastSocket
1869 +---------------------------------------------------------------------*/
~NPT_BsdUdpMulticastSocket()1870 NPT_BsdUdpMulticastSocket::~NPT_BsdUdpMulticastSocket()
1871 {
1872 }
1873 
1874 #if defined(_XBOX)
1875 /*----------------------------------------------------------------------
1876 |   NPT_BsdUdpMulticastSocket::JoinGroup
1877 +---------------------------------------------------------------------*/
1878 NPT_Result
JoinGroup(const NPT_IpAddress & group,const NPT_IpAddress & iface)1879 NPT_BsdUdpMulticastSocket::JoinGroup(const NPT_IpAddress& group,
1880                                      const NPT_IpAddress& iface)
1881 {
1882     return NPT_SUCCESS;
1883 }
1884 #else
1885 /*----------------------------------------------------------------------
1886 |   NPT_BsdUdpMulticastSocket::JoinGroup
1887 +---------------------------------------------------------------------*/
1888 NPT_Result
JoinGroup(const NPT_IpAddress & group,const NPT_IpAddress & iface)1889 NPT_BsdUdpMulticastSocket::JoinGroup(const NPT_IpAddress& group,
1890                                      const NPT_IpAddress& iface)
1891 {
1892 #if defined(NPT_CONFIG_ENABLE_IPV6)
1893     struct ipv6_mreq mreq;
1894 
1895     // set the interface index
1896     mreq.ipv6mr_interface = 0; // FIXME: hardcoded to 0 for now
1897 
1898     // set the group address
1899     if (group.GetType() == NPT_IpAddress::IPV6) {
1900         NPT_CopyMemory(&mreq.ipv6mr_multiaddr.s6_addr[0], group.AsBytes(), 16);
1901     } else {
1902         NPT_SetMemory(&mreq.ipv6mr_multiaddr.s6_addr[0], 0, 10);
1903         mreq.ipv6mr_multiaddr.s6_addr[10] = 0xFF;
1904         mreq.ipv6mr_multiaddr.s6_addr[11] = 0xFF;
1905         NPT_CopyMemory(&mreq.ipv6mr_multiaddr.s6_addr[12], group.AsBytes(), 4);
1906     }
1907 
1908     // set socket option
1909     NPT_LOG_FINE_2("joining multicast addr %s group %s",
1910                    iface.ToString().GetChars(), group.ToString().GetChars());
1911     if (setsockopt(m_SocketFdReference->m_SocketFd,
1912                    IPPROTO_IPV6, IPV6_JOIN_GROUP,
1913                    (SocketOption)&mreq, sizeof(mreq))) {
1914         NPT_Result result = MapErrorCode(GetSocketError());
1915         NPT_LOG_FINE_1("setsockopt error %d", result);
1916         return result;
1917     }
1918     return NPT_SUCCESS;
1919 #else
1920     struct ip_mreq mreq;
1921 
1922     // set the interface address
1923     mreq.imr_interface.s_addr = htonl(iface.AsLong());
1924 
1925     // set the group address
1926     mreq.imr_multiaddr.s_addr = htonl(group.AsLong());
1927 
1928     // set socket option
1929     NPT_LOG_FINE_2("joining multicast addr %s group %s",
1930                    iface.ToString().GetChars(), group.ToString().GetChars());
1931     if (setsockopt(m_SocketFdReference->m_SocketFd,
1932                    IPPROTO_IP, IP_ADD_MEMBERSHIP,
1933                    (SocketOption)&mreq, sizeof(mreq))) {
1934         NPT_Result result = MapErrorCode(GetSocketError());
1935         NPT_LOG_FINE_1("setsockopt error %d", result);
1936         return result;
1937     }
1938     return NPT_SUCCESS;
1939 #endif
1940 }
1941 #endif
1942 
1943 #if defined(_XBOX)
1944 /*----------------------------------------------------------------------
1945 |   NPT_BsdUdpMulticastSocket::LeaveGroup
1946 +---------------------------------------------------------------------*/
1947 NPT_Result
LeaveGroup(const NPT_IpAddress & group,const NPT_IpAddress & iface)1948 NPT_BsdUdpMulticastSocket::LeaveGroup(const NPT_IpAddress& group,
1949                                       const NPT_IpAddress& iface)
1950 {
1951     return NPT_SUCCESS;
1952 }
1953 #else
1954 /*----------------------------------------------------------------------
1955 |   NPT_BsdUdpMulticastSocket::LeaveGroup
1956 +---------------------------------------------------------------------*/
1957 NPT_Result
LeaveGroup(const NPT_IpAddress & group,const NPT_IpAddress & iface)1958 NPT_BsdUdpMulticastSocket::LeaveGroup(const NPT_IpAddress& group,
1959                                       const NPT_IpAddress& iface)
1960 {
1961 #if defined(NPT_CONFIG_ENABLE_IPV6)
1962     struct ipv6_mreq mreq;
1963 
1964     // set the interface index
1965     mreq.ipv6mr_interface = 0; // FIXME: hardcoded to 0 for now
1966 
1967     // set the group address
1968     if (group.GetType() == NPT_IpAddress::IPV6) {
1969         NPT_CopyMemory(&mreq.ipv6mr_multiaddr.s6_addr[0], group.AsBytes(), 16);
1970     } else {
1971         NPT_SetMemory(&mreq.ipv6mr_multiaddr.s6_addr[0], 0, 10);
1972         mreq.ipv6mr_multiaddr.s6_addr[10] = 0xFF;
1973         mreq.ipv6mr_multiaddr.s6_addr[11] = 0xFF;
1974         NPT_CopyMemory(&mreq.ipv6mr_multiaddr.s6_addr[12], group.AsBytes(), 4);
1975     }
1976 
1977     // set socket option
1978     NPT_LOG_FINE_2("leaving multicast addr %s group %s",
1979                    iface.ToString().GetChars(), group.ToString().GetChars());
1980     if (setsockopt(m_SocketFdReference->m_SocketFd,
1981                    IPPROTO_IPV6, IPV6_LEAVE_GROUP,
1982                    (SocketOption)&mreq, sizeof(mreq))) {
1983         NPT_Result result = MapErrorCode(GetSocketError());
1984         NPT_LOG_FINE_1("setsockopt error %d", result);
1985         return result;
1986     }
1987 #else
1988     struct ip_mreq mreq;
1989 
1990     // set the interface address
1991     mreq.imr_interface.s_addr = htonl(iface.AsLong());
1992 
1993     // set the group address
1994     mreq.imr_multiaddr.s_addr = htonl(group.AsLong());
1995 
1996     // set socket option
1997     NPT_LOG_FINE_2("leaving multicast addr %s group %s",
1998                    iface.ToString().GetChars(), group.ToString().GetChars());
1999     if (setsockopt(m_SocketFdReference->m_SocketFd,
2000                    IPPROTO_IP, IP_DROP_MEMBERSHIP,
2001                    (SocketOption)&mreq, sizeof(mreq))) {
2002         NPT_Result result = MapErrorCode(GetSocketError());
2003         NPT_LOG_FINE_1("setsockopt error %d", result);
2004         return result;
2005     }
2006 #endif
2007 
2008     return NPT_SUCCESS;
2009 }
2010 #endif
2011 
2012 #if defined(_XBOX)
2013 /*----------------------------------------------------------------------
2014 |   NPT_BsdUdpMulticastSocket::SetInterface
2015 +---------------------------------------------------------------------*/
2016 NPT_Result
SetInterface(const NPT_IpAddress & iface)2017 NPT_BsdUdpMulticastSocket::SetInterface(const NPT_IpAddress& iface)
2018 {
2019     return NPT_SUCCESS;
2020 }
2021 #else
2022 /*----------------------------------------------------------------------
2023 |   NPT_BsdUdpMulticastSocket::SetInterface
2024 +---------------------------------------------------------------------*/
2025 NPT_Result
SetInterface(const NPT_IpAddress & iface)2026 NPT_BsdUdpMulticastSocket::SetInterface(const NPT_IpAddress& iface)
2027 {
2028 #if defined(NPT_CONFIG_ENABLE_IPV6)
2029     unsigned int ifindex = 0; // FIXME: hardcoded to 0 for now
2030 
2031     // set socket option
2032     NPT_LOG_FINE_1("setting multicast interface %s", iface.ToString().GetChars());
2033     if (setsockopt(m_SocketFdReference->m_SocketFd,
2034                    IPPROTO_IPV6, IPV6_MULTICAST_IF,
2035                    (char*)&ifindex, sizeof(ifindex))) {
2036         NPT_Result result = MapErrorCode(GetSocketError());
2037         NPT_LOG_FINE_1("setsockopt error %d", result);
2038         return result;
2039     }
2040 #else
2041     struct in_addr iface_addr;
2042     // set the interface address
2043     iface_addr.s_addr = htonl(iface.AsLong());
2044 
2045     // set socket option
2046     NPT_LOG_FINE_1("setting multicast interface %s", iface.ToString().GetChars());
2047     if (setsockopt(m_SocketFdReference->m_SocketFd,
2048                    IPPROTO_IP, IP_MULTICAST_IF,
2049                    (char*)&iface_addr, sizeof(iface_addr))) {
2050         NPT_Result result = MapErrorCode(GetSocketError());
2051         NPT_LOG_FINE_1("setsockopt error %d", result);
2052         return result;
2053     }
2054 #endif
2055 
2056     return NPT_SUCCESS;
2057 }
2058 #endif
2059 
2060 #if defined(_XBOX)
2061 /*----------------------------------------------------------------------
2062 |   NPT_BsdUdpMulticastSocket::SetTimeToLive
2063 +---------------------------------------------------------------------*/
2064 NPT_Result
SetTimeToLive(unsigned char ttl)2065 NPT_BsdUdpMulticastSocket::SetTimeToLive(unsigned char ttl)
2066 {
2067     return NPT_ERROR_NOT_IMPLEMENTED;
2068 }
2069 #else
2070 /*----------------------------------------------------------------------
2071 |   NPT_BsdUdpMulticastSocket::SetTimeToLive
2072 +---------------------------------------------------------------------*/
2073 NPT_Result
SetTimeToLive(unsigned char ttl)2074 NPT_BsdUdpMulticastSocket::SetTimeToLive(unsigned char ttl)
2075 {
2076 
2077     // set socket option
2078     NPT_LOG_FINE_1("setting multicast TTL to %d", (int)ttl);
2079 #if defined(NPT_CONFIG_ENABLE_IPV6)
2080     int ttl_opt = ttl;
2081     if (setsockopt(m_SocketFdReference->m_SocketFd,
2082                    IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
2083                    (SocketOption)&ttl_opt, sizeof(ttl_opt))) {
2084 #else
2085     unsigned char ttl_opt = ttl;
2086     if (setsockopt(m_SocketFdReference->m_SocketFd,
2087                    IPPROTO_IP, IP_MULTICAST_TTL,
2088                    (SocketOption)&ttl_opt, sizeof(ttl_opt))) {
2089 #endif
2090         NPT_Result result = MapErrorCode(GetSocketError());
2091         NPT_LOG_FINE_1("setsockopt error %d", result);
2092         return result;
2093     }
2094 
2095     return NPT_SUCCESS;
2096 }
2097 #endif
2098 
2099 /*----------------------------------------------------------------------
2100 |   NPT_UdpMulticastSocket::NPT_UdpMulticastSocket
2101 +---------------------------------------------------------------------*/
2102 NPT_UdpMulticastSocket::NPT_UdpMulticastSocket(NPT_Flags flags) :
2103     NPT_UdpSocket((NPT_UdpSocketInterface*)0)
2104 {
2105     NPT_BsdUdpMulticastSocket* delegate = new NPT_BsdUdpMulticastSocket(flags);
2106     m_SocketDelegate             = delegate;
2107     m_UdpSocketDelegate          = delegate;
2108     m_UdpMulticastSocketDelegate = delegate;
2109 }
2110 
2111 /*----------------------------------------------------------------------
2112 |   NPT_UdpMulticastSocket::~NPT_UdpMulticastSocket
2113 +---------------------------------------------------------------------*/
2114 NPT_UdpMulticastSocket::~NPT_UdpMulticastSocket()
2115 {
2116     delete m_UdpMulticastSocketDelegate;
2117 
2118     // set the delegate pointers to NULL because it is shared by the
2119     // base classes, and we only want to delete the object once
2120     m_SocketDelegate             = NULL;
2121     m_UdpSocketDelegate          = NULL;
2122     m_UdpMulticastSocketDelegate = NULL;
2123 }
2124 
2125 /*----------------------------------------------------------------------
2126 |   NPT_BsdTcpClientSocket
2127 +---------------------------------------------------------------------*/
2128 class NPT_BsdTcpClientSocket : protected NPT_BsdSocket
2129 {
2130  public:
2131     // methods
2132      NPT_BsdTcpClientSocket(NPT_Flags flags);
2133     ~NPT_BsdTcpClientSocket();
2134 
2135     // NPT_SocketInterface methods
2136     NPT_Result Connect(const NPT_SocketAddress& address,
2137                        NPT_Timeout              timeout);
2138     NPT_Result WaitForConnection(NPT_Timeout timeout);
2139 
2140 protected:
2141     // friends
2142     friend class NPT_TcpClientSocket;
2143 };
2144 
2145 /*----------------------------------------------------------------------
2146 |   NPT_BsdTcpClientSocket::NPT_BsdTcpClientSocket
2147 +---------------------------------------------------------------------*/
2148 NPT_BsdTcpClientSocket::NPT_BsdTcpClientSocket(NPT_Flags flags) :
2149     NPT_BsdSocket(socket(NPT_SOCKETS_PF_INET, SOCK_STREAM, 0), flags)
2150 {
2151 }
2152 
2153 /*----------------------------------------------------------------------
2154 |   NPT_BsdTcpClientSocket::~NPT_BsdTcpClientSocket
2155 +---------------------------------------------------------------------*/
2156 NPT_BsdTcpClientSocket::~NPT_BsdTcpClientSocket()
2157 {
2158 }
2159 
2160 /*----------------------------------------------------------------------
2161 |   NPT_BsdTcpClientSocket::Connect
2162 +---------------------------------------------------------------------*/
2163 NPT_Result
2164 NPT_BsdTcpClientSocket::Connect(const NPT_SocketAddress& address,
2165                                 NPT_Timeout              timeout)
2166 {
2167     // convert the address
2168     NPT_sockaddr_in inet_address;
2169     socklen_t       inet_address_length;
2170     SocketAddressToInetAddress(address, inet_address, inet_address_length);
2171 
2172     // initiate connection
2173     NPT_LOG_FINE_2("connecting to %s, port %d",
2174                    address.GetIpAddress().ToString().GetChars(),
2175                    address.GetPort());
2176     int io_result;
2177     io_result = connect(m_SocketFdReference->m_SocketFd,
2178                         &inet_address.sa,
2179                         inet_address_length);
2180     if (io_result == 0) {
2181         // immediate connection
2182         NPT_LOG_FINE("immediate connection");
2183 
2184         // get socket info
2185         RefreshInfo();
2186 
2187         return NPT_SUCCESS;
2188     }
2189 
2190     // test for errors
2191     NPT_Result result = MapErrorCode(GetSocketError());
2192 
2193     // if we're blocking, wait for a connection unless there was an error
2194     if (timeout && result == NPT_ERROR_WOULD_BLOCK) {
2195         return WaitForConnection(timeout);
2196     }
2197 
2198     return result;
2199 }
2200 
2201 /*----------------------------------------------------------------------
2202 |   NPT_BsdTcpClientSocket::WaitForConnection
2203 +---------------------------------------------------------------------*/
2204 NPT_Result
2205 NPT_BsdTcpClientSocket::WaitForConnection(NPT_Timeout timeout)
2206 {
2207     NPT_Result result = m_SocketFdReference->WaitForCondition(true, true, true, timeout);
2208 
2209     // get socket info
2210     RefreshInfo();
2211 
2212     return result;
2213 }
2214 
2215 /*----------------------------------------------------------------------
2216 |   NPT_TcpClientSocket::NPT_TcpClientSocket
2217 +---------------------------------------------------------------------*/
2218 NPT_TcpClientSocket::NPT_TcpClientSocket(NPT_Flags flags) :
2219     NPT_Socket(new NPT_BsdTcpClientSocket(flags))
2220 {
2221 }
2222 
2223 /*----------------------------------------------------------------------
2224 |   NPT_TcpClientSocket::NPT_TcpClientSocket
2225 +---------------------------------------------------------------------*/
2226 NPT_TcpClientSocket::~NPT_TcpClientSocket()
2227 {
2228     delete m_SocketDelegate;
2229 
2230     // set the delegate pointer to NULL because it is shared by the
2231     // base classes, and we only want to delete the object once
2232     m_SocketDelegate = NULL;
2233 }
2234 
2235 /*----------------------------------------------------------------------
2236 |   NPT_BsdTcpServerSocket
2237 +---------------------------------------------------------------------*/
2238 class NPT_BsdTcpServerSocket : public    NPT_TcpServerSocketInterface,
2239                                protected NPT_BsdSocket
2240 
2241 {
2242  public:
2243     // methods
2244      NPT_BsdTcpServerSocket(NPT_Flags flags);
2245     ~NPT_BsdTcpServerSocket();
2246 
2247     // NPT_SocketInterface methods
2248     NPT_Result GetInputStream(NPT_InputStreamReference& stream) {
2249         // no stream
2250         stream = NULL;
2251         return NPT_ERROR_NOT_SUPPORTED;
2252     }
2253     NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) {
2254         // no stream
2255         stream = NULL;
2256         return NPT_ERROR_NOT_SUPPORTED;
2257     }
2258 
2259     // NPT_TcpServerSocket methods
2260     NPT_Result Listen(unsigned int max_clients);
2261     NPT_Result WaitForNewClient(NPT_Socket*& client,
2262                                 NPT_Timeout  timeout,
2263                                 NPT_Flags    flags);
2264 
2265 protected:
2266     // members
2267     unsigned int m_ListenMax;
2268 
2269     // friends
2270     friend class NPT_TcpServerSocket;
2271 };
2272 
2273 /*----------------------------------------------------------------------
2274 |   NPT_BsdTcpServerSocket::NPT_BsdTcpServerSocket
2275 +---------------------------------------------------------------------*/
2276 NPT_BsdTcpServerSocket::NPT_BsdTcpServerSocket(NPT_Flags flags) :
2277     NPT_BsdSocket(socket(NPT_SOCKETS_PF_INET, SOCK_STREAM, 0), flags),
2278     m_ListenMax(0)
2279 {
2280 }
2281 
2282 /*----------------------------------------------------------------------
2283 |   NPT_BsdTcpServerSocket::~NPT_BsdTcpServerSocket
2284 +---------------------------------------------------------------------*/
2285 NPT_BsdTcpServerSocket::~NPT_BsdTcpServerSocket()
2286 {
2287 }
2288 
2289 /*----------------------------------------------------------------------
2290 |   NPT_BsdTcpServerSocket::Listen
2291 +---------------------------------------------------------------------*/
2292 NPT_Result
2293 NPT_BsdTcpServerSocket::Listen(unsigned int max_clients)
2294 {
2295     // listen for connections
2296     if (listen(m_SocketFdReference->m_SocketFd, max_clients) < 0) {
2297         m_ListenMax = 0;
2298         return NPT_ERROR_LISTEN_FAILED;
2299     }
2300     m_ListenMax = max_clients;
2301 
2302     return NPT_SUCCESS;
2303 }
2304 
2305 /*----------------------------------------------------------------------
2306 |   NPT_BsdTcpServerSocket::WaitForNewClient
2307 +---------------------------------------------------------------------*/
2308 NPT_Result
2309 NPT_BsdTcpServerSocket::WaitForNewClient(NPT_Socket*& client,
2310                                          NPT_Timeout  timeout,
2311                                          NPT_Flags    flags)
2312 {
2313     // default value
2314     client = NULL;
2315 
2316     // check that we are listening for clients
2317     if (m_ListenMax == 0) {
2318         Listen(NPT_TCP_SERVER_SOCKET_DEFAULT_LISTEN_COUNT);
2319     }
2320 
2321     // wait until the socket is readable or writeable
2322     NPT_LOG_FINER("waiting until socket is readable or writeable");
2323     NPT_Result result = m_SocketFdReference->WaitForCondition(true, true, false, timeout);
2324     if (result != NPT_SUCCESS) return result;
2325 
2326     NPT_LOG_FINER("accepting connection");
2327     NPT_sockaddr_in inet_address;
2328     socklen_t       inet_address_length = sizeof(inet_address);
2329     SocketFd socket_fd = accept(m_SocketFdReference->m_SocketFd, &inet_address.sa, &inet_address_length);
2330     if (NPT_BSD_SOCKET_IS_INVALID(socket_fd)) {
2331         if (m_SocketFdReference->m_Cancelled) return NPT_ERROR_CANCELLED;
2332         result = MapErrorCode(GetSocketError());
2333         NPT_LOG_FINE_1("socket error %d", result);
2334         return result;
2335     } else {
2336         client = new NPT_Socket(new NPT_BsdSocket(socket_fd, flags));
2337     }
2338 
2339     // done
2340     return result;
2341 }
2342 
2343 /*----------------------------------------------------------------------
2344 |   NPT_TcpServerSocket::NPT_TcpServerSocket
2345 +---------------------------------------------------------------------*/
2346 NPT_TcpServerSocket::NPT_TcpServerSocket(NPT_Flags flags)
2347 {
2348     NPT_BsdTcpServerSocket* delegate = new NPT_BsdTcpServerSocket(flags);
2349     m_SocketDelegate          = delegate;
2350     m_TcpServerSocketDelegate = delegate;
2351 }
2352 
2353 /*----------------------------------------------------------------------
2354 |   NPT_TcpServerSocket::NPT_TcpServerSocket
2355 +---------------------------------------------------------------------*/
2356 NPT_TcpServerSocket::~NPT_TcpServerSocket()
2357 {
2358     delete m_TcpServerSocketDelegate;
2359 
2360     // set the delegate pointers to NULL because it is shared by the
2361     // base classes, and we only want to delete the object once
2362     m_SocketDelegate          = NULL;
2363     m_TcpServerSocketDelegate = NULL;
2364 }
2365