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