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