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