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