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