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