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