2009-04-29 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mono / io-layer / sockets.c
1 /*
2  * sockets.c:  Socket handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <sys/poll.h>
19 #ifdef HAVE_SYS_FILIO_H
20 #include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
21 #endif
22 #ifdef HAVE_SYS_SOCKIO_H
23 #include <sys/sockio.h>    /* defines SIOCATMARK */
24 #endif
25 #include <unistd.h>
26 #include <fcntl.h>
27
28 #ifndef HAVE_MSG_NOSIGNAL
29 #include <signal.h>
30 #endif
31
32 #include <mono/io-layer/wapi.h>
33 #include <mono/io-layer/wapi-private.h>
34 #include <mono/io-layer/socket-private.h>
35 #include <mono/io-layer/handles-private.h>
36 #include <mono/io-layer/socket-wrappers.h>
37
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <netdb.h>
41 #include <arpa/inet.h>
42
43 #undef DEBUG
44
45 static guint32 startup_count=0;
46
47 static void socket_close (gpointer handle, gpointer data);
48
49 struct _WapiHandleOps _wapi_socket_ops = {
50         socket_close,           /* close */
51         NULL,                   /* signal */
52         NULL,                   /* own */
53         NULL,                   /* is_owned */
54         NULL,                   /* special_wait */
55         NULL                    /* prewait */
56 };
57
58 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
59
60 static void socket_ops_init (void)
61 {
62         /* No capabilities to register */
63 }
64
65 static void socket_close (gpointer handle, gpointer data)
66 {
67         int ret;
68         struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
69
70 #ifdef DEBUG
71         g_message ("%s: closing socket handle %p", __func__, handle);
72 #endif
73
74         if (startup_count == 0) {
75                 WSASetLastError (WSANOTINITIALISED);
76                 return;
77         }
78
79         /* Shutdown the socket for reading, to interrupt any potential
80          * receives that may be blocking for data.  See bug 75705.
81          */
82         shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
83         
84         do {
85                 ret = close (GPOINTER_TO_UINT(handle));
86         } while (ret == -1 && errno == EINTR &&
87                  !_wapi_thread_cur_apc_pending ());
88         
89         if (ret == -1) {
90                 gint errnum = errno;
91 #ifdef DEBUG
92                 g_message ("%s: close error: %s", __func__, strerror (errno));
93 #endif
94                 errnum = errno_to_WSA (errnum, __func__);
95                 WSASetLastError (errnum);
96         }
97
98         socket_handle->saved_error = 0;
99 }
100
101 int WSAStartup(guint32 requested, WapiWSAData *data)
102 {
103         if (data == NULL) {
104                 return(WSAEFAULT);
105         }
106
107         /* Insist on v2.0+ */
108         if (requested < MAKEWORD(2,0)) {
109                 return(WSAVERNOTSUPPORTED);
110         }
111
112         startup_count++;
113
114         /* I've no idea what is the minor version of the spec I read */
115         data->wHighVersion = MAKEWORD(2,2);
116         
117         data->wVersion = requested < data->wHighVersion? requested:
118                 data->wHighVersion;
119
120 #ifdef DEBUG
121         g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
122 #endif
123         
124         strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
125         strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
126         
127         return(0);
128 }
129
130 static gboolean
131 cleanup_close (gpointer handle, gpointer data)
132 {
133         _wapi_handle_ops_close (handle, NULL);
134         return TRUE;
135 }
136
137 int WSACleanup(void)
138 {
139 #ifdef DEBUG
140         g_message ("%s: cleaning up", __func__);
141 #endif
142
143         if (--startup_count) {
144                 /* Do nothing */
145                 return(0);
146         }
147
148         _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
149         return(0);
150 }
151
152 void WSASetLastError(int error)
153 {
154         SetLastError (error);
155 }
156
157 int WSAGetLastError(void)
158 {
159         return(GetLastError ());
160 }
161
162 int closesocket(guint32 fd)
163 {
164         gpointer handle = GUINT_TO_POINTER (fd);
165         
166         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
167                 WSASetLastError (WSAENOTSOCK);
168                 return(0);
169         }
170         
171         _wapi_handle_unref (handle);
172         return(0);
173 }
174
175 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
176 {
177         gpointer handle = GUINT_TO_POINTER (fd);
178         gpointer new_handle;
179         struct _WapiHandle_socket *socket_handle;
180         struct _WapiHandle_socket new_socket_handle = {0};
181         gboolean ok;
182         int new_fd;
183         
184         if (startup_count == 0) {
185                 WSASetLastError (WSANOTINITIALISED);
186                 return(INVALID_SOCKET);
187         }
188
189         if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
190                 WSASetLastError (WSAEFAULT);
191                 return(INVALID_SOCKET);
192         }
193         
194         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
195                 WSASetLastError (WSAENOTSOCK);
196                 return(INVALID_SOCKET);
197         }
198         
199         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
200                                   (gpointer *)&socket_handle);
201         if (ok == FALSE) {
202                 g_warning ("%s: error looking up socket handle %p",
203                            __func__, handle);
204                 WSASetLastError (WSAENOTSOCK);
205                 return(INVALID_SOCKET);
206         }
207         
208         do {
209                 new_fd = accept (fd, addr, addrlen);
210         } while (new_fd == -1 && errno == EINTR &&
211                  !_wapi_thread_cur_apc_pending());
212
213         if (new_fd == -1) {
214                 gint errnum = errno;
215 #ifdef DEBUG
216                 g_message ("%s: accept error: %s", __func__, strerror(errno));
217 #endif
218
219                 errnum = errno_to_WSA (errnum, __func__);
220                 WSASetLastError (errnum);
221                 
222                 return(INVALID_SOCKET);
223         }
224
225         if (new_fd >= _wapi_fd_reserve) {
226 #ifdef DEBUG
227                 g_message ("%s: File descriptor is too big", __func__);
228 #endif
229
230                 WSASetLastError (WSASYSCALLFAILURE);
231                 
232                 close (new_fd);
233                 
234                 return(INVALID_SOCKET);
235         }
236
237         new_socket_handle.domain = socket_handle->domain;
238         new_socket_handle.type = socket_handle->type;
239         new_socket_handle.protocol = socket_handle->protocol;
240         new_socket_handle.still_readable = 1;
241
242         new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd,
243                                           &new_socket_handle);
244         if(new_handle == _WAPI_HANDLE_INVALID) {
245                 g_warning ("%s: error creating socket handle", __func__);
246                 WSASetLastError (ERROR_GEN_FAILURE);
247                 return(INVALID_SOCKET);
248         }
249
250 #ifdef DEBUG
251         g_message ("%s: returning newly accepted socket handle %p with",
252                    __func__, new_handle);
253 #endif
254         
255         return(new_fd);
256 }
257
258 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
259 {
260         gpointer handle = GUINT_TO_POINTER (fd);
261         int ret;
262         
263         if (startup_count == 0) {
264                 WSASetLastError (WSANOTINITIALISED);
265                 return(SOCKET_ERROR);
266         }
267
268         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
269                 WSASetLastError (WSAENOTSOCK);
270                 return(SOCKET_ERROR);
271         }
272         
273         ret = bind (fd, my_addr, addrlen);
274         if (ret == -1) {
275                 gint errnum = errno;
276 #ifdef DEBUG
277                 g_message ("%s: bind error: %s", __func__, strerror(errno));
278 #endif
279                 errnum = errno_to_WSA (errnum, __func__);
280                 WSASetLastError (errnum);
281                 
282                 return(SOCKET_ERROR);
283         }
284         return(ret);
285 }
286
287 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
288                   socklen_t addrlen)
289 {
290         gpointer handle = GUINT_TO_POINTER (fd);
291         struct _WapiHandle_socket *socket_handle;
292         gboolean ok;
293         gint errnum;
294         
295         if (startup_count == 0) {
296                 WSASetLastError (WSANOTINITIALISED);
297                 return(SOCKET_ERROR);
298         }
299         
300         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
301                 WSASetLastError (WSAENOTSOCK);
302                 return(SOCKET_ERROR);
303         }
304         
305         if (connect (fd, serv_addr, addrlen) == -1) {
306                 struct pollfd fds;
307                 int so_error;
308                 socklen_t len;
309                 
310                 errnum = errno;
311                 
312                 if (errno != EINTR) {
313 #ifdef DEBUG
314                         g_message ("%s: connect error: %s", __func__,
315                                    strerror (errnum));
316 #endif
317
318                         errnum = errno_to_WSA (errnum, __func__);
319                         if (errnum == WSAEINPROGRESS)
320                                 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
321
322                         WSASetLastError (errnum);
323
324                         /* 
325                          * On solaris x86 getsockopt (SO_ERROR) is not set after 
326                          * connect () fails so we need to save this error.
327                          *
328                          * But don't do this for EWOULDBLOCK (bug 317315)
329                          */
330                         if (errnum != WSAEWOULDBLOCK) {
331                                 ok = _wapi_lookup_handle (handle,
332                                                           WAPI_HANDLE_SOCKET,
333                                                           (gpointer *)&socket_handle);
334                                 if (ok == FALSE) {
335                                         /* ECONNRESET means the socket was closed by another thread */
336                                         if (errnum != WSAECONNRESET)
337                                                 g_warning ("%s: error looking up socket handle %p", __func__, handle);
338                                 } else {
339                                         socket_handle->saved_error = errnum;
340                                 }
341                         }
342                         return(SOCKET_ERROR);
343                 }
344
345                 fds.fd = fd;
346                 fds.events = POLLOUT;
347                 while (poll (&fds, 1, -1) == -1 &&
348                        !_wapi_thread_cur_apc_pending ()) {
349                         if (errno != EINTR) {
350                                 errnum = errno_to_WSA (errno, __func__);
351
352 #ifdef DEBUG
353                                 g_message ("%s: connect poll error: %s",
354                                            __func__, strerror (errno));
355 #endif
356
357                                 WSASetLastError (errnum);
358                                 return(SOCKET_ERROR);
359                         }
360                 }
361
362                 len = sizeof(so_error);
363                 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
364                                 &len) == -1) {
365                         errnum = errno_to_WSA (errno, __func__);
366
367 #ifdef DEBUG
368                         g_message ("%s: connect getsockopt error: %s",
369                                    __func__, strerror (errno));
370 #endif
371
372                         WSASetLastError (errnum);
373                         return(SOCKET_ERROR);
374                 }
375                 
376                 if (so_error != 0) {
377                         errnum = errno_to_WSA (so_error, __func__);
378
379                         /* Need to save this socket error */
380                         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
381                                                   (gpointer *)&socket_handle);
382                         if (ok == FALSE) {
383                                 g_warning ("%s: error looking up socket handle %p", __func__, handle);
384                         } else {
385                                 socket_handle->saved_error = errnum;
386                         }
387                         
388 #ifdef DEBUG
389                         g_message ("%s: connect getsockopt returned error: %s",
390                                    __func__, strerror (so_error));
391 #endif
392
393                         WSASetLastError (errnum);
394                         return(SOCKET_ERROR);
395                 }
396         }
397                 
398         return(0);
399 }
400
401 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
402 {
403         gpointer handle = GUINT_TO_POINTER (fd);
404         int ret;
405         
406         if (startup_count == 0) {
407                 WSASetLastError (WSANOTINITIALISED);
408                 return(SOCKET_ERROR);
409         }
410         
411         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
412                 WSASetLastError (WSAENOTSOCK);
413                 return(SOCKET_ERROR);
414         }
415
416         ret = getpeername (fd, name, namelen);
417         if (ret == -1) {
418                 gint errnum = errno;
419 #ifdef DEBUG
420                 g_message ("%s: getpeername error: %s", __func__,
421                            strerror (errno));
422 #endif
423
424                 errnum = errno_to_WSA (errnum, __func__);
425                 WSASetLastError (errnum);
426
427                 return(SOCKET_ERROR);
428         }
429         
430         return(ret);
431 }
432
433 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
434 {
435         gpointer handle = GUINT_TO_POINTER (fd);
436         int ret;
437         
438         if (startup_count == 0) {
439                 WSASetLastError (WSANOTINITIALISED);
440                 return(SOCKET_ERROR);
441         }
442         
443         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
444                 WSASetLastError (WSAENOTSOCK);
445                 return(SOCKET_ERROR);
446         }
447
448         ret = getsockname (fd, name, namelen);
449         if (ret == -1) {
450                 gint errnum = errno;
451 #ifdef DEBUG
452                 g_message ("%s: getsockname error: %s", __func__,
453                            strerror (errno));
454 #endif
455
456                 errnum = errno_to_WSA (errnum, __func__);
457                 WSASetLastError (errnum);
458
459                 return(SOCKET_ERROR);
460         }
461         
462         return(ret);
463 }
464
465 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
466                      socklen_t *optlen)
467 {
468         gpointer handle = GUINT_TO_POINTER (fd);
469         int ret;
470         struct timeval tv;
471         void *tmp_val;
472         struct _WapiHandle_socket *socket_handle;
473         gboolean ok;
474         
475         if (startup_count == 0) {
476                 WSASetLastError (WSANOTINITIALISED);
477                 return(SOCKET_ERROR);
478         }
479         
480         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
481                 WSASetLastError (WSAENOTSOCK);
482                 return(SOCKET_ERROR);
483         }
484
485         tmp_val = optval;
486         if (level == SOL_SOCKET &&
487             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
488                 tmp_val = &tv;
489                 *optlen = sizeof (tv);
490         }
491
492         ret = getsockopt (fd, level, optname, tmp_val, optlen);
493         if (ret == -1) {
494                 gint errnum = errno;
495 #ifdef DEBUG
496                 g_message ("%s: getsockopt error: %s", __func__,
497                            strerror (errno));
498 #endif
499
500                 errnum = errno_to_WSA (errnum, __func__);
501                 WSASetLastError (errnum);
502                 
503                 return(SOCKET_ERROR);
504         }
505
506         if (level == SOL_SOCKET &&
507             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
508                 *((int *) optval)  = tv.tv_sec * 1000 + (tv.tv_usec / 1000);    // milli from micro
509                 *optlen = sizeof (int);
510         }
511
512         if (optname == SO_ERROR) {
513                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
514                                           (gpointer *)&socket_handle);
515                 if (ok == FALSE) {
516                         g_warning ("%s: error looking up socket handle %p",
517                                    __func__, handle);
518
519                         /* can't extract the last error */
520                         *((int *) optval) = errno_to_WSA (*((int *)optval),
521                                                           __func__);
522                 } else {
523                         if (*((int *)optval) != 0) {
524                                 *((int *) optval) = errno_to_WSA (*((int *)optval),
525                                                                   __func__);
526                                 socket_handle->saved_error = *((int *)optval);
527                         } else {
528                                 *((int *)optval) = socket_handle->saved_error;
529                         }
530                 }
531         }
532         
533         return(ret);
534 }
535
536 int _wapi_listen(guint32 fd, int backlog)
537 {
538         gpointer handle = GUINT_TO_POINTER (fd);
539         int ret;
540         
541         if (startup_count == 0) {
542                 WSASetLastError (WSANOTINITIALISED);
543                 return(SOCKET_ERROR);
544         }
545         
546         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
547                 WSASetLastError (WSAENOTSOCK);
548                 return(SOCKET_ERROR);
549         }
550         
551         ret = listen (fd, backlog);
552         if (ret == -1) {
553                 gint errnum = errno;
554 #ifdef DEBUG
555                 g_message ("%s: listen error: %s", __func__, strerror (errno));
556 #endif
557
558                 errnum = errno_to_WSA (errnum, __func__);
559                 WSASetLastError (errnum);
560
561                 return(SOCKET_ERROR);
562         }
563
564         return(0);
565 }
566
567 int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
568 {
569         return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
570 }
571
572 int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
573                    struct sockaddr *from, socklen_t *fromlen)
574 {
575         gpointer handle = GUINT_TO_POINTER (fd);
576         struct _WapiHandle_socket *socket_handle;
577         gboolean ok;
578         int ret;
579         
580         if (startup_count == 0) {
581                 WSASetLastError (WSANOTINITIALISED);
582                 return(SOCKET_ERROR);
583         }
584         
585         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
586                 WSASetLastError (WSAENOTSOCK);
587                 return(SOCKET_ERROR);
588         }
589         
590         do {
591                 ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
592         } while (ret == -1 && errno == EINTR &&
593                  !_wapi_thread_cur_apc_pending ());
594
595         if (ret == 0 && len > 0) {
596                 /* According to the Linux man page, recvfrom only
597                  * returns 0 when the socket has been shut down
598                  * cleanly.  Turn this into an EINTR to simulate win32
599                  * behaviour of returning EINTR when a socket is
600                  * closed while the recvfrom is blocking (we use a
601                  * shutdown() in socket_close() to trigger this.) See
602                  * bug 75705.
603                  */
604                 /* Distinguish between the socket being shut down at
605                  * the local or remote ends, and reads that request 0
606                  * bytes to be read
607                  */
608
609                 /* If this returns FALSE, it means the socket has been
610                  * closed locally.  If it returns TRUE, but
611                  * still_readable != 1 then shutdown
612                  * (SHUT_RD|SHUT_RDWR) has been called locally.
613                  */
614                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
615                                           (gpointer *)&socket_handle);
616                 if (ok == FALSE || socket_handle->still_readable != 1) {
617                         ret = -1;
618                         errno = EINTR;
619                 }
620         }
621         
622         if (ret == -1) {
623                 gint errnum = errno;
624 #ifdef DEBUG
625                 g_message ("%s: recv error: %s", __func__, strerror(errno));
626 #endif
627
628                 errnum = errno_to_WSA (errnum, __func__);
629                 WSASetLastError (errnum);
630                 
631                 return(SOCKET_ERROR);
632         }
633         return(ret);
634 }
635
636 static int
637 _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
638 {
639         gpointer handle = GUINT_TO_POINTER (fd);
640         struct _WapiHandle_socket *socket_handle;
641         gboolean ok;
642         int ret;
643         
644         if (startup_count == 0) {
645                 WSASetLastError (WSANOTINITIALISED);
646                 return(SOCKET_ERROR);
647         }
648         
649         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
650                 WSASetLastError (WSAENOTSOCK);
651                 return(SOCKET_ERROR);
652         }
653         
654         do {
655                 ret = recvmsg (fd, msg, recv_flags);
656         } while (ret == -1 && errno == EINTR &&
657                  !_wapi_thread_cur_apc_pending ());
658
659         if (ret == 0) {
660                 /* see _wapi_recvfrom */
661                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
662                                           (gpointer *)&socket_handle);
663                 if (ok == FALSE || socket_handle->still_readable != 1) {
664                         ret = -1;
665                         errno = EINTR;
666                 }
667         }
668         
669         if (ret == -1) {
670                 gint errnum = errno;
671 #ifdef DEBUG
672                 g_message ("%s: recvmsg error: %s", __func__, strerror(errno));
673 #endif
674
675                 errnum = errno_to_WSA (errnum, __func__);
676                 WSASetLastError (errnum);
677                 
678                 return(SOCKET_ERROR);
679         }
680         return(ret);
681 }
682
683 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
684 {
685         gpointer handle = GUINT_TO_POINTER (fd);
686         int ret;
687         
688         if (startup_count == 0) {
689                 WSASetLastError (WSANOTINITIALISED);
690                 return(SOCKET_ERROR);
691         }
692         
693         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
694                 WSASetLastError (WSAENOTSOCK);
695                 return(SOCKET_ERROR);
696         }
697
698         do {
699                 ret = send (fd, msg, len, send_flags);
700         } while (ret == -1 && errno == EINTR &&
701                  !_wapi_thread_cur_apc_pending ());
702
703         if (ret == -1) {
704                 gint errnum = errno;
705 #ifdef DEBUG
706                 g_message ("%s: send error: %s", __func__, strerror (errno));
707 #endif
708
709                 errnum = errno_to_WSA (errnum, __func__);
710                 WSASetLastError (errnum);
711                 
712                 return(SOCKET_ERROR);
713         }
714         return(ret);
715 }
716
717 int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
718                  const struct sockaddr *to, socklen_t tolen)
719 {
720         gpointer handle = GUINT_TO_POINTER (fd);
721         int ret;
722         
723         if (startup_count == 0) {
724                 WSASetLastError (WSANOTINITIALISED);
725                 return(SOCKET_ERROR);
726         }
727         
728         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
729                 WSASetLastError (WSAENOTSOCK);
730                 return(SOCKET_ERROR);
731         }
732         
733         do {
734                 ret = sendto (fd, msg, len, send_flags, to, tolen);
735         } while (ret == -1 && errno == EINTR &&
736                  !_wapi_thread_cur_apc_pending ());
737
738         if (ret == -1) {
739                 gint errnum = errno;
740 #ifdef DEBUG
741                 g_message ("%s: send error: %s", __func__, strerror (errno));
742 #endif
743
744                 errnum = errno_to_WSA (errnum, __func__);
745                 WSASetLastError (errnum);
746                 
747                 return(SOCKET_ERROR);
748         }
749         return(ret);
750 }
751
752 static int
753 _wapi_sendmsg(guint32 fd,  const struct msghdr *msg, int send_flags)
754 {
755         gpointer handle = GUINT_TO_POINTER (fd);
756         int ret;
757         
758         if (startup_count == 0) {
759                 WSASetLastError (WSANOTINITIALISED);
760                 return(SOCKET_ERROR);
761         }
762         
763         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
764                 WSASetLastError (WSAENOTSOCK);
765                 return(SOCKET_ERROR);
766         }
767         
768         do {
769                 ret = sendmsg (fd, msg, send_flags);
770         } while (ret == -1 && errno == EINTR &&
771                  !_wapi_thread_cur_apc_pending ());
772
773         if (ret == -1) {
774                 gint errnum = errno;
775 #ifdef DEBUG
776                 g_message ("%s: sendmsg error: %s", __func__, strerror (errno));
777 #endif
778
779                 errnum = errno_to_WSA (errnum, __func__);
780                 WSASetLastError (errnum);
781                 
782                 return(SOCKET_ERROR);
783         }
784         return(ret);
785 }
786
787 int _wapi_setsockopt(guint32 fd, int level, int optname,
788                      const void *optval, socklen_t optlen)
789 {
790         gpointer handle = GUINT_TO_POINTER (fd);
791         int ret;
792         const void *tmp_val;
793         struct timeval tv;
794         
795         if (startup_count == 0) {
796                 WSASetLastError (WSANOTINITIALISED);
797                 return(SOCKET_ERROR);
798         }
799         
800         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
801                 WSASetLastError (WSAENOTSOCK);
802                 return(SOCKET_ERROR);
803         }
804
805         tmp_val = optval;
806         if (level == SOL_SOCKET &&
807             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
808                 int ms = *((int *) optval);
809                 tv.tv_sec = ms / 1000;
810                 tv.tv_usec = (ms % 1000) * 1000;        // micro from milli
811                 tmp_val = &tv;
812                 optlen = sizeof (tv);
813 #if defined (__linux__)
814         } else if (level == SOL_SOCKET &&
815                    (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
816                 /* According to socket(7) the Linux kernel doubles the
817                  * buffer sizes "to allow space for bookkeeping
818                  * overhead."
819                  */
820                 int bufsize = *((int *) optval);
821
822                 bufsize /= 2;
823                 tmp_val = &bufsize;
824 #endif
825         }
826                 
827         ret = setsockopt (fd, level, optname, tmp_val, optlen);
828         if (ret == -1) {
829                 gint errnum = errno;
830 #ifdef DEBUG
831                 g_message ("%s: setsockopt error: %s", __func__,
832                            strerror (errno));
833 #endif
834
835                 errnum = errno_to_WSA (errnum, __func__);
836                 WSASetLastError (errnum);
837                 
838                 return(SOCKET_ERROR);
839         }
840
841 #if defined (SO_REUSEPORT)
842         /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
843         if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
844                 int type;
845                 int type_len = sizeof (type);
846
847                 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
848                         if (type == SOCK_DGRAM)
849                                 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
850                 }
851         }
852 #endif
853         
854         return(ret);
855 }
856
857 int _wapi_shutdown(guint32 fd, int how)
858 {
859         struct _WapiHandle_socket *socket_handle;
860         gboolean ok;
861         gpointer handle = GUINT_TO_POINTER (fd);
862         int ret;
863         
864         if (startup_count == 0) {
865                 WSASetLastError (WSANOTINITIALISED);
866                 return(SOCKET_ERROR);
867         }
868         
869         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
870                 WSASetLastError (WSAENOTSOCK);
871                 return(SOCKET_ERROR);
872         }
873
874         if (how == SHUT_RD ||
875             how == SHUT_RDWR) {
876                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
877                                           (gpointer *)&socket_handle);
878                 if (ok == FALSE) {
879                         g_warning ("%s: error looking up socket handle %p",
880                                    __func__, handle);
881                         WSASetLastError (WSAENOTSOCK);
882                         return(SOCKET_ERROR);
883                 }
884                 
885                 socket_handle->still_readable = 0;
886         }
887         
888         ret = shutdown (fd, how);
889         if (ret == -1) {
890                 gint errnum = errno;
891 #ifdef DEBUG
892                 g_message ("%s: shutdown error: %s", __func__,
893                            strerror (errno));
894 #endif
895
896                 errnum = errno_to_WSA (errnum, __func__);
897                 WSASetLastError (errnum);
898                 
899                 return(SOCKET_ERROR);
900         }
901         
902         return(ret);
903 }
904
905 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
906                      guint32 unused2, guint32 unused3)
907 {
908         struct _WapiHandle_socket socket_handle = {0};
909         gpointer handle;
910         int fd;
911         
912         socket_handle.domain = domain;
913         socket_handle.type = type;
914         socket_handle.protocol = protocol;
915         socket_handle.still_readable = 1;
916         
917         fd = socket (domain, type, protocol);
918         if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
919             protocol == 0) {
920                 /* Retry with protocol == 4 (see bug #54565) */
921                 socket_handle.protocol = 4;
922                 fd = socket (AF_INET, SOCK_RAW, 4);
923         }
924         
925         if (fd == -1) {
926                 gint errnum = errno;
927 #ifdef DEBUG
928                 g_message ("%s: socket error: %s", __func__, strerror (errno));
929 #endif
930                 errnum = errno_to_WSA (errnum, __func__);
931                 WSASetLastError (errnum);
932
933                 return(INVALID_SOCKET);
934         }
935
936         if (fd >= _wapi_fd_reserve) {
937 #ifdef DEBUG
938                 g_message ("%s: File descriptor is too big (%d >= %d)",
939                            __func__, fd, _wapi_fd_reserve);
940 #endif
941
942                 WSASetLastError (WSASYSCALLFAILURE);
943                 close (fd);
944                 
945                 return(INVALID_SOCKET);
946         }
947
948         /* .net seems to set this by default for SOCK_STREAM, not for
949          * SOCK_DGRAM (see bug #36322)
950          *
951          * It seems winsock has a rather different idea of what
952          * SO_REUSEADDR means.  If it's set, then a new socket can be
953          * bound over an existing listening socket.  There's a new
954          * windows-specific option called SO_EXCLUSIVEADDRUSE but
955          * using that means the socket MUST be closed properly, or a
956          * denial of service can occur.  Luckily for us, winsock
957          * behaves as though any other system would when SO_REUSEADDR
958          * is true, so we don't need to do anything else here.  See
959          * bug 53992.
960          */
961         {
962                 int ret, true = 1;
963         
964                 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
965                                   sizeof (true));
966                 if (ret == -1) {
967                         int errnum = errno;
968
969 #ifdef DEBUG
970                         g_message ("%s: Error setting SO_REUSEADDR", __func__);
971 #endif
972                         
973                         errnum = errno_to_WSA (errnum, __func__);
974                         WSASetLastError (errnum);
975
976                         close (fd);
977
978                         return(INVALID_SOCKET);                 
979                 }
980         }
981         
982         
983         mono_once (&socket_ops_once, socket_ops_init);
984         
985         handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
986         if (handle == _WAPI_HANDLE_INVALID) {
987                 g_warning ("%s: error creating socket handle", __func__);
988                 WSASetLastError (WSASYSCALLFAILURE);
989                 close (fd);
990                 return(INVALID_SOCKET);
991         }
992
993 #ifdef DEBUG
994         g_message ("%s: returning socket handle %p", __func__, handle);
995 #endif
996
997         return(fd);
998 }
999
1000 struct hostent *_wapi_gethostbyname(const char *hostname)
1001 {
1002         struct hostent *he;
1003         
1004         if (startup_count == 0) {
1005                 WSASetLastError (WSANOTINITIALISED);
1006                 return(NULL);
1007         }
1008
1009         he = gethostbyname (hostname);
1010         if (he == NULL) {
1011 #ifdef DEBUG
1012                 g_message ("%s: gethostbyname error: %s", __func__,
1013                            strerror (h_errno));
1014 #endif
1015
1016                 switch(h_errno) {
1017                 case HOST_NOT_FOUND:
1018                         WSASetLastError (WSAHOST_NOT_FOUND);
1019                         break;
1020 #if NO_ADDRESS != NO_DATA
1021                 case NO_ADDRESS:
1022 #endif
1023                 case NO_DATA:
1024                         WSASetLastError (WSANO_DATA);
1025                         break;
1026                 case NO_RECOVERY:
1027                         WSASetLastError (WSANO_RECOVERY);
1028                         break;
1029                 case TRY_AGAIN:
1030                         WSASetLastError (WSATRY_AGAIN);
1031                         break;
1032                 default:
1033                         g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
1034                         break;
1035                 }
1036         }
1037         
1038         return(he);
1039 }
1040
1041 static gboolean socket_disconnect (guint32 fd)
1042 {
1043         struct _WapiHandle_socket *socket_handle;
1044         gboolean ok;
1045         gpointer handle = GUINT_TO_POINTER (fd);
1046         int newsock, ret;
1047         
1048         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
1049                                   (gpointer *)&socket_handle);
1050         if (ok == FALSE) {
1051                 g_warning ("%s: error looking up socket handle %p", __func__,
1052                            handle);
1053                 WSASetLastError (WSAENOTSOCK);
1054                 return(FALSE);
1055         }
1056         
1057         newsock = socket (socket_handle->domain, socket_handle->type,
1058                           socket_handle->protocol);
1059         if (newsock == -1) {
1060                 gint errnum = errno;
1061
1062 #ifdef DEBUG
1063                 g_message ("%s: socket error: %s", __func__, strerror (errno));
1064 #endif
1065
1066                 errnum = errno_to_WSA (errnum, __func__);
1067                 WSASetLastError (errnum);
1068                 
1069                 return(FALSE);
1070         }
1071
1072         /* According to Stevens "Advanced Programming in the UNIX
1073          * Environment: UNIX File I/O" dup2() is atomic so there
1074          * should not be a race condition between the old fd being
1075          * closed and the new socket fd being copied over
1076          */
1077         do {
1078                 ret = dup2 (newsock, fd);
1079         } while (ret == -1 && errno == EAGAIN);
1080         
1081         if (ret == -1) {
1082                 gint errnum = errno;
1083                 
1084 #ifdef DEBUG
1085                 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1086 #endif
1087
1088                 errnum = errno_to_WSA (errnum, __func__);
1089                 WSASetLastError (errnum);
1090                 
1091                 return(FALSE);
1092         }
1093
1094         close (newsock);
1095         
1096         return(TRUE);
1097 }
1098
1099 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1100                                    guint32 flags, guint32 reserved)
1101 {
1102 #ifdef DEBUG
1103         g_message ("%s: called on socket %d!", __func__, fd);
1104 #endif
1105         
1106         if (reserved != 0) {
1107                 WSASetLastError (WSAEINVAL);
1108                 return(FALSE);
1109         }
1110
1111         /* We could check the socket type here and fail unless its
1112          * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1113          * if we really wanted to
1114          */
1115
1116         return(socket_disconnect (fd));
1117 }
1118
1119 /* NB only supports NULL file handle, NULL buffers and
1120  * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
1121  * Shouldn't actually ever need to be called anyway though, because we
1122  * have DisconnectEx ().
1123  */
1124 static gboolean wapi_transmitfile (guint32 fd, gpointer file,
1125                                    guint32 num_write, guint32 num_per_send,
1126                                    WapiOverlapped *overlapped,
1127                                    WapiTransmitFileBuffers *buffers,
1128                                    WapiTransmitFileFlags flags)
1129 {
1130 #ifdef DEBUG
1131         g_message ("%s: called on socket %d!", __func__, fd);
1132 #endif
1133         
1134         g_assert (file == NULL);
1135         g_assert (overlapped == NULL);
1136         g_assert (buffers == NULL);
1137         g_assert (num_write == 0);
1138         g_assert (num_per_send == 0);
1139         g_assert (flags == (TF_DISCONNECT | TF_REUSE_SOCKET));
1140
1141         return(socket_disconnect (fd));
1142 }
1143
1144 static struct 
1145 {
1146         WapiGuid guid;
1147         gpointer func;
1148 } extension_functions[] = {
1149         {WSAID_DISCONNECTEX, wapi_disconnectex},
1150         {WSAID_TRANSMITFILE, wapi_transmitfile},
1151         {{0}, NULL},
1152 };
1153
1154 int
1155 WSAIoctl (guint32 fd, gint32 command,
1156           gchar *input, gint i_len,
1157           gchar *output, gint o_len, glong *written,
1158           void *unused1, void *unused2)
1159 {
1160         gpointer handle = GUINT_TO_POINTER (fd);
1161         int ret;
1162         gchar *buffer = NULL;
1163
1164         if (startup_count == 0) {
1165                 WSASetLastError (WSANOTINITIALISED);
1166                 return(SOCKET_ERROR);
1167         }
1168
1169         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1170                 WSASetLastError (WSAENOTSOCK);
1171                 return SOCKET_ERROR;
1172         }
1173
1174         if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1175                 int i = 0;
1176                 WapiGuid *guid = (WapiGuid *)input;
1177                 
1178                 if (i_len < sizeof(WapiGuid)) {
1179                         /* As far as I can tell, windows doesn't
1180                          * actually set an error here...
1181                          */
1182                         WSASetLastError (WSAEINVAL);
1183                         return(SOCKET_ERROR);
1184                 }
1185
1186                 if (o_len < sizeof(gpointer)) {
1187                         /* Or here... */
1188                         WSASetLastError (WSAEINVAL);
1189                         return(SOCKET_ERROR);
1190                 }
1191
1192                 if (output == NULL) {
1193                         /* Or here */
1194                         WSASetLastError (WSAEINVAL);
1195                         return(SOCKET_ERROR);
1196                 }
1197                 
1198                 while(extension_functions[i].func != NULL) {
1199                         if (!memcmp (guid, &extension_functions[i].guid,
1200                                      sizeof(WapiGuid))) {
1201                                 memcpy (output, &extension_functions[i].func,
1202                                         sizeof(gpointer));
1203                                 *written = sizeof(gpointer);
1204                                 return(0);
1205                         }
1206
1207                         i++;
1208                 }
1209                 
1210                 WSASetLastError (WSAEINVAL);
1211                 return(SOCKET_ERROR);
1212         }
1213
1214         if (i_len > 0) {
1215                 buffer = g_memdup (input, i_len);
1216         }
1217
1218         ret = ioctl (fd, command, buffer);
1219         if (ret == -1) {
1220                 gint errnum = errno;
1221 #ifdef DEBUG
1222                 g_message("%s: WSAIoctl error: %s", __func__,
1223                           strerror (errno));
1224 #endif
1225
1226                 errnum = errno_to_WSA (errnum, __func__);
1227                 WSASetLastError (errnum);
1228                 g_free (buffer);
1229                 
1230                 return(SOCKET_ERROR);
1231         }
1232
1233         if (buffer == NULL) {
1234                 *written = 0;
1235         } else {
1236                 /* We just copy the buffer to the output. Some ioctls
1237                  * don't even output any data, but, well...
1238                  *
1239                  * NB windows returns WSAEFAULT if o_len is too small
1240                  */
1241                 i_len = (i_len > o_len) ? o_len : i_len;
1242
1243                 if (i_len > 0 && output != NULL) {
1244                         memcpy (output, buffer, i_len);
1245                 }
1246                 
1247                 g_free (buffer);
1248                 *written = i_len;
1249         }
1250
1251         return(0);
1252 }
1253
1254 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1255 {
1256         gpointer handle = GUINT_TO_POINTER (fd);
1257         int ret;
1258         
1259         if (startup_count == 0) {
1260                 WSASetLastError (WSANOTINITIALISED);
1261                 return(SOCKET_ERROR);
1262         }
1263         
1264         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1265                 WSASetLastError (WSAENOTSOCK);
1266                 return(SOCKET_ERROR);
1267         }
1268
1269         switch(command){
1270                 case FIONBIO:
1271 #ifdef O_NONBLOCK
1272                         /* This works better than ioctl(...FIONBIO...) 
1273                          * on Linux (it causes connect to return
1274                          * EINPROGRESS, but the ioctl doesn't seem to)
1275                          */
1276                         ret = fcntl(fd, F_GETFL, 0);
1277                         if (ret != -1) {
1278                                 if (*(gboolean *)arg) {
1279                                         ret |= O_NONBLOCK;
1280                                 } else {
1281                                         ret &= ~O_NONBLOCK;
1282                                 }
1283                                 ret = fcntl(fd, F_SETFL, ret);
1284                         }
1285                         break;
1286 #endif /* O_NONBLOCK */
1287                 case FIONREAD:
1288                 case SIOCATMARK:
1289                         ret = ioctl (fd, command, arg);
1290                         break;
1291                 default:
1292                         WSASetLastError (WSAEINVAL);
1293                         return(SOCKET_ERROR);
1294         }
1295
1296         if (ret == -1) {
1297                 gint errnum = errno;
1298 #ifdef DEBUG
1299                 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1300 #endif
1301
1302                 errnum = errno_to_WSA (errnum, __func__);
1303                 WSASetLastError (errnum);
1304                 
1305                 return(SOCKET_ERROR);
1306         }
1307         
1308         return(0);
1309 }
1310
1311 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1312                  fd_set *exceptfds, struct timeval *timeout)
1313 {
1314         int ret, maxfd;
1315         
1316         if (startup_count == 0) {
1317                 WSASetLastError (WSANOTINITIALISED);
1318                 return(SOCKET_ERROR);
1319         }
1320
1321         for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1322                 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1323                     (writefds && FD_ISSET (maxfd, writefds)) ||
1324                     (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1325                         break;
1326                 }
1327         }
1328
1329         if (maxfd == -1) {
1330                 WSASetLastError (WSAEINVAL);
1331                 return(SOCKET_ERROR);
1332         }
1333
1334         do {
1335                 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1336                              timeout);
1337         } while (ret == -1 && errno == EINTR &&
1338                  !_wapi_thread_cur_apc_pending ());
1339
1340         if (ret == -1) {
1341                 gint errnum = errno;
1342 #ifdef DEBUG
1343                 g_message ("%s: select error: %s", __func__, strerror (errno));
1344 #endif
1345                 errnum = errno_to_WSA (errnum, __func__);
1346                 WSASetLastError (errnum);
1347                 
1348                 return(SOCKET_ERROR);
1349         }
1350
1351         return(ret);
1352 }
1353
1354 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1355 {
1356         gpointer handle = GUINT_TO_POINTER (fd);
1357         
1358         if (fd >= FD_SETSIZE) {
1359                 WSASetLastError (WSAEINVAL);
1360                 return;
1361         }
1362         
1363         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1364                 WSASetLastError (WSAENOTSOCK);
1365                 return;
1366         }
1367
1368         FD_CLR (fd, set);
1369 }
1370
1371 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1372 {
1373         gpointer handle = GUINT_TO_POINTER (fd);
1374         
1375         if (fd >= FD_SETSIZE) {
1376                 WSASetLastError (WSAEINVAL);
1377                 return(0);
1378         }
1379         
1380         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1381                 WSASetLastError (WSAENOTSOCK);
1382                 return(0);
1383         }
1384
1385         return(FD_ISSET (fd, set));
1386 }
1387
1388 void _wapi_FD_SET(guint32 fd, fd_set *set)
1389 {
1390         gpointer handle = GUINT_TO_POINTER (fd);
1391         
1392         if (fd >= FD_SETSIZE) {
1393                 WSASetLastError (WSAEINVAL);
1394                 return;
1395         }
1396
1397         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1398                 WSASetLastError (WSAENOTSOCK);
1399                 return;
1400         }
1401
1402         FD_SET (fd, set);
1403 }
1404
1405 static void
1406 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1407 {
1408         guint32 i;
1409
1410         memset (hdr, 0, sizeof (struct msghdr));
1411         hdr->msg_iovlen = count;
1412         hdr->msg_iov = g_new0 (struct iovec, count);
1413         for (i = 0; i < count; i++) {
1414                 hdr->msg_iov [i].iov_base = buffers [i].buf;
1415                 hdr->msg_iov [i].iov_len  = buffers [i].len;
1416         }
1417 }
1418
1419 static void
1420 msghdr_iov_free (struct msghdr *hdr)
1421 {
1422         g_free (hdr->msg_iov);
1423 }
1424
1425 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1426              guint32 *flags, WapiOverlapped *overlapped,
1427              WapiOverlappedCB *complete)
1428 {
1429         int ret;
1430         struct msghdr hdr;
1431
1432         g_assert (overlapped == NULL);
1433         g_assert (complete == NULL);
1434
1435         wsabuf_to_msghdr (buffers, count, &hdr);
1436         ret = _wapi_recvmsg (fd, &hdr, *flags);
1437         msghdr_iov_free (&hdr);
1438         
1439         if(ret == SOCKET_ERROR) {
1440                 return(ret);
1441         }
1442         
1443         *received = ret;
1444         *flags = hdr.msg_flags;
1445
1446         return(0);
1447 }
1448
1449 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1450              guint32 flags, WapiOverlapped *overlapped,
1451              WapiOverlappedCB *complete)
1452 {
1453         int ret;
1454         struct msghdr hdr;
1455
1456         g_assert (overlapped == NULL);
1457         g_assert (complete == NULL);
1458
1459         wsabuf_to_msghdr (buffers, count, &hdr);
1460         ret = _wapi_sendmsg (fd, &hdr, flags);
1461         msghdr_iov_free (&hdr);
1462         
1463         if(ret == SOCKET_ERROR) 
1464                 return ret;
1465
1466         *sent = ret;
1467         return 0;
1468 }