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