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