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