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