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