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