5816b142b051e09e6c784e93518bbd9241dbd643
[mono.git] / mono / metadata / w32socket-unix.c
1 /**
2  * \file
3  * Unix specific socket code.
4  *
5  * Copyright 2016 Microsoft
6  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
7  */
8
9 #include <config.h>
10 #include <glib.h>
11
12 #include <pthread.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #ifdef HAVE_SYS_IOCTL_H
18 #include <sys/ioctl.h>
19 #endif
20 #include <netinet/in.h>
21 #include <netinet/tcp.h>
22 #ifdef HAVE_NETDB_H
23 #include <netdb.h>
24 #endif
25 #include <arpa/inet.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #include <errno.h>
30 #include <fcntl.h>
31 #ifdef HAVE_SYS_UIO_H
32 #include <sys/uio.h>
33 #endif
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
36 #endif
37 #ifdef HAVE_SYS_FILIO_H
38 #include <sys/filio.h>     /* defines FIONBIO and FIONREAD */
39 #endif
40 #ifdef HAVE_SYS_SOCKIO_H
41 #include <sys/sockio.h>    /* defines SIOCATMARK */
42 #endif
43 #ifndef HAVE_MSG_NOSIGNAL
44 #include <signal.h>
45 #endif
46 #ifdef HAVE_SYS_SENDFILE_H
47 #include <sys/sendfile.h>
48 #endif
49 #include <sys/stat.h>
50
51 #include "w32socket.h"
52 #include "w32socket-internals.h"
53 #include "w32error.h"
54 #include "w32handle.h"
55 #include "utils/mono-logger-internals.h"
56 #include "utils/mono-poll.h"
57
58 typedef struct {
59         int domain;
60         int type;
61         int protocol;
62         int saved_error;
63         int still_readable;
64 } MonoW32HandleSocket;
65
66 static guint32 in_cleanup = 0;
67
68 static void
69 socket_close (gpointer handle, gpointer data)
70 {
71         int ret;
72         MonoW32HandleSocket *socket_handle = (MonoW32HandleSocket *)data;
73         MonoThreadInfo *info = mono_thread_info_current ();
74
75         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle);
76
77         /* Shutdown the socket for reading, to interrupt any potential
78          * receives that may be blocking for data.  See bug 75705. */
79         shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
80
81         do {
82                 ret = close (GPOINTER_TO_UINT(handle));
83         } while (ret == -1 && errno == EINTR &&
84                  !mono_thread_info_is_interrupt_state (info));
85
86         if (ret == -1) {
87                 gint errnum = errno;
88                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, g_strerror (errno));
89                 if (!in_cleanup)
90                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
91         }
92
93         if (!in_cleanup)
94                 socket_handle->saved_error = 0;
95 }
96
97 static void
98 socket_details (gpointer data)
99 {
100         /* FIXME: do something */
101 }
102
103 static const gchar*
104 socket_typename (void)
105 {
106         return "Socket";
107 }
108
109 static gsize
110 socket_typesize (void)
111 {
112         return sizeof (MonoW32HandleSocket);
113 }
114
115 static MonoW32HandleOps ops = {
116         socket_close,    /* close */
117         NULL,            /* signal */
118         NULL,            /* own */
119         NULL,            /* is_owned */
120         NULL,            /* special_wait */
121         NULL,            /* prewait */
122         socket_details,  /* details */
123         socket_typename, /* typename */
124         socket_typesize, /* typesize */
125 };
126
127 void
128 mono_w32socket_initialize (void)
129 {
130         mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &ops);
131 }
132
133 static gboolean
134 cleanup_close (gpointer handle, gpointer data, gpointer user_data)
135 {
136         if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET)
137                 mono_w32handle_force_close (handle, data);
138
139         return FALSE;
140 }
141
142 void
143 mono_w32socket_cleanup (void)
144 {
145         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__);
146
147         in_cleanup = 1;
148         mono_w32handle_foreach (cleanup_close, NULL);
149         in_cleanup = 0;
150 }
151
152 SOCKET
153 mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking)
154 {
155         gpointer handle;
156         gpointer new_handle;
157         MonoW32HandleSocket *socket_handle;
158         MonoW32HandleSocket new_socket_handle;
159         SOCKET new_fd;
160         MonoThreadInfo *info;
161
162         if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
163                 mono_w32socket_set_last_error (WSAEFAULT);
164                 return INVALID_SOCKET;
165         }
166
167         handle = GUINT_TO_POINTER (sock);
168         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
169                 mono_w32socket_set_last_error (WSAENOTSOCK);
170                 return INVALID_SOCKET;
171         }
172
173         info = mono_thread_info_current ();
174
175         do {
176                 new_fd = accept (sock, addr, addrlen);
177         } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
178
179         if (new_fd == -1) {
180                 gint errnum = errno;
181                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno));
182                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
183                 return INVALID_SOCKET;
184         }
185
186         if (new_fd >= mono_w32handle_fd_reserve) {
187                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
188
189                 mono_w32socket_set_last_error (WSASYSCALLFAILURE);
190
191                 close (new_fd);
192
193                 return INVALID_SOCKET;
194         }
195
196         new_socket_handle.domain = socket_handle->domain;
197         new_socket_handle.type = socket_handle->type;
198         new_socket_handle.protocol = socket_handle->protocol;
199         new_socket_handle.still_readable = 1;
200
201         new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd,
202                                           &new_socket_handle);
203         if(new_handle == INVALID_HANDLE_VALUE) {
204                 g_warning ("%s: error creating socket handle", __func__);
205                 mono_w32socket_set_last_error (ERROR_GEN_FAILURE);
206                 return INVALID_SOCKET;
207         }
208
209         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with",
210                    __func__, new_handle);
211
212         return new_fd;
213 }
214
215 int
216 mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking)
217 {
218         gpointer handle;
219         MonoW32HandleSocket *socket_handle;
220
221         handle = GUINT_TO_POINTER (sock);
222         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
223                 mono_w32socket_set_last_error (WSAENOTSOCK);
224                 return SOCKET_ERROR;
225         }
226
227         if (connect (sock, addr, addrlen) == -1) {
228                 MonoThreadInfo *info;
229                 mono_pollfd fds;
230                 gint errnum, so_error;
231                 socklen_t len;
232
233                 errnum = errno;
234
235                 if (errno != EINTR) {
236                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
237                                    g_strerror (errnum));
238
239                         errnum = mono_w32socket_convert_error (errnum);
240                         if (errnum == WSAEINPROGRESS)
241                                 errnum = WSAEWOULDBLOCK; /* see bug #73053 */
242
243                         mono_w32socket_set_last_error (errnum);
244
245                         /*
246                          * On solaris x86 getsockopt (SO_ERROR) is not set after
247                          * connect () fails so we need to save this error.
248                          *
249                          * But don't do this for EWOULDBLOCK (bug 317315)
250                          */
251                         if (errnum != WSAEWOULDBLOCK) {
252                                 /* ECONNRESET means the socket was closed by another thread */
253                                 /* Async close on mac raises ECONNABORTED. */
254                                 socket_handle->saved_error = errnum;
255                         }
256                         return SOCKET_ERROR;
257                 }
258
259                 info = mono_thread_info_current ();
260
261                 fds.fd = sock;
262                 fds.events = MONO_POLLOUT;
263                 while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) {
264                         if (errno != EINTR) {
265                                 gint errnum = errno;
266                                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno));
267                                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
268                                 return SOCKET_ERROR;
269                         }
270                 }
271
272                 len = sizeof(so_error);
273                 if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
274                         gint errnum = errno;
275                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno));
276                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
277                         return SOCKET_ERROR;
278                 }
279
280                 if (so_error != 0) {
281                         gint errnum = mono_w32socket_convert_error (so_error);
282
283                         /* Need to save this socket error */
284                         socket_handle->saved_error = errnum;
285
286                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
287                                    __func__, g_strerror (so_error));
288
289                         mono_w32socket_set_last_error (errnum);
290                         return SOCKET_ERROR;
291                 }
292         }
293
294         return 0;
295 }
296
297 int
298 mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
299 {
300         return mono_w32socket_recvfrom (sock, buf, len, flags, NULL, 0, blocking);
301 }
302
303 int
304 mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
305 {
306         gpointer handle;
307         MonoW32HandleSocket *socket_handle;
308         int ret;
309         MonoThreadInfo *info;
310
311         handle = GUINT_TO_POINTER (sock);
312         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
313                 mono_w32socket_set_last_error (WSAENOTSOCK);
314                 return SOCKET_ERROR;
315         }
316
317         info = mono_thread_info_current ();
318
319         do {
320                 ret = recvfrom (sock, buf, len, flags, from, fromlen);
321         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
322
323         if (ret == 0 && len > 0) {
324                 /* According to the Linux man page, recvfrom only
325                  * returns 0 when the socket has been shut down
326                  * cleanly.  Turn this into an EINTR to simulate win32
327                  * behaviour of returning EINTR when a socket is
328                  * closed while the recvfrom is blocking (we use a
329                  * shutdown() in socket_close() to trigger this.) See
330                  * bug 75705.
331                  */
332                 /* Distinguish between the socket being shut down at
333                  * the local or remote ends, and reads that request 0
334                  * bytes to be read
335                  */
336
337                 /* If this returns FALSE, it means the socket has been
338                  * closed locally.  If it returns TRUE, but
339                  * still_readable != 1 then shutdown
340                  * (SHUT_RD|SHUT_RDWR) has been called locally.
341                  */
342                 if (socket_handle->still_readable != 1) {
343                         ret = -1;
344                         errno = EINTR;
345                 }
346         }
347
348         if (ret == -1) {
349                 gint errnum = errno;
350                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno));
351                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
352                 return SOCKET_ERROR;
353         }
354         return ret;
355 }
356
357 static void
358 wsabuf_to_msghdr (WSABUF *buffers, guint32 count, struct msghdr *hdr)
359 {
360         guint32 i;
361
362         memset (hdr, 0, sizeof (struct msghdr));
363         hdr->msg_iovlen = count;
364         hdr->msg_iov = g_new0 (struct iovec, count);
365         for (i = 0; i < count; i++) {
366                 hdr->msg_iov [i].iov_base = buffers [i].buf;
367                 hdr->msg_iov [i].iov_len  = buffers [i].len;
368         }
369 }
370
371 static void
372 msghdr_iov_free (struct msghdr *hdr)
373 {
374         g_free (hdr->msg_iov);
375 }
376
377 int
378 mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking)
379 {
380         MonoW32HandleSocket *socket_handle;
381         MonoThreadInfo *info;
382         gpointer handle;
383         gint ret;
384         struct msghdr hdr;
385
386         g_assert (overlapped == NULL);
387         g_assert (complete == NULL);
388
389         handle = GUINT_TO_POINTER (sock);
390         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
391                 mono_w32socket_set_last_error (WSAENOTSOCK);
392                 return SOCKET_ERROR;
393         }
394
395         info = mono_thread_info_current ();
396
397         wsabuf_to_msghdr (buffers, count, &hdr);
398
399         do {
400                 ret = recvmsg (sock, &hdr, *flags);
401         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
402
403         msghdr_iov_free (&hdr);
404
405         if (ret == 0) {
406                 /* see mono_w32socket_recvfrom */
407                 if (socket_handle->still_readable != 1) {
408                         ret = -1;
409                         errno = EINTR;
410                 }
411         }
412
413         if (ret == -1) {
414                 gint errnum = errno;
415                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno));
416                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
417                 return SOCKET_ERROR;
418         }
419
420         *received = ret;
421         *flags = hdr.msg_flags;
422
423         return 0;
424 }
425
426 int
427 mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
428 {
429         gpointer handle;
430         int ret;
431         MonoThreadInfo *info;
432
433         handle = GUINT_TO_POINTER (sock);
434         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
435                 mono_w32socket_set_last_error (WSAENOTSOCK);
436                 return SOCKET_ERROR;
437         }
438
439         info = mono_thread_info_current ();
440
441         do {
442                 ret = send (sock, buf, len, flags);
443         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
444
445         if (ret == -1) {
446                 gint errnum = errno;
447                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
448
449 #ifdef O_NONBLOCK
450                 /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
451                  * a blocking socket. See bug #599488 */
452                 if (errnum == EAGAIN) {
453                         ret = fcntl (sock, F_GETFL, 0);
454                         if (ret != -1 && (ret & O_NONBLOCK) == 0)
455                                 errnum = ETIMEDOUT;
456                 }
457 #endif /* O_NONBLOCK */
458                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
459                 return SOCKET_ERROR;
460         }
461         return ret;
462 }
463
464 int
465 mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
466 {
467         gpointer handle;
468         int ret;
469         MonoThreadInfo *info;
470
471         handle = GUINT_TO_POINTER (sock);
472         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
473                 mono_w32socket_set_last_error (WSAENOTSOCK);
474                 return SOCKET_ERROR;
475         }
476
477         info = mono_thread_info_current ();
478
479         do {
480                 ret = sendto (sock, buf, len, flags, to, tolen);
481         } while (ret == -1 && errno == EINTR &&  !mono_thread_info_is_interrupt_state (info));
482
483         if (ret == -1) {
484                 gint errnum = errno;
485                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
486                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
487                 return SOCKET_ERROR;
488         }
489         return ret;
490 }
491
492 int
493 mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking)
494 {
495         struct msghdr hdr;
496         MonoThreadInfo *info;
497         gpointer handle;
498         gint ret;
499
500         g_assert (overlapped == NULL);
501         g_assert (complete == NULL);
502
503         handle = GUINT_TO_POINTER (sock);
504         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
505                 mono_w32socket_set_last_error (WSAENOTSOCK);
506                 return SOCKET_ERROR;
507         }
508
509         info = mono_thread_info_current ();
510
511         wsabuf_to_msghdr (buffers, count, &hdr);
512
513         do {
514                 ret = sendmsg (sock, &hdr, flags);
515         } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
516
517         msghdr_iov_free (&hdr);
518
519         if (ret == -1) {
520                 gint errnum = errno;
521                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno));
522                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
523                 return SOCKET_ERROR;
524         }
525
526         *sent = ret;
527         return 0;
528 }
529
530 #define SF_BUFFER_SIZE  16384
531
532 BOOL
533 mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking)
534 {
535         MonoThreadInfo *info;
536         gpointer handle;
537         gint file;
538         gssize ret;
539 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
540         struct stat statbuf;
541 #else
542         gchar *buffer;
543 #endif
544
545         handle = GUINT_TO_POINTER (sock);
546         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
547                 mono_w32socket_set_last_error (WSAENOTSOCK);
548                 return FALSE;
549         }
550
551         /* Write the header */
552         if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
553                 ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE);
554                 if (ret == SOCKET_ERROR)
555                         return FALSE;
556         }
557
558         info = mono_thread_info_current ();
559
560         file = GPOINTER_TO_INT (file_handle);
561
562 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
563         ret = fstat (file, &statbuf);
564         if (ret == -1) {
565                 gint errnum = errno;
566                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
567                 return SOCKET_ERROR;
568         }
569
570         do {
571 #ifdef __linux__
572                 ret = sendfile (sock, file, NULL, statbuf.st_size);
573 #elif defined(DARWIN)
574                 /* TODO: header/tail could be sent in the 5th argument */
575                 /* TODO: Might not send the entire file for non-blocking sockets */
576                 ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0);
577 #endif
578         } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
579 #else
580         buffer = g_malloc (SF_BUFFER_SIZE);
581
582         do {
583                 do {
584                         ret = read (file, buffer, SF_BUFFER_SIZE);
585                 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
586
587                 if (ret == -1 || ret == 0)
588                         break;
589
590                 do {
591                         ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */
592                 } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
593         } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
594
595         g_free (buffer);
596 #endif
597
598         if (ret == -1) {
599                 gint errnum = errno;
600                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
601                 return FALSE;
602         }
603
604         /* Write the tail */
605         if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
606                 ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE);
607                 if (ret == SOCKET_ERROR)
608                         return FALSE;
609         }
610
611         if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
612                 mono_w32handle_close (handle);
613
614         return TRUE;
615 }
616
617 SOCKET
618 mono_w32socket_socket (int domain, int type, int protocol)
619 {
620         MonoW32HandleSocket socket_handle = {0};
621         gpointer handle;
622         SOCKET sock;
623
624         socket_handle.domain = domain;
625         socket_handle.type = type;
626         socket_handle.protocol = protocol;
627         socket_handle.still_readable = 1;
628
629         sock = socket (domain, type, protocol);
630         if (sock == -1 && domain == AF_INET && type == SOCK_RAW &&
631             protocol == 0) {
632                 /* Retry with protocol == 4 (see bug #54565) */
633                 // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
634                 socket_handle.protocol = 4;
635                 sock = socket (AF_INET, SOCK_RAW, 4);
636         }
637
638         if (sock == -1) {
639                 gint errnum = errno;
640                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno));
641                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
642                 return INVALID_SOCKET;
643         }
644
645         if (sock >= mono_w32handle_fd_reserve) {
646                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)",
647                            __func__, sock, mono_w32handle_fd_reserve);
648
649                 mono_w32socket_set_last_error (WSASYSCALLFAILURE);
650                 close (sock);
651
652                 return INVALID_SOCKET;
653         }
654
655         /* .net seems to set this by default for SOCK_STREAM, not for
656          * SOCK_DGRAM (see bug #36322)
657          * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322
658          *
659          * It seems winsock has a rather different idea of what
660          * SO_REUSEADDR means.  If it's set, then a new socket can be
661          * bound over an existing listening socket.  There's a new
662          * windows-specific option called SO_EXCLUSIVEADDRUSE but
663          * using that means the socket MUST be closed properly, or a
664          * denial of service can occur.  Luckily for us, winsock
665          * behaves as though any other system would when SO_REUSEADDR
666          * is true, so we don't need to do anything else here.  See
667          * bug 53992.
668          * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992
669          */
670         {
671                 int ret, true_ = 1;
672
673                 ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
674                 if (ret == -1) {
675                         close (sock);
676                         gint errnum = errno;
677                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
678                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
679                         return INVALID_SOCKET;
680                 }
681         }
682
683
684         handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, sock, &socket_handle);
685         if (handle == INVALID_HANDLE_VALUE) {
686                 g_warning ("%s: error creating socket handle", __func__);
687                 mono_w32socket_set_last_error (WSASYSCALLFAILURE);
688                 close (sock);
689                 return INVALID_SOCKET;
690         }
691
692         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle);
693
694         return sock;
695 }
696
697 gint
698 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
699 {
700         gpointer handle;
701         int ret;
702
703         handle = GUINT_TO_POINTER (sock);
704         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
705                 mono_w32socket_set_last_error (WSAENOTSOCK);
706                 return SOCKET_ERROR;
707         }
708
709         ret = bind (sock, addr, addrlen);
710         if (ret == -1) {
711                 gint errnum = errno;
712                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno));
713                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
714                 return SOCKET_ERROR;
715         }
716
717         return 0;
718 }
719
720 gint
721 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
722 {
723         gpointer handle;
724         gint ret;
725
726         handle = GUINT_TO_POINTER (sock);
727         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
728                 mono_w32socket_set_last_error (WSAENOTSOCK);
729                 return SOCKET_ERROR;
730         }
731
732         ret = getpeername (sock, name, namelen);
733         if (ret == -1) {
734                 gint errnum = errno;
735                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno));
736                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
737                 return SOCKET_ERROR;
738         }
739
740         return 0;
741 }
742
743 gint
744 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
745 {
746         gpointer handle;
747         gint ret;
748
749         handle = GUINT_TO_POINTER (sock);
750         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
751                 mono_w32socket_set_last_error (WSAENOTSOCK);
752                 return SOCKET_ERROR;
753         }
754
755         ret = getsockname (sock, name, namelen);
756         if (ret == -1) {
757                 gint errnum = errno;
758                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno));
759                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
760                 return SOCKET_ERROR;
761         }
762
763         return 0;
764 }
765
766 gint
767 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
768 {
769         gpointer handle;
770         gint ret;
771         struct timeval tv;
772         gpointer tmp_val;
773         MonoW32HandleSocket *socket_handle;
774
775         handle = GUINT_TO_POINTER (sock);
776         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
777                 mono_w32socket_set_last_error (WSAENOTSOCK);
778                 return SOCKET_ERROR;
779         }
780
781         tmp_val = optval;
782         if (level == SOL_SOCKET &&
783             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
784                 tmp_val = &tv;
785                 *optlen = sizeof (tv);
786         }
787
788         ret = getsockopt (sock, level, optname, tmp_val, optlen);
789         if (ret == -1) {
790                 gint errnum = errno;
791                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
792                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
793                 return SOCKET_ERROR;
794         }
795
796         if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
797                 *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000);     // milli from micro
798                 *optlen = sizeof (int);
799         }
800
801         if (optname == SO_ERROR) {
802                 if (*((int *)optval) != 0) {
803                         *((int *) optval) = mono_w32socket_convert_error (*((int *)optval));
804                         socket_handle->saved_error = *((int *)optval);
805                 } else {
806                         *((int *)optval) = socket_handle->saved_error;
807                 }
808         }
809
810         return 0;
811 }
812
813 gint
814 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
815 {
816         gpointer handle;
817         gint ret;
818         gpointer tmp_val;
819 #if defined (__linux__)
820         /* This has its address taken so it cannot be moved to the if block which uses it */
821         gint bufsize = 0;
822 #endif
823         struct timeval tv;
824
825         handle = GUINT_TO_POINTER (sock);
826         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
827                 mono_w32socket_set_last_error (WSAENOTSOCK);
828                 return SOCKET_ERROR;
829         }
830
831         tmp_val = optval;
832         if (level == SOL_SOCKET &&
833             (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
834                 int ms = *((int *) optval);
835                 tv.tv_sec = ms / 1000;
836                 tv.tv_usec = (ms % 1000) * 1000;        // micro from milli
837                 tmp_val = &tv;
838                 optlen = sizeof (tv);
839         }
840 #if defined (__linux__)
841         else if (level == SOL_SOCKET &&
842                    (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
843                 /* According to socket(7) the Linux kernel doubles the
844                  * buffer sizes "to allow space for bookkeeping
845                  * overhead."
846                  */
847                 bufsize = *((int *) optval);
848
849                 bufsize /= 2;
850                 tmp_val = &bufsize;
851         }
852 #endif
853
854         ret = setsockopt (sock, level, optname, tmp_val, optlen);
855         if (ret == -1) {
856                 gint errnum = errno;
857                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno));
858                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
859                 return SOCKET_ERROR;
860         }
861
862 #if defined (SO_REUSEPORT)
863         /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
864         if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
865                 int type;
866                 socklen_t type_len = sizeof (type);
867
868                 if (!getsockopt (sock, level, SO_TYPE, &type, &type_len)) {
869                         if (type == SOCK_DGRAM || type == SOCK_STREAM)
870                                 setsockopt (sock, level, SO_REUSEPORT, tmp_val, optlen);
871                 }
872         }
873 #endif
874
875         return ret;
876 }
877
878 gint
879 mono_w32socket_listen (SOCKET sock, gint backlog)
880 {
881         gpointer handle;
882         gint ret;
883
884         handle = GUINT_TO_POINTER (sock);
885         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
886                 mono_w32socket_set_last_error (WSAENOTSOCK);
887                 return SOCKET_ERROR;
888         }
889
890         ret = listen (sock, backlog);
891         if (ret == -1) {
892                 gint errnum = errno;
893                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno));
894                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
895                 return SOCKET_ERROR;
896         }
897
898         return 0;
899 }
900
901 gint
902 mono_w32socket_shutdown (SOCKET sock, gint how)
903 {
904         MonoW32HandleSocket *socket_handle;
905         gpointer handle;
906         gint ret;
907
908         handle = GUINT_TO_POINTER (sock);
909         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
910                 mono_w32socket_set_last_error (WSAENOTSOCK);
911                 return SOCKET_ERROR;
912         }
913
914         if (how == SHUT_RD || how == SHUT_RDWR)
915                 socket_handle->still_readable = 0;
916
917         ret = shutdown (sock, how);
918         if (ret == -1) {
919                 gint errnum = errno;
920                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno));
921                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
922                 return SOCKET_ERROR;
923         }
924
925         return ret;
926 }
927
928 gint
929 mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
930 {
931         MonoW32HandleSocket *socket_handle;
932         gpointer handle;
933         SOCKET newsock;
934         gint ret;
935
936         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, sock);
937
938         /* We could check the socket type here and fail unless its
939          * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
940          * if we really wanted to */
941
942         handle = GUINT_TO_POINTER (sock);
943         if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
944                 mono_w32socket_set_last_error (WSAENOTSOCK);
945                 return SOCKET_ERROR;
946         }
947
948         newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol);
949         if (newsock == -1) {
950                 gint errnum = errno;
951                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum));
952                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
953                 return SOCKET_ERROR;
954         }
955
956         /* According to Stevens "Advanced Programming in the UNIX
957          * Environment: UNIX File I/O" dup2() is atomic so there
958          * should not be a race condition between the old fd being
959          * closed and the new socket fd being copied over */
960         do {
961                 ret = dup2 (newsock, sock);
962         } while (ret == -1 && errno == EAGAIN);
963
964         if (ret == -1) {
965                 gint errnum = errno;
966                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum));
967                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
968                 return SOCKET_ERROR;
969         }
970
971         close (newsock);
972
973         return 0;
974 }
975
976 static gboolean
977 extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved)
978 {
979         return mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
980 }
981
982 static gboolean
983 extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send,
984         OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags)
985 {
986         return mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
987 }
988
989 static struct {
990         GUID guid;
991         gpointer func;
992 } extension_functions[] = {
993         { {0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}} /* WSAID_DISCONNECTEX */, extension_disconect },
994         { {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} /* WSAID_TRANSMITFILE */, extension_transmit_file },
995         { {0} , NULL },
996 };
997
998 gint
999 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
1000 {
1001         gpointer handle;
1002         gint ret;
1003         gchar *buffer;
1004
1005         handle = GUINT_TO_POINTER (sock);
1006         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
1007                 mono_w32socket_set_last_error (WSAENOTSOCK);
1008                 return SOCKET_ERROR;
1009         }
1010
1011         if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
1012                 gint i;
1013                 GUID *guid;
1014
1015                 if (inputlen < sizeof(GUID)) {
1016                         /* As far as I can tell, windows doesn't
1017                          * actually set an error here...
1018                          */
1019                         mono_w32socket_set_last_error (WSAEINVAL);
1020                         return SOCKET_ERROR;
1021                 }
1022
1023                 if (outputlen < sizeof(gpointer)) {
1024                         /* Or here... */
1025                         mono_w32socket_set_last_error (WSAEINVAL);
1026                         return SOCKET_ERROR;
1027                 }
1028
1029                 if (output == NULL) {
1030                         /* Or here */
1031                         mono_w32socket_set_last_error (WSAEINVAL);
1032                         return SOCKET_ERROR;
1033                 }
1034
1035                 guid = (GUID*) input;
1036                 for (i = 0; extension_functions[i].func; i++) {
1037                         if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
1038                                 memcpy (output, &extension_functions[i].func, sizeof(gpointer));
1039                                 *written = sizeof(gpointer);
1040                                 return 0;
1041                         }
1042                 }
1043
1044                 mono_w32socket_set_last_error (WSAEINVAL);
1045                 return SOCKET_ERROR;
1046         }
1047
1048         if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) {
1049                 guint32 onoff;
1050
1051                 if (inputlen < 3 * sizeof (guint32)) {
1052                         mono_w32socket_set_last_error (WSAEINVAL);
1053                         return SOCKET_ERROR;
1054                 }
1055
1056                 onoff = *((guint32*) input);
1057
1058                 ret = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
1059                 if (ret < 0) {
1060                         mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1061                         return SOCKET_ERROR;
1062                 }
1063
1064 #if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
1065                 if (onoff != 0) {
1066                         /* Values are in ms, but we need s */
1067                         guint32 keepalivetime, keepaliveinterval, rem;
1068
1069                         keepalivetime = *(((guint32*) input) + 1);
1070                         keepaliveinterval = *(((guint32*) input) + 2);
1071
1072                         /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
1073                         rem = keepalivetime % 1000;
1074                         keepalivetime /= 1000;
1075                         if (keepalivetime == 0 || rem >= 500)
1076                                 keepalivetime++;
1077                         ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
1078                         if (ret == 0) {
1079                                 rem = keepaliveinterval % 1000;
1080                                 keepaliveinterval /= 1000;
1081                                 if (keepaliveinterval == 0 || rem >= 500)
1082                                         keepaliveinterval++;
1083                                 ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
1084                         }
1085                         if (ret != 0) {
1086                                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
1087                                 return SOCKET_ERROR;
1088                         }
1089
1090                         return 0;
1091                 }
1092 #endif
1093
1094                 return 0;
1095         }
1096
1097         buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;
1098
1099         ret = ioctl (sock, command, buffer);
1100         if (ret == -1) {
1101                 g_free (buffer);
1102
1103                 gint errnum = errno;
1104                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
1105                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1106                 return SOCKET_ERROR;
1107         }
1108
1109         if (!buffer) {
1110                 *written = 0;
1111                 return 0;
1112         }
1113
1114         /* We just copy the buffer to the output. Some ioctls
1115          * don't even output any data, but, well...
1116          *
1117          * NB windows returns WSAEFAULT if outputlen is too small */
1118         inputlen = (inputlen > outputlen) ? outputlen : inputlen;
1119
1120         if (inputlen > 0 && output != NULL)
1121                 memcpy (output, buffer, inputlen);
1122
1123         g_free (buffer);
1124         *written = inputlen;
1125
1126         return 0;
1127 }
1128
1129 gboolean
1130 mono_w32socket_close (SOCKET sock)
1131 {
1132         return mono_w32handle_close (GINT_TO_POINTER (sock));
1133 }
1134
1135 gint
1136 mono_w32socket_set_blocking (SOCKET socket, gboolean blocking)
1137 {
1138 #ifdef O_NONBLOCK
1139         gint ret;
1140         gpointer handle;
1141
1142         handle = GINT_TO_POINTER (socket);
1143         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
1144                 mono_w32socket_set_last_error (WSAENOTSOCK);
1145                 return SOCKET_ERROR;
1146         }
1147
1148         /* This works better than ioctl(...FIONBIO...)
1149          * on Linux (it causes connect to return
1150          * EINPROGRESS, but the ioctl doesn't seem to) */
1151         ret = fcntl (socket, F_GETFL, 0);
1152         if (ret != -1)
1153                 ret = fcntl (socket, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
1154
1155         if (ret == -1) {
1156                 gint errnum = errno;
1157                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
1158                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1159                 return SOCKET_ERROR;
1160         }
1161
1162         return 0;
1163 #else
1164         mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED);
1165         return SOCKET_ERROR;
1166 #endif /* O_NONBLOCK */
1167 }
1168
1169 gint
1170 mono_w32socket_get_available (SOCKET socket, guint64 *amount)
1171 {
1172         gint ret;
1173         gpointer handle;
1174
1175         handle = GINT_TO_POINTER (socket);
1176         if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
1177                 mono_w32socket_set_last_error (WSAENOTSOCK);
1178                 return SOCKET_ERROR;
1179         }
1180
1181 #if defined (PLATFORM_MACOSX)
1182         // ioctl (socket, FIONREAD, XXX) returns the size of
1183         // the UDP header as well on Darwin.
1184         //
1185         // Use getsockopt SO_NREAD instead to get the
1186         // right values for TCP and UDP.
1187         //
1188         // ai_canonname can be null in some cases on darwin,
1189         // where the runtime assumes it will be the value of
1190         // the ip buffer.
1191
1192         socklen_t optlen = sizeof (int);
1193         ret = getsockopt (socket, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
1194 #else
1195         ret = ioctl (socket, FIONREAD, (gulong*) amount);
1196 #endif
1197
1198         if (ret == -1) {
1199                 gint errnum = errno;
1200                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
1201                 mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
1202                 return SOCKET_ERROR;
1203         }
1204
1205         return 0;
1206 }
1207
1208 void
1209 mono_w32socket_set_last_error (gint32 error)
1210 {
1211         mono_w32error_set_last (error);
1212 }
1213
1214 gint32
1215 mono_w32socket_get_last_error (void)
1216 {
1217         return mono_w32error_get_last ();
1218 }
1219
1220 gint32
1221 mono_w32socket_convert_error (gint error)
1222 {
1223         switch (error) {
1224         case 0: return ERROR_SUCCESS;
1225         case EACCES: return WSAEACCES;
1226 #ifdef EADDRINUSE
1227         case EADDRINUSE: return WSAEADDRINUSE;
1228 #endif
1229 #ifdef EAFNOSUPPORT
1230         case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
1231 #endif
1232 #if EAGAIN != EWOULDBLOCK
1233         case EAGAIN: return WSAEWOULDBLOCK;
1234 #endif
1235 #ifdef EALREADY
1236         case EALREADY: return WSAEALREADY;
1237 #endif
1238         case EBADF: return WSAENOTSOCK;
1239 #ifdef ECONNABORTED
1240         case ECONNABORTED: return WSAENETDOWN;
1241 #endif
1242 #ifdef ECONNREFUSED
1243         case ECONNREFUSED: return WSAECONNREFUSED;
1244 #endif
1245 #ifdef ECONNRESET
1246         case ECONNRESET: return WSAECONNRESET;
1247 #endif
1248         case EFAULT: return WSAEFAULT;
1249 #ifdef EHOSTUNREACH
1250         case EHOSTUNREACH: return WSAEHOSTUNREACH;
1251 #endif
1252 #ifdef EINPROGRESS
1253         case EINPROGRESS: return WSAEINPROGRESS;
1254 #endif
1255         case EINTR: return WSAEINTR;
1256         case EINVAL: return WSAEINVAL;
1257         /*FIXME: case EIO: return WSAE????; */
1258 #ifdef EISCONN
1259         case EISCONN: return WSAEISCONN;
1260 #endif
1261         /* FIXME: case ELOOP: return WSA????; */
1262         case EMFILE: return WSAEMFILE;
1263 #ifdef EMSGSIZE
1264         case EMSGSIZE: return WSAEMSGSIZE;
1265 #endif
1266         /* FIXME: case ENAMETOOLONG: return WSAEACCES; */
1267 #ifdef ENETUNREACH
1268         case ENETUNREACH: return WSAENETUNREACH;
1269 #endif
1270 #ifdef ENOBUFS
1271         case ENOBUFS: return WSAENOBUFS; /* not documented */
1272 #endif
1273         /* case ENOENT: return WSAE????; */
1274         case ENOMEM: return WSAENOBUFS;
1275 #ifdef ENOPROTOOPT
1276         case ENOPROTOOPT: return WSAENOPROTOOPT;
1277 #endif
1278 #ifdef ENOSR
1279         case ENOSR: return WSAENETDOWN;
1280 #endif
1281 #ifdef ENOTCONN
1282         case ENOTCONN: return WSAENOTCONN;
1283 #endif
1284         /*FIXME: case ENOTDIR: return WSAE????; */
1285 #ifdef ENOTSOCK
1286         case ENOTSOCK: return WSAENOTSOCK;
1287 #endif
1288         case ENOTTY: return WSAENOTSOCK;
1289 #ifdef EOPNOTSUPP
1290         case EOPNOTSUPP: return WSAEOPNOTSUPP;
1291 #endif
1292         case EPERM: return WSAEACCES;
1293         case EPIPE: return WSAESHUTDOWN;
1294 #ifdef EPROTONOSUPPORT
1295         case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
1296 #endif
1297 #if ERESTARTSYS
1298         case ERESTARTSYS: return WSAENETDOWN;
1299 #endif
1300         /*FIXME: case EROFS: return WSAE????; */
1301 #ifdef ESOCKTNOSUPPORT
1302         case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
1303 #endif
1304 #ifdef ETIMEDOUT
1305         case ETIMEDOUT: return WSAETIMEDOUT;
1306 #endif
1307 #ifdef EWOULDBLOCK
1308         case EWOULDBLOCK: return WSAEWOULDBLOCK;
1309 #endif
1310 #ifdef EADDRNOTAVAIL
1311         case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
1312 #endif
1313         /* This might happen with unix sockets */
1314         case ENOENT: return WSAECONNREFUSED;
1315 #ifdef EDESTADDRREQ
1316         case EDESTADDRREQ: return WSAEDESTADDRREQ;
1317 #endif
1318 #ifdef EHOSTDOWN
1319         case EHOSTDOWN: return WSAEHOSTDOWN;
1320 #endif
1321 #ifdef ENETDOWN
1322         case ENETDOWN: return WSAENETDOWN;
1323 #endif
1324         case ENODEV: return WSAENETDOWN;
1325 #ifdef EPROTOTYPE
1326         case EPROTOTYPE: return WSAEPROTOTYPE;
1327 #endif
1328 #ifdef ENXIO
1329         case ENXIO: return WSAENXIO;
1330 #endif
1331         default:
1332                 g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error));
1333         }
1334 }
1335
1336 gboolean
1337 ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError *error)
1338 {
1339         error_init (error);
1340 #if defined (SO_REUSEPORT)
1341         return TRUE;
1342 #else
1343 #ifdef __linux__
1344         /* Linux always supports double binding for UDP, even on older kernels. */
1345         if (proto == ProtocolType_Udp)
1346                 return TRUE;
1347 #endif
1348         return FALSE;
1349 #endif
1350 }