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