[runtime] Fix warnings.
[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 #if defined (__linux__)
704         } else if (level == SOL_SOCKET &&
705                    (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
706                 /* According to socket(7) the Linux kernel doubles the
707                  * buffer sizes "to allow space for bookkeeping
708                  * overhead."
709                  */
710                 bufsize = *((int *) optval);
711
712                 bufsize /= 2;
713                 tmp_val = &bufsize;
714 #endif
715         }
716                 
717         ret = setsockopt (fd, level, optname, tmp_val, optlen);
718         if (ret == -1) {
719                 gint errnum = errno;
720                 DEBUG ("%s: setsockopt error: %s", __func__,
721                            strerror (errno));
722
723                 errnum = errno_to_WSA (errnum, __func__);
724                 WSASetLastError (errnum);
725                 
726                 return(SOCKET_ERROR);
727         }
728
729 #if defined (SO_REUSEPORT)
730         /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
731         if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
732                 int type;
733                 socklen_t type_len = sizeof (type);
734
735                 if (!getsockopt (fd, level, SO_TYPE, &type, &type_len)) {
736                         if (type == SOCK_DGRAM)
737                                 setsockopt (fd, level, SO_REUSEPORT, tmp_val, optlen);
738                 }
739         }
740 #endif
741         
742         return(ret);
743 }
744
745 int _wapi_shutdown(guint32 fd, int how)
746 {
747         struct _WapiHandle_socket *socket_handle;
748         gboolean ok;
749         gpointer handle = GUINT_TO_POINTER (fd);
750         int ret;
751
752         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
753                 WSASetLastError (WSAENOTSOCK);
754                 return(SOCKET_ERROR);
755         }
756
757         if (how == SHUT_RD ||
758             how == SHUT_RDWR) {
759                 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
760                                           (gpointer *)&socket_handle);
761                 if (ok == FALSE) {
762                         g_warning ("%s: error looking up socket handle %p",
763                                    __func__, handle);
764                         WSASetLastError (WSAENOTSOCK);
765                         return(SOCKET_ERROR);
766                 }
767                 
768                 socket_handle->still_readable = 0;
769         }
770         
771         ret = shutdown (fd, how);
772         if (ret == -1) {
773                 gint errnum = errno;
774                 DEBUG ("%s: shutdown error: %s", __func__,
775                            strerror (errno));
776
777                 errnum = errno_to_WSA (errnum, __func__);
778                 WSASetLastError (errnum);
779                 
780                 return(SOCKET_ERROR);
781         }
782         
783         return(ret);
784 }
785
786 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
787                      guint32 unused2, guint32 unused3)
788 {
789         struct _WapiHandle_socket socket_handle = {0};
790         gpointer handle;
791         int fd;
792         
793         socket_handle.domain = domain;
794         socket_handle.type = type;
795         socket_handle.protocol = protocol;
796         socket_handle.still_readable = 1;
797         
798         fd = socket (domain, type, protocol);
799         if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
800             protocol == 0) {
801                 /* Retry with protocol == 4 (see bug #54565) */
802                 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
803                 socket_handle.protocol = 4;
804                 fd = socket (AF_INET, SOCK_RAW, 4);
805         }
806         
807         if (fd == -1) {
808                 gint errnum = errno;
809                 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
810                 errnum = errno_to_WSA (errnum, __func__);
811                 WSASetLastError (errnum);
812
813                 return(INVALID_SOCKET);
814         }
815
816         if (fd >= _wapi_fd_reserve) {
817                 DEBUG ("%s: File descriptor is too big (%d >= %d)",
818                            __func__, fd, _wapi_fd_reserve);
819
820                 WSASetLastError (WSASYSCALLFAILURE);
821                 close (fd);
822                 
823                 return(INVALID_SOCKET);
824         }
825
826         /* .net seems to set this by default for SOCK_STREAM, not for
827          * SOCK_DGRAM (see bug #36322)
828          * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
829          *
830          * It seems winsock has a rather different idea of what
831          * SO_REUSEADDR means.  If it's set, then a new socket can be
832          * bound over an existing listening socket.  There's a new
833          * windows-specific option called SO_EXCLUSIVEADDRUSE but
834          * using that means the socket MUST be closed properly, or a
835          * denial of service can occur.  Luckily for us, winsock
836          * behaves as though any other system would when SO_REUSEADDR
837          * is true, so we don't need to do anything else here.  See
838          * bug 53992.
839          * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
840          */
841         {
842                 int ret, true = 1;
843         
844                 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
845                                   sizeof (true));
846                 if (ret == -1) {
847                         int errnum = errno;
848
849                         DEBUG ("%s: Error setting SO_REUSEADDR", __func__);
850                         
851                         errnum = errno_to_WSA (errnum, __func__);
852                         WSASetLastError (errnum);
853
854                         close (fd);
855
856                         return(INVALID_SOCKET);                 
857                 }
858         }
859         
860         
861         mono_once (&socket_ops_once, socket_ops_init);
862         
863         handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle);
864         if (handle == _WAPI_HANDLE_INVALID) {
865                 g_warning ("%s: error creating socket handle", __func__);
866                 WSASetLastError (WSASYSCALLFAILURE);
867                 close (fd);
868                 return(INVALID_SOCKET);
869         }
870
871         DEBUG ("%s: returning socket handle %p", __func__, handle);
872
873         return(fd);
874 }
875
876 static gboolean socket_disconnect (guint32 fd)
877 {
878         struct _WapiHandle_socket *socket_handle;
879         gboolean ok;
880         gpointer handle = GUINT_TO_POINTER (fd);
881         int newsock, ret;
882         
883         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
884                                   (gpointer *)&socket_handle);
885         if (ok == FALSE) {
886                 g_warning ("%s: error looking up socket handle %p", __func__,
887                            handle);
888                 WSASetLastError (WSAENOTSOCK);
889                 return(FALSE);
890         }
891         
892         newsock = socket (socket_handle->domain, socket_handle->type,
893                           socket_handle->protocol);
894         if (newsock == -1) {
895                 gint errnum = errno;
896
897                 DEBUG ("%s: socket error: %s", __func__, strerror (errno));
898
899                 errnum = errno_to_WSA (errnum, __func__);
900                 WSASetLastError (errnum);
901                 
902                 return(FALSE);
903         }
904
905         /* According to Stevens "Advanced Programming in the UNIX
906          * Environment: UNIX File I/O" dup2() is atomic so there
907          * should not be a race condition between the old fd being
908          * closed and the new socket fd being copied over
909          */
910         do {
911                 ret = dup2 (newsock, fd);
912         } while (ret == -1 && errno == EAGAIN);
913         
914         if (ret == -1) {
915                 gint errnum = errno;
916                 
917                 DEBUG ("%s: dup2 error: %s", __func__, strerror (errno));
918
919                 errnum = errno_to_WSA (errnum, __func__);
920                 WSASetLastError (errnum);
921                 
922                 return(FALSE);
923         }
924
925         close (newsock);
926         
927         return(TRUE);
928 }
929
930 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
931                                    guint32 flags, guint32 reserved)
932 {
933         DEBUG ("%s: called on socket %d!", __func__, fd);
934         
935         if (reserved != 0) {
936                 WSASetLastError (WSAEINVAL);
937                 return(FALSE);
938         }
939
940         /* We could check the socket type here and fail unless its
941          * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
942          * if we really wanted to
943          */
944
945         return(socket_disconnect (fd));
946 }
947
948 #define SF_BUFFER_SIZE  16384
949 static gint
950 wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags)
951 {
952 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
953         gint file = GPOINTER_TO_INT (fd);
954         gint n;
955         gint errnum;
956         gssize res;
957         struct stat statbuf;
958
959         n = fstat (file, &statbuf);
960         if (n == -1) {
961                 errnum = errno;
962                 errnum = errno_to_WSA (errnum, __func__);
963                 WSASetLastError (errnum);
964                 return SOCKET_ERROR;
965         }
966         do {
967 #ifdef __linux__
968                 res = sendfile (socket, file, NULL, statbuf.st_size);
969 #elif defined(DARWIN)
970                 /* TODO: header/tail could be sent in the 5th argument */
971                 /* TODO: Might not send the entire file for non-blocking sockets */
972                 res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0);
973 #endif
974         } while (res != -1 && (errno == EINTR || errno == EAGAIN) && !_wapi_thread_cur_apc_pending ());
975         if (res == -1) {
976                 errnum = errno;
977                 errnum = errno_to_WSA (errnum, __func__);
978                 WSASetLastError (errnum);
979                 return SOCKET_ERROR;
980         }
981 #else
982         /* Default implementation */
983         gint file = GPOINTER_TO_INT (fd);
984         gchar *buffer;
985         gint n;
986
987         buffer = g_malloc (SF_BUFFER_SIZE);
988         do {
989                 do {
990                         n = read (file, buffer, SF_BUFFER_SIZE);
991                 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
992                 if (n == -1)
993                         break;
994                 if (n == 0) {
995                         g_free (buffer);
996                         return 0; /* We're done reading */
997                 }
998                 do {
999                         n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */
1000                 } while (n == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
1001         } while (n != -1);
1002
1003         if (n == -1) {
1004                 gint errnum = errno;
1005                 errnum = errno_to_WSA (errnum, __func__);
1006                 WSASetLastError (errnum);
1007                 g_free (buffer);
1008                 return SOCKET_ERROR;
1009         }
1010         g_free (buffer);
1011 #endif
1012         return 0;
1013 }
1014
1015 gboolean
1016 TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
1017                 WapiTransmitFileBuffers *buffers, guint32 flags)
1018 {
1019         gpointer sock = GUINT_TO_POINTER (socket);
1020         gint ret;
1021
1022         if (_wapi_handle_type (sock) != WAPI_HANDLE_SOCKET) {
1023                 WSASetLastError (WSAENOTSOCK);
1024                 return FALSE;
1025         }
1026
1027         /* Write the header */
1028         if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
1029                 ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
1030                 if (ret == SOCKET_ERROR)
1031                         return FALSE;
1032         }
1033
1034         ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
1035         if (ret == SOCKET_ERROR)
1036                 return FALSE;
1037
1038         /* Write the tail */
1039         if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
1040                 ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
1041                 if (ret == SOCKET_ERROR)
1042                         return FALSE;
1043         }
1044
1045         if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
1046                 closesocket (socket);
1047
1048         return TRUE;
1049 }
1050
1051 static struct 
1052 {
1053         WapiGuid guid;
1054         gpointer func;
1055 } extension_functions[] = {
1056         {WSAID_DISCONNECTEX, wapi_disconnectex},
1057         {WSAID_TRANSMITFILE, TransmitFile},
1058         {{0}, NULL},
1059 };
1060
1061 int
1062 WSAIoctl (guint32 fd, gint32 command,
1063           gchar *input, gint i_len,
1064           gchar *output, gint o_len, glong *written,
1065           void *unused1, void *unused2)
1066 {
1067         gpointer handle = GUINT_TO_POINTER (fd);
1068         int ret;
1069         gchar *buffer = NULL;
1070
1071         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1072                 WSASetLastError (WSAENOTSOCK);
1073                 return SOCKET_ERROR;
1074         }
1075
1076         if (command == SIO_GET_EXTENSION_FUNCTION_POINTER) {
1077                 int i = 0;
1078                 WapiGuid *guid = (WapiGuid *)input;
1079                 
1080                 if (i_len < sizeof(WapiGuid)) {
1081                         /* As far as I can tell, windows doesn't
1082                          * actually set an error here...
1083                          */
1084                         WSASetLastError (WSAEINVAL);
1085                         return(SOCKET_ERROR);
1086                 }
1087
1088                 if (o_len < sizeof(gpointer)) {
1089                         /* Or here... */
1090                         WSASetLastError (WSAEINVAL);
1091                         return(SOCKET_ERROR);
1092                 }
1093
1094                 if (output == NULL) {
1095                         /* Or here */
1096                         WSASetLastError (WSAEINVAL);
1097                         return(SOCKET_ERROR);
1098                 }
1099                 
1100                 while(extension_functions[i].func != NULL) {
1101                         if (!memcmp (guid, &extension_functions[i].guid,
1102                                      sizeof(WapiGuid))) {
1103                                 memcpy (output, &extension_functions[i].func,
1104                                         sizeof(gpointer));
1105                                 *written = sizeof(gpointer);
1106                                 return(0);
1107                         }
1108
1109                         i++;
1110                 }
1111                 
1112                 WSASetLastError (WSAEINVAL);
1113                 return(SOCKET_ERROR);
1114         }
1115
1116         if (command == SIO_KEEPALIVE_VALS) {
1117                 uint32_t onoff;
1118                 uint32_t keepalivetime;
1119                 uint32_t keepaliveinterval;
1120
1121                 if (i_len < (3 * sizeof (uint32_t))) {
1122                         WSASetLastError (WSAEINVAL);
1123                         return SOCKET_ERROR;
1124                 }
1125                 memcpy (&onoff, input, sizeof (uint32_t));
1126                 memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
1127                 memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
1128                 ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
1129                 if (ret < 0) {
1130                         gint errnum = errno;
1131                         errnum = errno_to_WSA (errnum, __func__);
1132                         WSASetLastError (errnum);
1133                         return SOCKET_ERROR;
1134                 }
1135                 if (onoff != 0) {
1136 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1137                         /* Values are in ms, but we need s */
1138                         uint32_t rem;
1139
1140                         /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1141                         rem = keepalivetime % 1000;
1142                         keepalivetime /= 1000;
1143                         if (keepalivetime == 0 || rem >= 500)
1144                                 keepalivetime++;
1145                         ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
1146                         if (ret == 0) {
1147                                 rem = keepaliveinterval % 1000;
1148                                 keepaliveinterval /= 1000;
1149                                 if (keepaliveinterval == 0 || rem >= 500)
1150                                         keepaliveinterval++;
1151                                 ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
1152                         }
1153                         if (ret != 0) {
1154                                 gint errnum = errno;
1155                                 errnum = errno_to_WSA (errnum, __func__);
1156                                 WSASetLastError (errnum);
1157                                 return SOCKET_ERROR;
1158                         }
1159                         return 0;
1160 #endif
1161                 }
1162                 return 0;
1163         }
1164
1165         if (i_len > 0) {
1166                 buffer = g_memdup (input, i_len);
1167         }
1168
1169         ret = ioctl (fd, command, buffer);
1170         if (ret == -1) {
1171                 gint errnum = errno;
1172                 DEBUG("%s: WSAIoctl error: %s", __func__,
1173                           strerror (errno));
1174
1175                 errnum = errno_to_WSA (errnum, __func__);
1176                 WSASetLastError (errnum);
1177                 g_free (buffer);
1178                 
1179                 return(SOCKET_ERROR);
1180         }
1181
1182         if (buffer == NULL) {
1183                 *written = 0;
1184         } else {
1185                 /* We just copy the buffer to the output. Some ioctls
1186                  * don't even output any data, but, well...
1187                  *
1188                  * NB windows returns WSAEFAULT if o_len is too small
1189                  */
1190                 i_len = (i_len > o_len) ? o_len : i_len;
1191
1192                 if (i_len > 0 && output != NULL) {
1193                         memcpy (output, buffer, i_len);
1194                 }
1195                 
1196                 g_free (buffer);
1197                 *written = i_len;
1198         }
1199
1200         return(0);
1201 }
1202
1203 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1204 int ioctlsocket(guint32 fd, unsigned long command, gpointer arg)
1205 {
1206         gpointer handle = GUINT_TO_POINTER (fd);
1207         int ret;
1208         
1209         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1210                 WSASetLastError (WSAENOTSOCK);
1211                 return(SOCKET_ERROR);
1212         }
1213
1214         switch(command){
1215                 case FIONBIO:
1216 #ifdef O_NONBLOCK
1217                         /* This works better than ioctl(...FIONBIO...) 
1218                          * on Linux (it causes connect to return
1219                          * EINPROGRESS, but the ioctl doesn't seem to)
1220                          */
1221                         ret = fcntl(fd, F_GETFL, 0);
1222                         if (ret != -1) {
1223                                 if (*(gboolean *)arg) {
1224                                         ret |= O_NONBLOCK;
1225                                 } else {
1226                                         ret &= ~O_NONBLOCK;
1227                                 }
1228                                 ret = fcntl(fd, F_SETFL, ret);
1229                         }
1230                         break;
1231 #endif /* O_NONBLOCK */
1232                         /* Unused in Mono */
1233                 case SIOCATMARK:
1234                         ret = ioctl (fd, command, arg);
1235                         break;
1236                         
1237                 case FIONREAD:
1238                 {
1239 #if defined (PLATFORM_MACOSX)
1240                         
1241                         // ioctl (fd, FIONREAD, XXX) returns the size of
1242                         // the UDP header as well on
1243                         // Darwin.
1244                         //
1245                         // Use getsockopt SO_NREAD instead to get the
1246                         // right values for TCP and UDP.
1247                         // 
1248                         // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1249                         // be the value of the ip buffer.
1250
1251                         socklen_t optlen = sizeof (int);
1252                         ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
1253 #else
1254                         ret = ioctl (fd, command, arg);
1255 #endif
1256                         break;
1257                 }
1258                 default:
1259                         WSASetLastError (WSAEINVAL);
1260                         return(SOCKET_ERROR);
1261         }
1262
1263         if (ret == -1) {
1264                 gint errnum = errno;
1265                 DEBUG ("%s: ioctl error: %s", __func__, strerror (errno));
1266
1267                 errnum = errno_to_WSA (errnum, __func__);
1268                 WSASetLastError (errnum);
1269                 
1270                 return(SOCKET_ERROR);
1271         }
1272         
1273         return(0);
1274 }
1275
1276 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1277                  fd_set *exceptfds, struct timeval *timeout)
1278 {
1279         int ret, maxfd;
1280         
1281         for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) {
1282                 if ((readfds && FD_ISSET (maxfd, readfds)) ||
1283                     (writefds && FD_ISSET (maxfd, writefds)) ||
1284                     (exceptfds && FD_ISSET (maxfd, exceptfds))) {
1285                         break;
1286                 }
1287         }
1288
1289         if (maxfd == -1) {
1290                 WSASetLastError (WSAEINVAL);
1291                 return(SOCKET_ERROR);
1292         }
1293
1294         do {
1295                 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1296                              timeout);
1297         } while (ret == -1 && errno == EINTR &&
1298                  !_wapi_thread_cur_apc_pending ());
1299
1300         if (ret == -1) {
1301                 gint errnum = errno;
1302                 DEBUG ("%s: select error: %s", __func__, strerror (errno));
1303                 errnum = errno_to_WSA (errnum, __func__);
1304                 WSASetLastError (errnum);
1305                 
1306                 return(SOCKET_ERROR);
1307         }
1308
1309         return(ret);
1310 }
1311
1312 void _wapi_FD_CLR(guint32 fd, fd_set *set)
1313 {
1314         gpointer handle = GUINT_TO_POINTER (fd);
1315         
1316         if (fd >= FD_SETSIZE) {
1317                 WSASetLastError (WSAEINVAL);
1318                 return;
1319         }
1320         
1321         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1322                 WSASetLastError (WSAENOTSOCK);
1323                 return;
1324         }
1325
1326         FD_CLR (fd, set);
1327 }
1328
1329 int _wapi_FD_ISSET(guint32 fd, fd_set *set)
1330 {
1331         gpointer handle = GUINT_TO_POINTER (fd);
1332         
1333         if (fd >= FD_SETSIZE) {
1334                 WSASetLastError (WSAEINVAL);
1335                 return(0);
1336         }
1337         
1338         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1339                 WSASetLastError (WSAENOTSOCK);
1340                 return(0);
1341         }
1342
1343         return(FD_ISSET (fd, set));
1344 }
1345
1346 void _wapi_FD_SET(guint32 fd, fd_set *set)
1347 {
1348         gpointer handle = GUINT_TO_POINTER (fd);
1349         
1350         if (fd >= FD_SETSIZE) {
1351                 WSASetLastError (WSAEINVAL);
1352                 return;
1353         }
1354
1355         if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1356                 WSASetLastError (WSAENOTSOCK);
1357                 return;
1358         }
1359
1360         FD_SET (fd, set);
1361 }
1362 #endif
1363
1364 static void
1365 wsabuf_to_msghdr (WapiWSABuf *buffers, guint32 count, struct msghdr *hdr)
1366 {
1367         guint32 i;
1368
1369         memset (hdr, 0, sizeof (struct msghdr));
1370         hdr->msg_iovlen = count;
1371         hdr->msg_iov = g_new0 (struct iovec, count);
1372         for (i = 0; i < count; i++) {
1373                 hdr->msg_iov [i].iov_base = buffers [i].buf;
1374                 hdr->msg_iov [i].iov_len  = buffers [i].len;
1375         }
1376 }
1377
1378 static void
1379 msghdr_iov_free (struct msghdr *hdr)
1380 {
1381         g_free (hdr->msg_iov);
1382 }
1383
1384 int WSARecv (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *received,
1385              guint32 *flags, WapiOverlapped *overlapped,
1386              WapiOverlappedCB *complete)
1387 {
1388         int ret;
1389         struct msghdr hdr;
1390
1391         g_assert (overlapped == NULL);
1392         g_assert (complete == NULL);
1393
1394         wsabuf_to_msghdr (buffers, count, &hdr);
1395         ret = _wapi_recvmsg (fd, &hdr, *flags);
1396         msghdr_iov_free (&hdr);
1397         
1398         if(ret == SOCKET_ERROR) {
1399                 return(ret);
1400         }
1401         
1402         *received = ret;
1403         *flags = hdr.msg_flags;
1404
1405         return(0);
1406 }
1407
1408 int WSASend (guint32 fd, WapiWSABuf *buffers, guint32 count, guint32 *sent,
1409              guint32 flags, WapiOverlapped *overlapped,
1410              WapiOverlappedCB *complete)
1411 {
1412         int ret;
1413         struct msghdr hdr;
1414
1415         g_assert (overlapped == NULL);
1416         g_assert (complete == NULL);
1417
1418         wsabuf_to_msghdr (buffers, count, &hdr);
1419         ret = _wapi_sendmsg (fd, &hdr, flags);
1420         msghdr_iov_free (&hdr);
1421         
1422         if(ret == SOCKET_ERROR) 
1423                 return ret;
1424
1425         *sent = ret;
1426         return 0;
1427 }
1428
1429 #endif /* ifndef DISABLE_SOCKETS */