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