2 * sockets.c: Socket handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
15 #include <sys/types.h>
16 #include <sys/socket.h>
20 #ifdef HAVE_SYS_IOCTL_H
21 # include <sys/ioctl.h>
23 #ifdef HAVE_SYS_FILIO_H
24 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
26 #ifdef HAVE_SYS_SOCKIO_H
27 #include <sys/sockio.h> /* defines SIOCATMARK */
32 #ifndef HAVE_MSG_NOSIGNAL
36 #include <mono/io-layer/wapi.h>
37 #include <mono/io-layer/wapi-private.h>
38 #include <mono/io-layer/socket-private.h>
39 #include <mono/io-layer/handles-private.h>
40 #include <mono/io-layer/socket-wrappers.h>
41 #include <mono/utils/mono-poll.h>
43 #include <netinet/in.h>
44 #include <netinet/tcp.h>
46 #include <arpa/inet.h>
47 #ifdef HAVE_SYS_SENDFILE_H
48 #include <sys/sendfile.h>
53 static guint32 startup_count
=0;
55 static void socket_close (gpointer handle
, gpointer data
);
57 struct _WapiHandleOps _wapi_socket_ops
= {
58 socket_close
, /* close */
62 NULL
, /* special_wait */
66 static mono_once_t socket_ops_once
=MONO_ONCE_INIT
;
68 static void socket_ops_init (void)
70 /* No capabilities to register */
73 static void socket_close (gpointer handle
, gpointer data
)
76 struct _WapiHandle_socket
*socket_handle
= (struct _WapiHandle_socket
*)data
;
79 g_message ("%s: closing socket handle %p", __func__
, handle
);
82 if (startup_count
== 0) {
83 WSASetLastError (WSANOTINITIALISED
);
87 /* Shutdown the socket for reading, to interrupt any potential
88 * receives that may be blocking for data. See bug 75705.
90 shutdown (GPOINTER_TO_UINT (handle
), SHUT_RD
);
93 ret
= close (GPOINTER_TO_UINT(handle
));
94 } while (ret
== -1 && errno
== EINTR
&&
95 !_wapi_thread_cur_apc_pending ());
100 g_message ("%s: close error: %s", __func__
, strerror (errno
));
102 errnum
= errno_to_WSA (errnum
, __func__
);
103 WSASetLastError (errnum
);
106 socket_handle
->saved_error
= 0;
109 int WSAStartup(guint32 requested
, WapiWSAData
*data
)
115 /* Insist on v2.0+ */
116 if (requested
< MAKEWORD(2,0)) {
117 return(WSAVERNOTSUPPORTED
);
122 /* I've no idea what is the minor version of the spec I read */
123 data
->wHighVersion
= MAKEWORD(2,2);
125 data
->wVersion
= requested
< data
->wHighVersion
? requested
:
129 g_message ("%s: high version 0x%x", __func__
, data
->wHighVersion
);
132 strncpy (data
->szDescription
, "WAPI", WSADESCRIPTION_LEN
);
133 strncpy (data
->szSystemStatus
, "groovy", WSASYS_STATUS_LEN
);
139 cleanup_close (gpointer handle
, gpointer data
)
141 _wapi_handle_ops_close (handle
, NULL
);
148 g_message ("%s: cleaning up", __func__
);
151 if (--startup_count
) {
156 _wapi_handle_foreach (WAPI_HANDLE_SOCKET
, cleanup_close
, NULL
);
160 void WSASetLastError(int error
)
162 SetLastError (error
);
165 int WSAGetLastError(void)
167 return(GetLastError ());
170 int closesocket(guint32 fd
)
172 gpointer handle
= GUINT_TO_POINTER (fd
);
174 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
175 WSASetLastError (WSAENOTSOCK
);
179 _wapi_handle_unref (handle
);
183 guint32
_wapi_accept(guint32 fd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
185 gpointer handle
= GUINT_TO_POINTER (fd
);
187 struct _WapiHandle_socket
*socket_handle
;
188 struct _WapiHandle_socket new_socket_handle
= {0};
192 if (startup_count
== 0) {
193 WSASetLastError (WSANOTINITIALISED
);
194 return(INVALID_SOCKET
);
197 if (addr
!= NULL
&& *addrlen
< sizeof(struct sockaddr
)) {
198 WSASetLastError (WSAEFAULT
);
199 return(INVALID_SOCKET
);
202 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
203 WSASetLastError (WSAENOTSOCK
);
204 return(INVALID_SOCKET
);
207 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
208 (gpointer
*)&socket_handle
);
210 g_warning ("%s: error looking up socket handle %p",
212 WSASetLastError (WSAENOTSOCK
);
213 return(INVALID_SOCKET
);
217 new_fd
= accept (fd
, addr
, addrlen
);
218 } while (new_fd
== -1 && errno
== EINTR
&&
219 !_wapi_thread_cur_apc_pending());
224 g_message ("%s: accept error: %s", __func__
, strerror(errno
));
227 errnum
= errno_to_WSA (errnum
, __func__
);
228 WSASetLastError (errnum
);
230 return(INVALID_SOCKET
);
233 if (new_fd
>= _wapi_fd_reserve
) {
235 g_message ("%s: File descriptor is too big", __func__
);
238 WSASetLastError (WSASYSCALLFAILURE
);
242 return(INVALID_SOCKET
);
245 new_socket_handle
.domain
= socket_handle
->domain
;
246 new_socket_handle
.type
= socket_handle
->type
;
247 new_socket_handle
.protocol
= socket_handle
->protocol
;
248 new_socket_handle
.still_readable
= 1;
250 new_handle
= _wapi_handle_new_fd (WAPI_HANDLE_SOCKET
, new_fd
,
252 if(new_handle
== _WAPI_HANDLE_INVALID
) {
253 g_warning ("%s: error creating socket handle", __func__
);
254 WSASetLastError (ERROR_GEN_FAILURE
);
255 return(INVALID_SOCKET
);
259 g_message ("%s: returning newly accepted socket handle %p with",
260 __func__
, new_handle
);
266 int _wapi_bind(guint32 fd
, struct sockaddr
*my_addr
, socklen_t addrlen
)
268 gpointer handle
= GUINT_TO_POINTER (fd
);
271 if (startup_count
== 0) {
272 WSASetLastError (WSANOTINITIALISED
);
273 return(SOCKET_ERROR
);
276 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
277 WSASetLastError (WSAENOTSOCK
);
278 return(SOCKET_ERROR
);
281 ret
= bind (fd
, my_addr
, addrlen
);
285 g_message ("%s: bind error: %s", __func__
, strerror(errno
));
287 errnum
= errno_to_WSA (errnum
, __func__
);
288 WSASetLastError (errnum
);
290 return(SOCKET_ERROR
);
295 int _wapi_connect(guint32 fd
, const struct sockaddr
*serv_addr
,
298 gpointer handle
= GUINT_TO_POINTER (fd
);
299 struct _WapiHandle_socket
*socket_handle
;
303 if (startup_count
== 0) {
304 WSASetLastError (WSANOTINITIALISED
);
305 return(SOCKET_ERROR
);
308 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
309 WSASetLastError (WSAENOTSOCK
);
310 return(SOCKET_ERROR
);
313 if (connect (fd
, serv_addr
, addrlen
) == -1) {
320 if (errno
!= EINTR
) {
322 g_message ("%s: connect error: %s", __func__
,
326 errnum
= errno_to_WSA (errnum
, __func__
);
327 if (errnum
== WSAEINPROGRESS
)
328 errnum
= WSAEWOULDBLOCK
; /* see bug #73053 */
330 WSASetLastError (errnum
);
333 * On solaris x86 getsockopt (SO_ERROR) is not set after
334 * connect () fails so we need to save this error.
336 * But don't do this for EWOULDBLOCK (bug 317315)
338 if (errnum
!= WSAEWOULDBLOCK
) {
339 ok
= _wapi_lookup_handle (handle
,
341 (gpointer
*)&socket_handle
);
343 /* ECONNRESET means the socket was closed by another thread */
344 if (errnum
!= WSAECONNRESET
)
345 g_warning ("%s: error looking up socket handle %p (error %d)", __func__
, handle
, errnum
);
347 socket_handle
->saved_error
= errnum
;
350 return(SOCKET_ERROR
);
354 fds
.events
= POLLOUT
;
355 while (mono_poll (&fds
, 1, -1) == -1 &&
356 !_wapi_thread_cur_apc_pending ()) {
357 if (errno
!= EINTR
) {
358 errnum
= errno_to_WSA (errno
, __func__
);
361 g_message ("%s: connect poll error: %s",
362 __func__
, strerror (errno
));
365 WSASetLastError (errnum
);
366 return(SOCKET_ERROR
);
370 len
= sizeof(so_error
);
371 if (getsockopt (fd
, SOL_SOCKET
, SO_ERROR
, &so_error
,
373 errnum
= errno_to_WSA (errno
, __func__
);
376 g_message ("%s: connect getsockopt error: %s",
377 __func__
, strerror (errno
));
380 WSASetLastError (errnum
);
381 return(SOCKET_ERROR
);
385 errnum
= errno_to_WSA (so_error
, __func__
);
387 /* Need to save this socket error */
388 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
389 (gpointer
*)&socket_handle
);
391 g_warning ("%s: error looking up socket handle %p", __func__
, handle
);
393 socket_handle
->saved_error
= errnum
;
397 g_message ("%s: connect getsockopt returned error: %s",
398 __func__
, strerror (so_error
));
401 WSASetLastError (errnum
);
402 return(SOCKET_ERROR
);
409 int _wapi_getpeername(guint32 fd
, struct sockaddr
*name
, socklen_t
*namelen
)
411 gpointer handle
= GUINT_TO_POINTER (fd
);
414 if (startup_count
== 0) {
415 WSASetLastError (WSANOTINITIALISED
);
416 return(SOCKET_ERROR
);
419 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
420 WSASetLastError (WSAENOTSOCK
);
421 return(SOCKET_ERROR
);
424 ret
= getpeername (fd
, name
, namelen
);
428 g_message ("%s: getpeername error: %s", __func__
,
432 errnum
= errno_to_WSA (errnum
, __func__
);
433 WSASetLastError (errnum
);
435 return(SOCKET_ERROR
);
441 int _wapi_getsockname(guint32 fd
, struct sockaddr
*name
, socklen_t
*namelen
)
443 gpointer handle
= GUINT_TO_POINTER (fd
);
446 if (startup_count
== 0) {
447 WSASetLastError (WSANOTINITIALISED
);
448 return(SOCKET_ERROR
);
451 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
452 WSASetLastError (WSAENOTSOCK
);
453 return(SOCKET_ERROR
);
456 ret
= getsockname (fd
, name
, namelen
);
460 g_message ("%s: getsockname error: %s", __func__
,
464 errnum
= errno_to_WSA (errnum
, __func__
);
465 WSASetLastError (errnum
);
467 return(SOCKET_ERROR
);
473 int _wapi_getsockopt(guint32 fd
, int level
, int optname
, void *optval
,
476 gpointer handle
= GUINT_TO_POINTER (fd
);
480 struct _WapiHandle_socket
*socket_handle
;
483 if (startup_count
== 0) {
484 WSASetLastError (WSANOTINITIALISED
);
485 return(SOCKET_ERROR
);
488 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
489 WSASetLastError (WSAENOTSOCK
);
490 return(SOCKET_ERROR
);
494 if (level
== SOL_SOCKET
&&
495 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
497 *optlen
= sizeof (tv
);
500 ret
= getsockopt (fd
, level
, optname
, tmp_val
, optlen
);
504 g_message ("%s: getsockopt error: %s", __func__
,
508 errnum
= errno_to_WSA (errnum
, __func__
);
509 WSASetLastError (errnum
);
511 return(SOCKET_ERROR
);
514 if (level
== SOL_SOCKET
&&
515 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
516 *((int *) optval
) = tv
.tv_sec
* 1000 + (tv
.tv_usec
/ 1000); // milli from micro
517 *optlen
= sizeof (int);
520 if (optname
== SO_ERROR
) {
521 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
522 (gpointer
*)&socket_handle
);
524 g_warning ("%s: error looking up socket handle %p",
527 /* can't extract the last error */
528 *((int *) optval
) = errno_to_WSA (*((int *)optval
),
531 if (*((int *)optval
) != 0) {
532 *((int *) optval
) = errno_to_WSA (*((int *)optval
),
534 socket_handle
->saved_error
= *((int *)optval
);
536 *((int *)optval
) = socket_handle
->saved_error
;
544 int _wapi_listen(guint32 fd
, int backlog
)
546 gpointer handle
= GUINT_TO_POINTER (fd
);
549 if (startup_count
== 0) {
550 WSASetLastError (WSANOTINITIALISED
);
551 return(SOCKET_ERROR
);
554 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
555 WSASetLastError (WSAENOTSOCK
);
556 return(SOCKET_ERROR
);
559 ret
= listen (fd
, backlog
);
563 g_message ("%s: listen error: %s", __func__
, strerror (errno
));
566 errnum
= errno_to_WSA (errnum
, __func__
);
567 WSASetLastError (errnum
);
569 return(SOCKET_ERROR
);
575 int _wapi_recv(guint32 fd
, void *buf
, size_t len
, int recv_flags
)
577 return(_wapi_recvfrom (fd
, buf
, len
, recv_flags
, NULL
, 0));
580 int _wapi_recvfrom(guint32 fd
, void *buf
, size_t len
, int recv_flags
,
581 struct sockaddr
*from
, socklen_t
*fromlen
)
583 gpointer handle
= GUINT_TO_POINTER (fd
);
584 struct _WapiHandle_socket
*socket_handle
;
588 if (startup_count
== 0) {
589 WSASetLastError (WSANOTINITIALISED
);
590 return(SOCKET_ERROR
);
593 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
594 WSASetLastError (WSAENOTSOCK
);
595 return(SOCKET_ERROR
);
599 ret
= recvfrom (fd
, buf
, len
, recv_flags
, from
, fromlen
);
600 } while (ret
== -1 && errno
== EINTR
&&
601 !_wapi_thread_cur_apc_pending ());
603 if (ret
== 0 && len
> 0) {
604 /* According to the Linux man page, recvfrom only
605 * returns 0 when the socket has been shut down
606 * cleanly. Turn this into an EINTR to simulate win32
607 * behaviour of returning EINTR when a socket is
608 * closed while the recvfrom is blocking (we use a
609 * shutdown() in socket_close() to trigger this.) See
612 /* Distinguish between the socket being shut down at
613 * the local or remote ends, and reads that request 0
617 /* If this returns FALSE, it means the socket has been
618 * closed locally. If it returns TRUE, but
619 * still_readable != 1 then shutdown
620 * (SHUT_RD|SHUT_RDWR) has been called locally.
622 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
623 (gpointer
*)&socket_handle
);
624 if (ok
== FALSE
|| socket_handle
->still_readable
!= 1) {
633 g_message ("%s: recv error: %s", __func__
, strerror(errno
));
636 errnum
= errno_to_WSA (errnum
, __func__
);
637 WSASetLastError (errnum
);
639 return(SOCKET_ERROR
);
645 _wapi_recvmsg(guint32 fd
, struct msghdr
*msg
, int recv_flags
)
647 gpointer handle
= GUINT_TO_POINTER (fd
);
648 struct _WapiHandle_socket
*socket_handle
;
652 if (startup_count
== 0) {
653 WSASetLastError (WSANOTINITIALISED
);
654 return(SOCKET_ERROR
);
657 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
658 WSASetLastError (WSAENOTSOCK
);
659 return(SOCKET_ERROR
);
663 ret
= recvmsg (fd
, msg
, recv_flags
);
664 } while (ret
== -1 && errno
== EINTR
&&
665 !_wapi_thread_cur_apc_pending ());
668 /* see _wapi_recvfrom */
669 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
670 (gpointer
*)&socket_handle
);
671 if (ok
== FALSE
|| socket_handle
->still_readable
!= 1) {
680 g_message ("%s: recvmsg error: %s", __func__
, strerror(errno
));
683 errnum
= errno_to_WSA (errnum
, __func__
);
684 WSASetLastError (errnum
);
686 return(SOCKET_ERROR
);
691 int _wapi_send(guint32 fd
, const void *msg
, size_t len
, int send_flags
)
693 gpointer handle
= GUINT_TO_POINTER (fd
);
696 if (startup_count
== 0) {
697 WSASetLastError (WSANOTINITIALISED
);
698 return(SOCKET_ERROR
);
701 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
702 WSASetLastError (WSAENOTSOCK
);
703 return(SOCKET_ERROR
);
707 ret
= send (fd
, msg
, len
, send_flags
);
708 } while (ret
== -1 && errno
== EINTR
&&
709 !_wapi_thread_cur_apc_pending ());
714 g_message ("%s: send error: %s", __func__
, strerror (errno
));
717 errnum
= errno_to_WSA (errnum
, __func__
);
718 WSASetLastError (errnum
);
720 return(SOCKET_ERROR
);
725 int _wapi_sendto(guint32 fd
, const void *msg
, size_t len
, int send_flags
,
726 const struct sockaddr
*to
, socklen_t tolen
)
728 gpointer handle
= GUINT_TO_POINTER (fd
);
731 if (startup_count
== 0) {
732 WSASetLastError (WSANOTINITIALISED
);
733 return(SOCKET_ERROR
);
736 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
737 WSASetLastError (WSAENOTSOCK
);
738 return(SOCKET_ERROR
);
742 ret
= sendto (fd
, msg
, len
, send_flags
, to
, tolen
);
743 } while (ret
== -1 && errno
== EINTR
&&
744 !_wapi_thread_cur_apc_pending ());
749 g_message ("%s: send error: %s", __func__
, strerror (errno
));
752 errnum
= errno_to_WSA (errnum
, __func__
);
753 WSASetLastError (errnum
);
755 return(SOCKET_ERROR
);
761 _wapi_sendmsg(guint32 fd
, const struct msghdr
*msg
, int send_flags
)
763 gpointer handle
= GUINT_TO_POINTER (fd
);
766 if (startup_count
== 0) {
767 WSASetLastError (WSANOTINITIALISED
);
768 return(SOCKET_ERROR
);
771 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
772 WSASetLastError (WSAENOTSOCK
);
773 return(SOCKET_ERROR
);
777 ret
= sendmsg (fd
, msg
, send_flags
);
778 } while (ret
== -1 && errno
== EINTR
&&
779 !_wapi_thread_cur_apc_pending ());
784 g_message ("%s: sendmsg error: %s", __func__
, strerror (errno
));
787 errnum
= errno_to_WSA (errnum
, __func__
);
788 WSASetLastError (errnum
);
790 return(SOCKET_ERROR
);
795 int _wapi_setsockopt(guint32 fd
, int level
, int optname
,
796 const void *optval
, socklen_t optlen
)
798 gpointer handle
= GUINT_TO_POINTER (fd
);
803 if (startup_count
== 0) {
804 WSASetLastError (WSANOTINITIALISED
);
805 return(SOCKET_ERROR
);
808 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
809 WSASetLastError (WSAENOTSOCK
);
810 return(SOCKET_ERROR
);
814 if (level
== SOL_SOCKET
&&
815 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
816 int ms
= *((int *) optval
);
817 tv
.tv_sec
= ms
/ 1000;
818 tv
.tv_usec
= (ms
% 1000) * 1000; // micro from milli
820 optlen
= sizeof (tv
);
821 #if defined (__linux__)
822 } else if (level
== SOL_SOCKET
&&
823 (optname
== SO_SNDBUF
|| optname
== SO_RCVBUF
)) {
824 /* According to socket(7) the Linux kernel doubles the
825 * buffer sizes "to allow space for bookkeeping
828 int bufsize
= *((int *) optval
);
835 ret
= setsockopt (fd
, level
, optname
, tmp_val
, optlen
);
839 g_message ("%s: setsockopt error: %s", __func__
,
843 errnum
= errno_to_WSA (errnum
, __func__
);
844 WSASetLastError (errnum
);
846 return(SOCKET_ERROR
);
849 #if defined (SO_REUSEPORT)
850 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
851 if (level
== SOL_SOCKET
&& optname
== SO_REUSEADDR
) {
853 socklen_t type_len
= sizeof (type
);
855 if (!getsockopt (fd
, level
, SO_TYPE
, &type
, &type_len
)) {
856 if (type
== SOCK_DGRAM
)
857 setsockopt (fd
, level
, SO_REUSEPORT
, tmp_val
, optlen
);
865 int _wapi_shutdown(guint32 fd
, int how
)
867 struct _WapiHandle_socket
*socket_handle
;
869 gpointer handle
= GUINT_TO_POINTER (fd
);
872 if (startup_count
== 0) {
873 WSASetLastError (WSANOTINITIALISED
);
874 return(SOCKET_ERROR
);
877 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
878 WSASetLastError (WSAENOTSOCK
);
879 return(SOCKET_ERROR
);
882 if (how
== SHUT_RD
||
884 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
885 (gpointer
*)&socket_handle
);
887 g_warning ("%s: error looking up socket handle %p",
889 WSASetLastError (WSAENOTSOCK
);
890 return(SOCKET_ERROR
);
893 socket_handle
->still_readable
= 0;
896 ret
= shutdown (fd
, how
);
900 g_message ("%s: shutdown error: %s", __func__
,
904 errnum
= errno_to_WSA (errnum
, __func__
);
905 WSASetLastError (errnum
);
907 return(SOCKET_ERROR
);
913 guint32
_wapi_socket(int domain
, int type
, int protocol
, void *unused
,
914 guint32 unused2
, guint32 unused3
)
916 struct _WapiHandle_socket socket_handle
= {0};
920 socket_handle
.domain
= domain
;
921 socket_handle
.type
= type
;
922 socket_handle
.protocol
= protocol
;
923 socket_handle
.still_readable
= 1;
925 fd
= socket (domain
, type
, protocol
);
926 if (fd
== -1 && domain
== AF_INET
&& type
== SOCK_RAW
&&
928 /* Retry with protocol == 4 (see bug #54565) */
929 socket_handle
.protocol
= 4;
930 fd
= socket (AF_INET
, SOCK_RAW
, 4);
936 g_message ("%s: socket error: %s", __func__
, strerror (errno
));
938 errnum
= errno_to_WSA (errnum
, __func__
);
939 WSASetLastError (errnum
);
941 return(INVALID_SOCKET
);
944 if (fd
>= _wapi_fd_reserve
) {
946 g_message ("%s: File descriptor is too big (%d >= %d)",
947 __func__
, fd
, _wapi_fd_reserve
);
950 WSASetLastError (WSASYSCALLFAILURE
);
953 return(INVALID_SOCKET
);
956 /* .net seems to set this by default for SOCK_STREAM, not for
957 * SOCK_DGRAM (see bug #36322)
959 * It seems winsock has a rather different idea of what
960 * SO_REUSEADDR means. If it's set, then a new socket can be
961 * bound over an existing listening socket. There's a new
962 * windows-specific option called SO_EXCLUSIVEADDRUSE but
963 * using that means the socket MUST be closed properly, or a
964 * denial of service can occur. Luckily for us, winsock
965 * behaves as though any other system would when SO_REUSEADDR
966 * is true, so we don't need to do anything else here. See
972 ret
= setsockopt (fd
, SOL_SOCKET
, SO_REUSEADDR
, &true,
978 g_message ("%s: Error setting SO_REUSEADDR", __func__
);
981 errnum
= errno_to_WSA (errnum
, __func__
);
982 WSASetLastError (errnum
);
986 return(INVALID_SOCKET
);
991 mono_once (&socket_ops_once
, socket_ops_init
);
993 handle
= _wapi_handle_new_fd (WAPI_HANDLE_SOCKET
, fd
, &socket_handle
);
994 if (handle
== _WAPI_HANDLE_INVALID
) {
995 g_warning ("%s: error creating socket handle", __func__
);
996 WSASetLastError (WSASYSCALLFAILURE
);
998 return(INVALID_SOCKET
);
1002 g_message ("%s: returning socket handle %p", __func__
, handle
);
1008 struct hostent
*_wapi_gethostbyname(const char *hostname
)
1012 if (startup_count
== 0) {
1013 WSASetLastError (WSANOTINITIALISED
);
1017 he
= gethostbyname (hostname
);
1020 g_message ("%s: gethostbyname error: %s", __func__
,
1021 strerror (h_errno
));
1025 case HOST_NOT_FOUND
:
1026 WSASetLastError (WSAHOST_NOT_FOUND
);
1028 #if NO_ADDRESS != NO_DATA
1032 WSASetLastError (WSANO_DATA
);
1035 WSASetLastError (WSANO_RECOVERY
);
1038 WSASetLastError (WSATRY_AGAIN
);
1041 g_warning ("%s: Need to translate %d into winsock error", __func__
, h_errno
);
1049 static gboolean
socket_disconnect (guint32 fd
)
1051 struct _WapiHandle_socket
*socket_handle
;
1053 gpointer handle
= GUINT_TO_POINTER (fd
);
1056 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
1057 (gpointer
*)&socket_handle
);
1059 g_warning ("%s: error looking up socket handle %p", __func__
,
1061 WSASetLastError (WSAENOTSOCK
);
1065 newsock
= socket (socket_handle
->domain
, socket_handle
->type
,
1066 socket_handle
->protocol
);
1067 if (newsock
== -1) {
1068 gint errnum
= errno
;
1071 g_message ("%s: socket error: %s", __func__
, strerror (errno
));
1074 errnum
= errno_to_WSA (errnum
, __func__
);
1075 WSASetLastError (errnum
);
1080 /* According to Stevens "Advanced Programming in the UNIX
1081 * Environment: UNIX File I/O" dup2() is atomic so there
1082 * should not be a race condition between the old fd being
1083 * closed and the new socket fd being copied over
1086 ret
= dup2 (newsock
, fd
);
1087 } while (ret
== -1 && errno
== EAGAIN
);
1090 gint errnum
= errno
;
1093 g_message ("%s: dup2 error: %s", __func__
, strerror (errno
));
1096 errnum
= errno_to_WSA (errnum
, __func__
);
1097 WSASetLastError (errnum
);
1107 static gboolean
wapi_disconnectex (guint32 fd
, WapiOverlapped
*overlapped
,
1108 guint32 flags
, guint32 reserved
)
1111 g_message ("%s: called on socket %d!", __func__
, fd
);
1114 if (reserved
!= 0) {
1115 WSASetLastError (WSAEINVAL
);
1119 /* We could check the socket type here and fail unless its
1120 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1121 * if we really wanted to
1124 return(socket_disconnect (fd
));
1127 #define SF_BUFFER_SIZE 16384
1129 wapi_sendfile (guint32 socket
, gpointer fd
, guint32 bytes_to_write
, guint32 bytes_per_send
, guint32 flags
)
1131 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1132 gint file
= GPOINTER_TO_INT (fd
);
1136 struct stat statbuf
;
1138 n
= fstat (file
, &statbuf
);
1141 errnum
= errno_to_WSA (errnum
, __func__
);
1142 WSASetLastError (errnum
);
1143 return SOCKET_ERROR
;
1147 res
= sendfile (socket
, file
, NULL
, statbuf
.st_size
);
1148 #elif defined(DARWIN)
1149 /* TODO: header/tail could be sent in the 5th argument */
1150 /* TODO: Might not send the entire file for non-blocking sockets */
1151 res
= sendfile (file
, socket
, 0, &statbuf
.st_size
, NULL
, 0);
1153 } while (res
!= -1 && (errno
== EINTR
|| errno
== EAGAIN
) && !_wapi_thread_cur_apc_pending ());
1156 errnum
= errno_to_WSA (errnum
, __func__
);
1157 WSASetLastError (errnum
);
1158 return SOCKET_ERROR
;
1161 /* Default implementation */
1162 gint file
= GPOINTER_TO_INT (fd
);
1166 buffer
= g_malloc (SF_BUFFER_SIZE
);
1169 n
= read (file
, buffer
, SF_BUFFER_SIZE
);
1170 } while (n
== -1 && errno
== EINTR
&& !_wapi_thread_cur_apc_pending ());
1175 return 0; /* We're done reading */
1178 n
= send (socket
, buffer
, n
, 0); /* short sends? enclose this in a loop? */
1179 } while (n
== -1 && errno
== EINTR
&& !_wapi_thread_cur_apc_pending ());
1183 gint errnum
= errno
;
1184 errnum
= errno_to_WSA (errnum
, __func__
);
1185 WSASetLastError (errnum
);
1187 return SOCKET_ERROR
;
1195 TransmitFile (guint32 socket
, gpointer file
, guint32 bytes_to_write
, guint32 bytes_per_send
, WapiOverlapped
*ol
,
1196 WapiTransmitFileBuffers
*buffers
, guint32 flags
)
1198 gpointer sock
= GUINT_TO_POINTER (socket
);
1201 if (startup_count
== 0) {
1202 WSASetLastError (WSANOTINITIALISED
);
1206 if (_wapi_handle_type (sock
) != WAPI_HANDLE_SOCKET
) {
1207 WSASetLastError (WSAENOTSOCK
);
1211 /* Write the header */
1212 if (buffers
!= NULL
&& buffers
->Head
!= NULL
&& buffers
->HeadLength
> 0) {
1213 ret
= _wapi_send (socket
, buffers
->Head
, buffers
->HeadLength
, 0);
1214 if (ret
== SOCKET_ERROR
)
1218 ret
= wapi_sendfile (socket
, file
, bytes_to_write
, bytes_per_send
, flags
);
1219 if (ret
== SOCKET_ERROR
)
1222 /* Write the tail */
1223 if (buffers
!= NULL
&& buffers
->Tail
!= NULL
&& buffers
->TailLength
> 0) {
1224 ret
= _wapi_send (socket
, buffers
->Tail
, buffers
->TailLength
, 0);
1225 if (ret
== SOCKET_ERROR
)
1229 if ((flags
& TF_DISCONNECT
) == TF_DISCONNECT
)
1230 closesocket (socket
);
1239 } extension_functions
[] = {
1240 {WSAID_DISCONNECTEX
, wapi_disconnectex
},
1241 {WSAID_TRANSMITFILE
, TransmitFile
},
1246 WSAIoctl (guint32 fd
, gint32 command
,
1247 gchar
*input
, gint i_len
,
1248 gchar
*output
, gint o_len
, glong
*written
,
1249 void *unused1
, void *unused2
)
1251 gpointer handle
= GUINT_TO_POINTER (fd
);
1253 gchar
*buffer
= NULL
;
1255 if (startup_count
== 0) {
1256 WSASetLastError (WSANOTINITIALISED
);
1257 return(SOCKET_ERROR
);
1260 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1261 WSASetLastError (WSAENOTSOCK
);
1262 return SOCKET_ERROR
;
1265 if (command
== SIO_GET_EXTENSION_FUNCTION_POINTER
) {
1267 WapiGuid
*guid
= (WapiGuid
*)input
;
1269 if (i_len
< sizeof(WapiGuid
)) {
1270 /* As far as I can tell, windows doesn't
1271 * actually set an error here...
1273 WSASetLastError (WSAEINVAL
);
1274 return(SOCKET_ERROR
);
1277 if (o_len
< sizeof(gpointer
)) {
1279 WSASetLastError (WSAEINVAL
);
1280 return(SOCKET_ERROR
);
1283 if (output
== NULL
) {
1285 WSASetLastError (WSAEINVAL
);
1286 return(SOCKET_ERROR
);
1289 while(extension_functions
[i
].func
!= NULL
) {
1290 if (!memcmp (guid
, &extension_functions
[i
].guid
,
1291 sizeof(WapiGuid
))) {
1292 memcpy (output
, &extension_functions
[i
].func
,
1294 *written
= sizeof(gpointer
);
1301 WSASetLastError (WSAEINVAL
);
1302 return(SOCKET_ERROR
);
1306 buffer
= g_memdup (input
, i_len
);
1309 ret
= ioctl (fd
, command
, buffer
);
1311 gint errnum
= errno
;
1313 g_message("%s: WSAIoctl error: %s", __func__
,
1317 errnum
= errno_to_WSA (errnum
, __func__
);
1318 WSASetLastError (errnum
);
1321 return(SOCKET_ERROR
);
1324 if (buffer
== NULL
) {
1327 /* We just copy the buffer to the output. Some ioctls
1328 * don't even output any data, but, well...
1330 * NB windows returns WSAEFAULT if o_len is too small
1332 i_len
= (i_len
> o_len
) ? o_len
: i_len
;
1334 if (i_len
> 0 && output
!= NULL
) {
1335 memcpy (output
, buffer
, i_len
);
1345 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1346 int ioctlsocket(guint32 fd
, gint32 command
, gpointer arg
)
1348 gpointer handle
= GUINT_TO_POINTER (fd
);
1351 if (startup_count
== 0) {
1352 WSASetLastError (WSANOTINITIALISED
);
1353 return(SOCKET_ERROR
);
1356 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1357 WSASetLastError (WSAENOTSOCK
);
1358 return(SOCKET_ERROR
);
1364 /* This works better than ioctl(...FIONBIO...)
1365 * on Linux (it causes connect to return
1366 * EINPROGRESS, but the ioctl doesn't seem to)
1368 ret
= fcntl(fd
, F_GETFL
, 0);
1370 if (*(gboolean
*)arg
) {
1375 ret
= fcntl(fd
, F_SETFL
, ret
);
1378 #endif /* O_NONBLOCK */
1379 /* Unused in Mono */
1381 ret
= ioctl (fd
, command
, arg
);
1386 #if defined (PLATFORM_MACOSX)
1388 // ioctl (fd, FIONREAD, XXX) returns the size of
1389 // the UDP header as well on
1392 // Use getsockopt SO_NREAD instead to get the
1393 // right values for TCP and UDP.
1395 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1396 // be the value of the ip buffer.
1398 socklen_t optlen
= sizeof (int);
1399 ret
= getsockopt (fd
, SOL_SOCKET
, SO_NREAD
, arg
, &optlen
);
1401 ret
= ioctl (fd
, command
, arg
);
1406 WSASetLastError (WSAEINVAL
);
1407 return(SOCKET_ERROR
);
1411 gint errnum
= errno
;
1413 g_message ("%s: ioctl error: %s", __func__
, strerror (errno
));
1416 errnum
= errno_to_WSA (errnum
, __func__
);
1417 WSASetLastError (errnum
);
1419 return(SOCKET_ERROR
);
1425 int _wapi_select(int nfds G_GNUC_UNUSED
, fd_set
*readfds
, fd_set
*writefds
,
1426 fd_set
*exceptfds
, struct timeval
*timeout
)
1430 if (startup_count
== 0) {
1431 WSASetLastError (WSANOTINITIALISED
);
1432 return(SOCKET_ERROR
);
1435 for (maxfd
= FD_SETSIZE
-1; maxfd
>= 0; maxfd
--) {
1436 if ((readfds
&& FD_ISSET (maxfd
, readfds
)) ||
1437 (writefds
&& FD_ISSET (maxfd
, writefds
)) ||
1438 (exceptfds
&& FD_ISSET (maxfd
, exceptfds
))) {
1444 WSASetLastError (WSAEINVAL
);
1445 return(SOCKET_ERROR
);
1449 ret
= select(maxfd
+ 1, readfds
, writefds
, exceptfds
,
1451 } while (ret
== -1 && errno
== EINTR
&&
1452 !_wapi_thread_cur_apc_pending ());
1455 gint errnum
= errno
;
1457 g_message ("%s: select error: %s", __func__
, strerror (errno
));
1459 errnum
= errno_to_WSA (errnum
, __func__
);
1460 WSASetLastError (errnum
);
1462 return(SOCKET_ERROR
);
1468 void _wapi_FD_CLR(guint32 fd
, fd_set
*set
)
1470 gpointer handle
= GUINT_TO_POINTER (fd
);
1472 if (fd
>= FD_SETSIZE
) {
1473 WSASetLastError (WSAEINVAL
);
1477 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1478 WSASetLastError (WSAENOTSOCK
);
1485 int _wapi_FD_ISSET(guint32 fd
, fd_set
*set
)
1487 gpointer handle
= GUINT_TO_POINTER (fd
);
1489 if (fd
>= FD_SETSIZE
) {
1490 WSASetLastError (WSAEINVAL
);
1494 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1495 WSASetLastError (WSAENOTSOCK
);
1499 return(FD_ISSET (fd
, set
));
1502 void _wapi_FD_SET(guint32 fd
, fd_set
*set
)
1504 gpointer handle
= GUINT_TO_POINTER (fd
);
1506 if (fd
>= FD_SETSIZE
) {
1507 WSASetLastError (WSAEINVAL
);
1511 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1512 WSASetLastError (WSAENOTSOCK
);
1521 wsabuf_to_msghdr (WapiWSABuf
*buffers
, guint32 count
, struct msghdr
*hdr
)
1525 memset (hdr
, 0, sizeof (struct msghdr
));
1526 hdr
->msg_iovlen
= count
;
1527 hdr
->msg_iov
= g_new0 (struct iovec
, count
);
1528 for (i
= 0; i
< count
; i
++) {
1529 hdr
->msg_iov
[i
].iov_base
= buffers
[i
].buf
;
1530 hdr
->msg_iov
[i
].iov_len
= buffers
[i
].len
;
1535 msghdr_iov_free (struct msghdr
*hdr
)
1537 g_free (hdr
->msg_iov
);
1540 int WSARecv (guint32 fd
, WapiWSABuf
*buffers
, guint32 count
, guint32
*received
,
1541 guint32
*flags
, WapiOverlapped
*overlapped
,
1542 WapiOverlappedCB
*complete
)
1547 g_assert (overlapped
== NULL
);
1548 g_assert (complete
== NULL
);
1550 wsabuf_to_msghdr (buffers
, count
, &hdr
);
1551 ret
= _wapi_recvmsg (fd
, &hdr
, *flags
);
1552 msghdr_iov_free (&hdr
);
1554 if(ret
== SOCKET_ERROR
) {
1559 *flags
= hdr
.msg_flags
;
1564 int WSASend (guint32 fd
, WapiWSABuf
*buffers
, guint32 count
, guint32
*sent
,
1565 guint32 flags
, WapiOverlapped
*overlapped
,
1566 WapiOverlappedCB
*complete
)
1571 g_assert (overlapped
== NULL
);
1572 g_assert (complete
== NULL
);
1574 wsabuf_to_msghdr (buffers
, count
, &hdr
);
1575 ret
= _wapi_sendmsg (fd
, &hdr
, flags
);
1576 msghdr_iov_free (&hdr
);
1578 if(ret
== SOCKET_ERROR
)