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>
17 #ifdef HAVE_SYS_IOCTL_H
18 # include <sys/ioctl.h>
21 #ifdef HAVE_SYS_FILIO_H
22 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
24 #ifdef HAVE_SYS_SOCKIO_H
25 #include <sys/sockio.h> /* defines SIOCATMARK */
30 #ifndef HAVE_MSG_NOSIGNAL
34 #include <mono/io-layer/wapi.h>
35 #include <mono/io-layer/wapi-private.h>
36 #include <mono/io-layer/socket-private.h>
37 #include <mono/io-layer/handles-private.h>
38 #include <mono/io-layer/socket-wrappers.h>
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
43 #include <arpa/inet.h>
44 #ifdef HAVE_SYS_SENDFILE_H
45 #include <sys/sendfile.h>
50 static guint32 startup_count
=0;
52 static void socket_close (gpointer handle
, gpointer data
);
54 struct _WapiHandleOps _wapi_socket_ops
= {
55 socket_close
, /* close */
59 NULL
, /* special_wait */
63 static mono_once_t socket_ops_once
=MONO_ONCE_INIT
;
65 static void socket_ops_init (void)
67 /* No capabilities to register */
70 static void socket_close (gpointer handle
, gpointer data
)
73 struct _WapiHandle_socket
*socket_handle
= (struct _WapiHandle_socket
*)data
;
76 g_message ("%s: closing socket handle %p", __func__
, handle
);
79 if (startup_count
== 0) {
80 WSASetLastError (WSANOTINITIALISED
);
84 /* Shutdown the socket for reading, to interrupt any potential
85 * receives that may be blocking for data. See bug 75705.
87 shutdown (GPOINTER_TO_UINT (handle
), SHUT_RD
);
90 ret
= close (GPOINTER_TO_UINT(handle
));
91 } while (ret
== -1 && errno
== EINTR
&&
92 !_wapi_thread_cur_apc_pending ());
97 g_message ("%s: close error: %s", __func__
, strerror (errno
));
99 errnum
= errno_to_WSA (errnum
, __func__
);
100 WSASetLastError (errnum
);
103 socket_handle
->saved_error
= 0;
106 int WSAStartup(guint32 requested
, WapiWSAData
*data
)
112 /* Insist on v2.0+ */
113 if (requested
< MAKEWORD(2,0)) {
114 return(WSAVERNOTSUPPORTED
);
119 /* I've no idea what is the minor version of the spec I read */
120 data
->wHighVersion
= MAKEWORD(2,2);
122 data
->wVersion
= requested
< data
->wHighVersion
? requested
:
126 g_message ("%s: high version 0x%x", __func__
, data
->wHighVersion
);
129 strncpy (data
->szDescription
, "WAPI", WSADESCRIPTION_LEN
);
130 strncpy (data
->szSystemStatus
, "groovy", WSASYS_STATUS_LEN
);
136 cleanup_close (gpointer handle
, gpointer data
)
138 _wapi_handle_ops_close (handle
, NULL
);
145 g_message ("%s: cleaning up", __func__
);
148 if (--startup_count
) {
153 _wapi_handle_foreach (WAPI_HANDLE_SOCKET
, cleanup_close
, NULL
);
157 void WSASetLastError(int error
)
159 SetLastError (error
);
162 int WSAGetLastError(void)
164 return(GetLastError ());
167 int closesocket(guint32 fd
)
169 gpointer handle
= GUINT_TO_POINTER (fd
);
171 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
172 WSASetLastError (WSAENOTSOCK
);
176 _wapi_handle_unref (handle
);
180 guint32
_wapi_accept(guint32 fd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
182 gpointer handle
= GUINT_TO_POINTER (fd
);
184 struct _WapiHandle_socket
*socket_handle
;
185 struct _WapiHandle_socket new_socket_handle
= {0};
189 if (startup_count
== 0) {
190 WSASetLastError (WSANOTINITIALISED
);
191 return(INVALID_SOCKET
);
194 if (addr
!= NULL
&& *addrlen
< sizeof(struct sockaddr
)) {
195 WSASetLastError (WSAEFAULT
);
196 return(INVALID_SOCKET
);
199 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
200 WSASetLastError (WSAENOTSOCK
);
201 return(INVALID_SOCKET
);
204 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
205 (gpointer
*)&socket_handle
);
207 g_warning ("%s: error looking up socket handle %p",
209 WSASetLastError (WSAENOTSOCK
);
210 return(INVALID_SOCKET
);
214 new_fd
= accept (fd
, addr
, addrlen
);
215 } while (new_fd
== -1 && errno
== EINTR
&&
216 !_wapi_thread_cur_apc_pending());
221 g_message ("%s: accept error: %s", __func__
, strerror(errno
));
224 errnum
= errno_to_WSA (errnum
, __func__
);
225 WSASetLastError (errnum
);
227 return(INVALID_SOCKET
);
230 if (new_fd
>= _wapi_fd_reserve
) {
232 g_message ("%s: File descriptor is too big", __func__
);
235 WSASetLastError (WSASYSCALLFAILURE
);
239 return(INVALID_SOCKET
);
242 new_socket_handle
.domain
= socket_handle
->domain
;
243 new_socket_handle
.type
= socket_handle
->type
;
244 new_socket_handle
.protocol
= socket_handle
->protocol
;
245 new_socket_handle
.still_readable
= 1;
247 new_handle
= _wapi_handle_new_fd (WAPI_HANDLE_SOCKET
, new_fd
,
249 if(new_handle
== _WAPI_HANDLE_INVALID
) {
250 g_warning ("%s: error creating socket handle", __func__
);
251 WSASetLastError (ERROR_GEN_FAILURE
);
252 return(INVALID_SOCKET
);
256 g_message ("%s: returning newly accepted socket handle %p with",
257 __func__
, new_handle
);
263 int _wapi_bind(guint32 fd
, struct sockaddr
*my_addr
, socklen_t addrlen
)
265 gpointer handle
= GUINT_TO_POINTER (fd
);
268 if (startup_count
== 0) {
269 WSASetLastError (WSANOTINITIALISED
);
270 return(SOCKET_ERROR
);
273 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
274 WSASetLastError (WSAENOTSOCK
);
275 return(SOCKET_ERROR
);
278 ret
= bind (fd
, my_addr
, addrlen
);
282 g_message ("%s: bind error: %s", __func__
, strerror(errno
));
284 errnum
= errno_to_WSA (errnum
, __func__
);
285 WSASetLastError (errnum
);
287 return(SOCKET_ERROR
);
292 int _wapi_connect(guint32 fd
, const struct sockaddr
*serv_addr
,
295 gpointer handle
= GUINT_TO_POINTER (fd
);
296 struct _WapiHandle_socket
*socket_handle
;
300 if (startup_count
== 0) {
301 WSASetLastError (WSANOTINITIALISED
);
302 return(SOCKET_ERROR
);
305 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
306 WSASetLastError (WSAENOTSOCK
);
307 return(SOCKET_ERROR
);
310 if (connect (fd
, serv_addr
, addrlen
) == -1) {
317 if (errno
!= EINTR
) {
319 g_message ("%s: connect error: %s", __func__
,
323 errnum
= errno_to_WSA (errnum
, __func__
);
324 if (errnum
== WSAEINPROGRESS
)
325 errnum
= WSAEWOULDBLOCK
; /* see bug #73053 */
327 WSASetLastError (errnum
);
330 * On solaris x86 getsockopt (SO_ERROR) is not set after
331 * connect () fails so we need to save this error.
333 * But don't do this for EWOULDBLOCK (bug 317315)
335 if (errnum
!= WSAEWOULDBLOCK
) {
336 ok
= _wapi_lookup_handle (handle
,
338 (gpointer
*)&socket_handle
);
340 /* ECONNRESET means the socket was closed by another thread */
341 if (errnum
!= WSAECONNRESET
)
342 g_warning ("%s: error looking up socket handle %p (error %d)", __func__
, handle
, errnum
);
344 socket_handle
->saved_error
= errnum
;
347 return(SOCKET_ERROR
);
351 fds
.events
= POLLOUT
;
352 while (poll (&fds
, 1, -1) == -1 &&
353 !_wapi_thread_cur_apc_pending ()) {
354 if (errno
!= EINTR
) {
355 errnum
= errno_to_WSA (errno
, __func__
);
358 g_message ("%s: connect poll error: %s",
359 __func__
, strerror (errno
));
362 WSASetLastError (errnum
);
363 return(SOCKET_ERROR
);
367 len
= sizeof(so_error
);
368 if (getsockopt (fd
, SOL_SOCKET
, SO_ERROR
, &so_error
,
370 errnum
= errno_to_WSA (errno
, __func__
);
373 g_message ("%s: connect getsockopt error: %s",
374 __func__
, strerror (errno
));
377 WSASetLastError (errnum
);
378 return(SOCKET_ERROR
);
382 errnum
= errno_to_WSA (so_error
, __func__
);
384 /* Need to save this socket error */
385 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
386 (gpointer
*)&socket_handle
);
388 g_warning ("%s: error looking up socket handle %p", __func__
, handle
);
390 socket_handle
->saved_error
= errnum
;
394 g_message ("%s: connect getsockopt returned error: %s",
395 __func__
, strerror (so_error
));
398 WSASetLastError (errnum
);
399 return(SOCKET_ERROR
);
406 int _wapi_getpeername(guint32 fd
, struct sockaddr
*name
, socklen_t
*namelen
)
408 gpointer handle
= GUINT_TO_POINTER (fd
);
411 if (startup_count
== 0) {
412 WSASetLastError (WSANOTINITIALISED
);
413 return(SOCKET_ERROR
);
416 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
417 WSASetLastError (WSAENOTSOCK
);
418 return(SOCKET_ERROR
);
421 ret
= getpeername (fd
, name
, namelen
);
425 g_message ("%s: getpeername error: %s", __func__
,
429 errnum
= errno_to_WSA (errnum
, __func__
);
430 WSASetLastError (errnum
);
432 return(SOCKET_ERROR
);
438 int _wapi_getsockname(guint32 fd
, struct sockaddr
*name
, socklen_t
*namelen
)
440 gpointer handle
= GUINT_TO_POINTER (fd
);
443 if (startup_count
== 0) {
444 WSASetLastError (WSANOTINITIALISED
);
445 return(SOCKET_ERROR
);
448 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
449 WSASetLastError (WSAENOTSOCK
);
450 return(SOCKET_ERROR
);
453 ret
= getsockname (fd
, name
, namelen
);
457 g_message ("%s: getsockname error: %s", __func__
,
461 errnum
= errno_to_WSA (errnum
, __func__
);
462 WSASetLastError (errnum
);
464 return(SOCKET_ERROR
);
470 int _wapi_getsockopt(guint32 fd
, int level
, int optname
, void *optval
,
473 gpointer handle
= GUINT_TO_POINTER (fd
);
477 struct _WapiHandle_socket
*socket_handle
;
480 if (startup_count
== 0) {
481 WSASetLastError (WSANOTINITIALISED
);
482 return(SOCKET_ERROR
);
485 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
486 WSASetLastError (WSAENOTSOCK
);
487 return(SOCKET_ERROR
);
491 if (level
== SOL_SOCKET
&&
492 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
494 *optlen
= sizeof (tv
);
497 ret
= getsockopt (fd
, level
, optname
, tmp_val
, optlen
);
501 g_message ("%s: getsockopt error: %s", __func__
,
505 errnum
= errno_to_WSA (errnum
, __func__
);
506 WSASetLastError (errnum
);
508 return(SOCKET_ERROR
);
511 if (level
== SOL_SOCKET
&&
512 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
513 *((int *) optval
) = tv
.tv_sec
* 1000 + (tv
.tv_usec
/ 1000); // milli from micro
514 *optlen
= sizeof (int);
517 if (optname
== SO_ERROR
) {
518 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
519 (gpointer
*)&socket_handle
);
521 g_warning ("%s: error looking up socket handle %p",
524 /* can't extract the last error */
525 *((int *) optval
) = errno_to_WSA (*((int *)optval
),
528 if (*((int *)optval
) != 0) {
529 *((int *) optval
) = errno_to_WSA (*((int *)optval
),
531 socket_handle
->saved_error
= *((int *)optval
);
533 *((int *)optval
) = socket_handle
->saved_error
;
541 int _wapi_listen(guint32 fd
, int backlog
)
543 gpointer handle
= GUINT_TO_POINTER (fd
);
546 if (startup_count
== 0) {
547 WSASetLastError (WSANOTINITIALISED
);
548 return(SOCKET_ERROR
);
551 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
552 WSASetLastError (WSAENOTSOCK
);
553 return(SOCKET_ERROR
);
556 ret
= listen (fd
, backlog
);
560 g_message ("%s: listen error: %s", __func__
, strerror (errno
));
563 errnum
= errno_to_WSA (errnum
, __func__
);
564 WSASetLastError (errnum
);
566 return(SOCKET_ERROR
);
572 int _wapi_recv(guint32 fd
, void *buf
, size_t len
, int recv_flags
)
574 return(_wapi_recvfrom (fd
, buf
, len
, recv_flags
, NULL
, 0));
577 int _wapi_recvfrom(guint32 fd
, void *buf
, size_t len
, int recv_flags
,
578 struct sockaddr
*from
, socklen_t
*fromlen
)
580 gpointer handle
= GUINT_TO_POINTER (fd
);
581 struct _WapiHandle_socket
*socket_handle
;
585 if (startup_count
== 0) {
586 WSASetLastError (WSANOTINITIALISED
);
587 return(SOCKET_ERROR
);
590 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
591 WSASetLastError (WSAENOTSOCK
);
592 return(SOCKET_ERROR
);
596 ret
= recvfrom (fd
, buf
, len
, recv_flags
, from
, fromlen
);
597 } while (ret
== -1 && errno
== EINTR
&&
598 !_wapi_thread_cur_apc_pending ());
600 if (ret
== 0 && len
> 0) {
601 /* According to the Linux man page, recvfrom only
602 * returns 0 when the socket has been shut down
603 * cleanly. Turn this into an EINTR to simulate win32
604 * behaviour of returning EINTR when a socket is
605 * closed while the recvfrom is blocking (we use a
606 * shutdown() in socket_close() to trigger this.) See
609 /* Distinguish between the socket being shut down at
610 * the local or remote ends, and reads that request 0
614 /* If this returns FALSE, it means the socket has been
615 * closed locally. If it returns TRUE, but
616 * still_readable != 1 then shutdown
617 * (SHUT_RD|SHUT_RDWR) has been called locally.
619 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
620 (gpointer
*)&socket_handle
);
621 if (ok
== FALSE
|| socket_handle
->still_readable
!= 1) {
630 g_message ("%s: recv error: %s", __func__
, strerror(errno
));
633 errnum
= errno_to_WSA (errnum
, __func__
);
634 WSASetLastError (errnum
);
636 return(SOCKET_ERROR
);
642 _wapi_recvmsg(guint32 fd
, struct msghdr
*msg
, int recv_flags
)
644 gpointer handle
= GUINT_TO_POINTER (fd
);
645 struct _WapiHandle_socket
*socket_handle
;
649 if (startup_count
== 0) {
650 WSASetLastError (WSANOTINITIALISED
);
651 return(SOCKET_ERROR
);
654 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
655 WSASetLastError (WSAENOTSOCK
);
656 return(SOCKET_ERROR
);
660 ret
= recvmsg (fd
, msg
, recv_flags
);
661 } while (ret
== -1 && errno
== EINTR
&&
662 !_wapi_thread_cur_apc_pending ());
665 /* see _wapi_recvfrom */
666 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
667 (gpointer
*)&socket_handle
);
668 if (ok
== FALSE
|| socket_handle
->still_readable
!= 1) {
677 g_message ("%s: recvmsg error: %s", __func__
, strerror(errno
));
680 errnum
= errno_to_WSA (errnum
, __func__
);
681 WSASetLastError (errnum
);
683 return(SOCKET_ERROR
);
688 int _wapi_send(guint32 fd
, const void *msg
, size_t len
, int send_flags
)
690 gpointer handle
= GUINT_TO_POINTER (fd
);
693 if (startup_count
== 0) {
694 WSASetLastError (WSANOTINITIALISED
);
695 return(SOCKET_ERROR
);
698 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
699 WSASetLastError (WSAENOTSOCK
);
700 return(SOCKET_ERROR
);
704 ret
= send (fd
, msg
, len
, send_flags
);
705 } while (ret
== -1 && errno
== EINTR
&&
706 !_wapi_thread_cur_apc_pending ());
711 g_message ("%s: send error: %s", __func__
, strerror (errno
));
714 errnum
= errno_to_WSA (errnum
, __func__
);
715 WSASetLastError (errnum
);
717 return(SOCKET_ERROR
);
722 int _wapi_sendto(guint32 fd
, const void *msg
, size_t len
, int send_flags
,
723 const struct sockaddr
*to
, socklen_t tolen
)
725 gpointer handle
= GUINT_TO_POINTER (fd
);
728 if (startup_count
== 0) {
729 WSASetLastError (WSANOTINITIALISED
);
730 return(SOCKET_ERROR
);
733 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
734 WSASetLastError (WSAENOTSOCK
);
735 return(SOCKET_ERROR
);
739 ret
= sendto (fd
, msg
, len
, send_flags
, to
, tolen
);
740 } while (ret
== -1 && errno
== EINTR
&&
741 !_wapi_thread_cur_apc_pending ());
746 g_message ("%s: send error: %s", __func__
, strerror (errno
));
749 errnum
= errno_to_WSA (errnum
, __func__
);
750 WSASetLastError (errnum
);
752 return(SOCKET_ERROR
);
758 _wapi_sendmsg(guint32 fd
, const struct msghdr
*msg
, int send_flags
)
760 gpointer handle
= GUINT_TO_POINTER (fd
);
763 if (startup_count
== 0) {
764 WSASetLastError (WSANOTINITIALISED
);
765 return(SOCKET_ERROR
);
768 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
769 WSASetLastError (WSAENOTSOCK
);
770 return(SOCKET_ERROR
);
774 ret
= sendmsg (fd
, msg
, send_flags
);
775 } while (ret
== -1 && errno
== EINTR
&&
776 !_wapi_thread_cur_apc_pending ());
781 g_message ("%s: sendmsg error: %s", __func__
, strerror (errno
));
784 errnum
= errno_to_WSA (errnum
, __func__
);
785 WSASetLastError (errnum
);
787 return(SOCKET_ERROR
);
792 int _wapi_setsockopt(guint32 fd
, int level
, int optname
,
793 const void *optval
, socklen_t optlen
)
795 gpointer handle
= GUINT_TO_POINTER (fd
);
800 if (startup_count
== 0) {
801 WSASetLastError (WSANOTINITIALISED
);
802 return(SOCKET_ERROR
);
805 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
806 WSASetLastError (WSAENOTSOCK
);
807 return(SOCKET_ERROR
);
811 if (level
== SOL_SOCKET
&&
812 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
813 int ms
= *((int *) optval
);
814 tv
.tv_sec
= ms
/ 1000;
815 tv
.tv_usec
= (ms
% 1000) * 1000; // micro from milli
817 optlen
= sizeof (tv
);
818 #if defined (__linux__)
819 } else if (level
== SOL_SOCKET
&&
820 (optname
== SO_SNDBUF
|| optname
== SO_RCVBUF
)) {
821 /* According to socket(7) the Linux kernel doubles the
822 * buffer sizes "to allow space for bookkeeping
825 int bufsize
= *((int *) optval
);
832 ret
= setsockopt (fd
, level
, optname
, tmp_val
, optlen
);
836 g_message ("%s: setsockopt error: %s", __func__
,
840 errnum
= errno_to_WSA (errnum
, __func__
);
841 WSASetLastError (errnum
);
843 return(SOCKET_ERROR
);
846 #if defined (SO_REUSEPORT)
847 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
848 if (level
== SOL_SOCKET
&& optname
== SO_REUSEADDR
) {
850 socklen_t type_len
= sizeof (type
);
852 if (!getsockopt (fd
, level
, SO_TYPE
, &type
, &type_len
)) {
853 if (type
== SOCK_DGRAM
)
854 setsockopt (fd
, level
, SO_REUSEPORT
, tmp_val
, optlen
);
862 int _wapi_shutdown(guint32 fd
, int how
)
864 struct _WapiHandle_socket
*socket_handle
;
866 gpointer handle
= GUINT_TO_POINTER (fd
);
869 if (startup_count
== 0) {
870 WSASetLastError (WSANOTINITIALISED
);
871 return(SOCKET_ERROR
);
874 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
875 WSASetLastError (WSAENOTSOCK
);
876 return(SOCKET_ERROR
);
879 if (how
== SHUT_RD
||
881 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
882 (gpointer
*)&socket_handle
);
884 g_warning ("%s: error looking up socket handle %p",
886 WSASetLastError (WSAENOTSOCK
);
887 return(SOCKET_ERROR
);
890 socket_handle
->still_readable
= 0;
893 ret
= shutdown (fd
, how
);
897 g_message ("%s: shutdown error: %s", __func__
,
901 errnum
= errno_to_WSA (errnum
, __func__
);
902 WSASetLastError (errnum
);
904 return(SOCKET_ERROR
);
910 guint32
_wapi_socket(int domain
, int type
, int protocol
, void *unused
,
911 guint32 unused2
, guint32 unused3
)
913 struct _WapiHandle_socket socket_handle
= {0};
917 socket_handle
.domain
= domain
;
918 socket_handle
.type
= type
;
919 socket_handle
.protocol
= protocol
;
920 socket_handle
.still_readable
= 1;
922 fd
= socket (domain
, type
, protocol
);
923 if (fd
== -1 && domain
== AF_INET
&& type
== SOCK_RAW
&&
925 /* Retry with protocol == 4 (see bug #54565) */
926 socket_handle
.protocol
= 4;
927 fd
= socket (AF_INET
, SOCK_RAW
, 4);
933 g_message ("%s: socket error: %s", __func__
, strerror (errno
));
935 errnum
= errno_to_WSA (errnum
, __func__
);
936 WSASetLastError (errnum
);
938 return(INVALID_SOCKET
);
941 if (fd
>= _wapi_fd_reserve
) {
943 g_message ("%s: File descriptor is too big (%d >= %d)",
944 __func__
, fd
, _wapi_fd_reserve
);
947 WSASetLastError (WSASYSCALLFAILURE
);
950 return(INVALID_SOCKET
);
953 /* .net seems to set this by default for SOCK_STREAM, not for
954 * SOCK_DGRAM (see bug #36322)
956 * It seems winsock has a rather different idea of what
957 * SO_REUSEADDR means. If it's set, then a new socket can be
958 * bound over an existing listening socket. There's a new
959 * windows-specific option called SO_EXCLUSIVEADDRUSE but
960 * using that means the socket MUST be closed properly, or a
961 * denial of service can occur. Luckily for us, winsock
962 * behaves as though any other system would when SO_REUSEADDR
963 * is true, so we don't need to do anything else here. See
969 ret
= setsockopt (fd
, SOL_SOCKET
, SO_REUSEADDR
, &true,
975 g_message ("%s: Error setting SO_REUSEADDR", __func__
);
978 errnum
= errno_to_WSA (errnum
, __func__
);
979 WSASetLastError (errnum
);
983 return(INVALID_SOCKET
);
988 mono_once (&socket_ops_once
, socket_ops_init
);
990 handle
= _wapi_handle_new_fd (WAPI_HANDLE_SOCKET
, fd
, &socket_handle
);
991 if (handle
== _WAPI_HANDLE_INVALID
) {
992 g_warning ("%s: error creating socket handle", __func__
);
993 WSASetLastError (WSASYSCALLFAILURE
);
995 return(INVALID_SOCKET
);
999 g_message ("%s: returning socket handle %p", __func__
, handle
);
1005 struct hostent
*_wapi_gethostbyname(const char *hostname
)
1009 if (startup_count
== 0) {
1010 WSASetLastError (WSANOTINITIALISED
);
1014 he
= gethostbyname (hostname
);
1017 g_message ("%s: gethostbyname error: %s", __func__
,
1018 strerror (h_errno
));
1022 case HOST_NOT_FOUND
:
1023 WSASetLastError (WSAHOST_NOT_FOUND
);
1025 #if NO_ADDRESS != NO_DATA
1029 WSASetLastError (WSANO_DATA
);
1032 WSASetLastError (WSANO_RECOVERY
);
1035 WSASetLastError (WSATRY_AGAIN
);
1038 g_warning ("%s: Need to translate %d into winsock error", __func__
, h_errno
);
1046 static gboolean
socket_disconnect (guint32 fd
)
1048 struct _WapiHandle_socket
*socket_handle
;
1050 gpointer handle
= GUINT_TO_POINTER (fd
);
1053 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
1054 (gpointer
*)&socket_handle
);
1056 g_warning ("%s: error looking up socket handle %p", __func__
,
1058 WSASetLastError (WSAENOTSOCK
);
1062 newsock
= socket (socket_handle
->domain
, socket_handle
->type
,
1063 socket_handle
->protocol
);
1064 if (newsock
== -1) {
1065 gint errnum
= errno
;
1068 g_message ("%s: socket error: %s", __func__
, strerror (errno
));
1071 errnum
= errno_to_WSA (errnum
, __func__
);
1072 WSASetLastError (errnum
);
1077 /* According to Stevens "Advanced Programming in the UNIX
1078 * Environment: UNIX File I/O" dup2() is atomic so there
1079 * should not be a race condition between the old fd being
1080 * closed and the new socket fd being copied over
1083 ret
= dup2 (newsock
, fd
);
1084 } while (ret
== -1 && errno
== EAGAIN
);
1087 gint errnum
= errno
;
1090 g_message ("%s: dup2 error: %s", __func__
, strerror (errno
));
1093 errnum
= errno_to_WSA (errnum
, __func__
);
1094 WSASetLastError (errnum
);
1104 static gboolean
wapi_disconnectex (guint32 fd
, WapiOverlapped
*overlapped
,
1105 guint32 flags
, guint32 reserved
)
1108 g_message ("%s: called on socket %d!", __func__
, fd
);
1111 if (reserved
!= 0) {
1112 WSASetLastError (WSAEINVAL
);
1116 /* We could check the socket type here and fail unless its
1117 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1118 * if we really wanted to
1121 return(socket_disconnect (fd
));
1124 #define SF_BUFFER_SIZE 16384
1126 wapi_sendfile (guint32 socket
, gpointer fd
, guint32 bytes_to_write
, guint32 bytes_per_send
, guint32 flags
)
1128 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
1129 gint file
= GPOINTER_TO_INT (fd
);
1133 struct stat statbuf
;
1135 n
= fstat (file
, &statbuf
);
1138 errnum
= errno_to_WSA (errnum
, __func__
);
1139 WSASetLastError (errnum
);
1140 return SOCKET_ERROR
;
1144 res
= sendfile (socket
, file
, NULL
, statbuf
.st_size
);
1145 #elif defined(DARWIN)
1146 /* TODO: header/tail could be sent in the 5th argument */
1147 /* TODO: Might not send the entire file for non-blocking sockets */
1148 res
= sendfile (file
, socket
, 0, &statbuf
.st_size
, NULL
, 0);
1150 } while (res
!= -1 && (errno
== EINTR
|| errno
== EAGAIN
) && !_wapi_thread_cur_apc_pending ());
1153 errnum
= errno_to_WSA (errnum
, __func__
);
1154 WSASetLastError (errnum
);
1155 return SOCKET_ERROR
;
1158 /* Default implementation */
1159 gint file
= GPOINTER_TO_INT (fd
);
1163 buffer
= g_malloc (SF_BUFFER_SIZE
);
1166 n
= read (file
, buffer
, SF_BUFFER_SIZE
);
1167 } while (n
== -1 && errno
== EINTR
&& !_wapi_thread_cur_apc_pending ());
1172 return 0; /* We're done reading */
1175 n
= send (socket
, buffer
, n
, 0); /* short sends? enclose this in a loop? */
1176 } while (n
== -1 && errno
== EINTR
&& !_wapi_thread_cur_apc_pending ());
1180 gint errnum
= errno
;
1181 errnum
= errno_to_WSA (errnum
, __func__
);
1182 WSASetLastError (errnum
);
1184 return SOCKET_ERROR
;
1192 TransmitFile (guint32 socket
, gpointer file
, guint32 bytes_to_write
, guint32 bytes_per_send
, WapiOverlapped
*ol
,
1193 WapiTransmitFileBuffers
*buffers
, guint32 flags
)
1195 gpointer sock
= GUINT_TO_POINTER (socket
);
1198 if (startup_count
== 0) {
1199 WSASetLastError (WSANOTINITIALISED
);
1203 if (_wapi_handle_type (sock
) != WAPI_HANDLE_SOCKET
) {
1204 WSASetLastError (WSAENOTSOCK
);
1208 /* Write the header */
1209 if (buffers
!= NULL
&& buffers
->Head
!= NULL
&& buffers
->HeadLength
> 0) {
1210 ret
= _wapi_send (socket
, buffers
->Head
, buffers
->HeadLength
, 0);
1211 if (ret
== SOCKET_ERROR
)
1215 ret
= wapi_sendfile (socket
, file
, bytes_to_write
, bytes_per_send
, flags
);
1216 if (ret
== SOCKET_ERROR
)
1219 /* Write the tail */
1220 if (buffers
!= NULL
&& buffers
->Tail
!= NULL
&& buffers
->TailLength
> 0) {
1221 ret
= _wapi_send (socket
, buffers
->Tail
, buffers
->TailLength
, 0);
1222 if (ret
== SOCKET_ERROR
)
1226 if ((flags
& TF_DISCONNECT
) == TF_DISCONNECT
)
1227 closesocket (socket
);
1236 } extension_functions
[] = {
1237 {WSAID_DISCONNECTEX
, wapi_disconnectex
},
1238 {WSAID_TRANSMITFILE
, TransmitFile
},
1243 WSAIoctl (guint32 fd
, gint32 command
,
1244 gchar
*input
, gint i_len
,
1245 gchar
*output
, gint o_len
, glong
*written
,
1246 void *unused1
, void *unused2
)
1248 gpointer handle
= GUINT_TO_POINTER (fd
);
1250 gchar
*buffer
= NULL
;
1252 if (startup_count
== 0) {
1253 WSASetLastError (WSANOTINITIALISED
);
1254 return(SOCKET_ERROR
);
1257 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1258 WSASetLastError (WSAENOTSOCK
);
1259 return SOCKET_ERROR
;
1262 if (command
== SIO_GET_EXTENSION_FUNCTION_POINTER
) {
1264 WapiGuid
*guid
= (WapiGuid
*)input
;
1266 if (i_len
< sizeof(WapiGuid
)) {
1267 /* As far as I can tell, windows doesn't
1268 * actually set an error here...
1270 WSASetLastError (WSAEINVAL
);
1271 return(SOCKET_ERROR
);
1274 if (o_len
< sizeof(gpointer
)) {
1276 WSASetLastError (WSAEINVAL
);
1277 return(SOCKET_ERROR
);
1280 if (output
== NULL
) {
1282 WSASetLastError (WSAEINVAL
);
1283 return(SOCKET_ERROR
);
1286 while(extension_functions
[i
].func
!= NULL
) {
1287 if (!memcmp (guid
, &extension_functions
[i
].guid
,
1288 sizeof(WapiGuid
))) {
1289 memcpy (output
, &extension_functions
[i
].func
,
1291 *written
= sizeof(gpointer
);
1298 WSASetLastError (WSAEINVAL
);
1299 return(SOCKET_ERROR
);
1303 buffer
= g_memdup (input
, i_len
);
1306 ret
= ioctl (fd
, command
, buffer
);
1308 gint errnum
= errno
;
1310 g_message("%s: WSAIoctl error: %s", __func__
,
1314 errnum
= errno_to_WSA (errnum
, __func__
);
1315 WSASetLastError (errnum
);
1318 return(SOCKET_ERROR
);
1321 if (buffer
== NULL
) {
1324 /* We just copy the buffer to the output. Some ioctls
1325 * don't even output any data, but, well...
1327 * NB windows returns WSAEFAULT if o_len is too small
1329 i_len
= (i_len
> o_len
) ? o_len
: i_len
;
1331 if (i_len
> 0 && output
!= NULL
) {
1332 memcpy (output
, buffer
, i_len
);
1342 #ifndef PLATFORM_PORT_PROVIDES_IOCTLSOCKET
1343 int ioctlsocket(guint32 fd
, gint32 command
, gpointer arg
)
1345 gpointer handle
= GUINT_TO_POINTER (fd
);
1348 if (startup_count
== 0) {
1349 WSASetLastError (WSANOTINITIALISED
);
1350 return(SOCKET_ERROR
);
1353 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1354 WSASetLastError (WSAENOTSOCK
);
1355 return(SOCKET_ERROR
);
1361 /* This works better than ioctl(...FIONBIO...)
1362 * on Linux (it causes connect to return
1363 * EINPROGRESS, but the ioctl doesn't seem to)
1365 ret
= fcntl(fd
, F_GETFL
, 0);
1367 if (*(gboolean
*)arg
) {
1372 ret
= fcntl(fd
, F_SETFL
, ret
);
1375 #endif /* O_NONBLOCK */
1376 /* Unused in Mono */
1378 ret
= ioctl (fd
, command
, arg
);
1383 #if defined (PLATFORM_MACOSX)
1385 // ioctl (fd, FIONREAD, XXX) returns the size of
1386 // the UDP header as well on
1389 // Use getsockopt SO_NREAD instead to get the
1390 // right values for TCP and UDP.
1392 // ai_canonname can be null in some cases on darwin, where the runtime assumes it will
1393 // be the value of the ip buffer.
1395 socklen_t optlen
= sizeof (int);
1396 ret
= getsockopt (fd
, SOL_SOCKET
, SO_NREAD
, arg
, &optlen
);
1398 ret
= ioctl (fd
, command
, arg
);
1403 WSASetLastError (WSAEINVAL
);
1404 return(SOCKET_ERROR
);
1408 gint errnum
= errno
;
1410 g_message ("%s: ioctl error: %s", __func__
, strerror (errno
));
1413 errnum
= errno_to_WSA (errnum
, __func__
);
1414 WSASetLastError (errnum
);
1416 return(SOCKET_ERROR
);
1422 int _wapi_select(int nfds G_GNUC_UNUSED
, fd_set
*readfds
, fd_set
*writefds
,
1423 fd_set
*exceptfds
, struct timeval
*timeout
)
1427 if (startup_count
== 0) {
1428 WSASetLastError (WSANOTINITIALISED
);
1429 return(SOCKET_ERROR
);
1432 for (maxfd
= FD_SETSIZE
-1; maxfd
>= 0; maxfd
--) {
1433 if ((readfds
&& FD_ISSET (maxfd
, readfds
)) ||
1434 (writefds
&& FD_ISSET (maxfd
, writefds
)) ||
1435 (exceptfds
&& FD_ISSET (maxfd
, exceptfds
))) {
1441 WSASetLastError (WSAEINVAL
);
1442 return(SOCKET_ERROR
);
1446 ret
= select(maxfd
+ 1, readfds
, writefds
, exceptfds
,
1448 } while (ret
== -1 && errno
== EINTR
&&
1449 !_wapi_thread_cur_apc_pending ());
1452 gint errnum
= errno
;
1454 g_message ("%s: select error: %s", __func__
, strerror (errno
));
1456 errnum
= errno_to_WSA (errnum
, __func__
);
1457 WSASetLastError (errnum
);
1459 return(SOCKET_ERROR
);
1465 void _wapi_FD_CLR(guint32 fd
, fd_set
*set
)
1467 gpointer handle
= GUINT_TO_POINTER (fd
);
1469 if (fd
>= FD_SETSIZE
) {
1470 WSASetLastError (WSAEINVAL
);
1474 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1475 WSASetLastError (WSAENOTSOCK
);
1482 int _wapi_FD_ISSET(guint32 fd
, fd_set
*set
)
1484 gpointer handle
= GUINT_TO_POINTER (fd
);
1486 if (fd
>= FD_SETSIZE
) {
1487 WSASetLastError (WSAEINVAL
);
1491 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1492 WSASetLastError (WSAENOTSOCK
);
1496 return(FD_ISSET (fd
, set
));
1499 void _wapi_FD_SET(guint32 fd
, fd_set
*set
)
1501 gpointer handle
= GUINT_TO_POINTER (fd
);
1503 if (fd
>= FD_SETSIZE
) {
1504 WSASetLastError (WSAEINVAL
);
1508 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1509 WSASetLastError (WSAENOTSOCK
);
1518 wsabuf_to_msghdr (WapiWSABuf
*buffers
, guint32 count
, struct msghdr
*hdr
)
1522 memset (hdr
, 0, sizeof (struct msghdr
));
1523 hdr
->msg_iovlen
= count
;
1524 hdr
->msg_iov
= g_new0 (struct iovec
, count
);
1525 for (i
= 0; i
< count
; i
++) {
1526 hdr
->msg_iov
[i
].iov_base
= buffers
[i
].buf
;
1527 hdr
->msg_iov
[i
].iov_len
= buffers
[i
].len
;
1532 msghdr_iov_free (struct msghdr
*hdr
)
1534 g_free (hdr
->msg_iov
);
1537 int WSARecv (guint32 fd
, WapiWSABuf
*buffers
, guint32 count
, guint32
*received
,
1538 guint32
*flags
, WapiOverlapped
*overlapped
,
1539 WapiOverlappedCB
*complete
)
1544 g_assert (overlapped
== NULL
);
1545 g_assert (complete
== NULL
);
1547 wsabuf_to_msghdr (buffers
, count
, &hdr
);
1548 ret
= _wapi_recvmsg (fd
, &hdr
, *flags
);
1549 msghdr_iov_free (&hdr
);
1551 if(ret
== SOCKET_ERROR
) {
1556 *flags
= hdr
.msg_flags
;
1561 int WSASend (guint32 fd
, WapiWSABuf
*buffers
, guint32 count
, guint32
*sent
,
1562 guint32 flags
, WapiOverlapped
*overlapped
,
1563 WapiOverlappedCB
*complete
)
1568 g_assert (overlapped
== NULL
);
1569 g_assert (complete
== NULL
);
1571 wsabuf_to_msghdr (buffers
, count
, &hdr
);
1572 ret
= _wapi_sendmsg (fd
, &hdr
, flags
);
1573 msghdr_iov_free (&hdr
);
1575 if(ret
== SOCKET_ERROR
)