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 #include <sys/ioctl.h>
19 #ifdef HAVE_SYS_FILIO_H
20 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
22 #ifdef HAVE_SYS_SOCKIO_H
23 #include <sys/sockio.h> /* defines SIOCATMARK */
28 #ifndef HAVE_MSG_NOSIGNAL
32 #include <mono/io-layer/wapi.h>
33 #include <mono/io-layer/wapi-private.h>
34 #include <mono/io-layer/socket-private.h>
35 #include <mono/io-layer/handles-private.h>
36 #include <mono/io-layer/socket-wrappers.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
41 #include <arpa/inet.h>
45 static guint32 startup_count
=0;
47 static void socket_close (gpointer handle
, gpointer data
);
49 struct _WapiHandleOps _wapi_socket_ops
= {
50 socket_close
, /* close */
54 NULL
, /* special_wait */
58 static mono_once_t socket_ops_once
=MONO_ONCE_INIT
;
60 static void socket_ops_init (void)
62 /* No capabilities to register */
65 static void socket_close (gpointer handle
, gpointer data
)
68 struct _WapiHandle_socket
*socket_handle
= (struct _WapiHandle_socket
*)data
;
71 g_message ("%s: closing socket handle %p", __func__
, handle
);
74 if (startup_count
== 0) {
75 WSASetLastError (WSANOTINITIALISED
);
79 /* Shutdown the socket for reading, to interrupt any potential
80 * receives that may be blocking for data. See bug 75705.
82 shutdown (GPOINTER_TO_UINT (handle
), SHUT_RD
);
85 ret
= close (GPOINTER_TO_UINT(handle
));
86 } while (ret
== -1 && errno
== EINTR
&&
87 !_wapi_thread_cur_apc_pending ());
92 g_message ("%s: close error: %s", __func__
, strerror (errno
));
94 errnum
= errno_to_WSA (errnum
, __func__
);
95 WSASetLastError (errnum
);
98 socket_handle
->saved_error
= 0;
101 int WSAStartup(guint32 requested
, WapiWSAData
*data
)
107 /* Insist on v2.0+ */
108 if (requested
< MAKEWORD(2,0)) {
109 return(WSAVERNOTSUPPORTED
);
114 /* I've no idea what is the minor version of the spec I read */
115 data
->wHighVersion
= MAKEWORD(2,2);
117 data
->wVersion
= requested
< data
->wHighVersion
? requested
:
121 g_message ("%s: high version 0x%x", __func__
, data
->wHighVersion
);
124 strncpy (data
->szDescription
, "WAPI", WSADESCRIPTION_LEN
);
125 strncpy (data
->szSystemStatus
, "groovy", WSASYS_STATUS_LEN
);
131 cleanup_close (gpointer handle
, gpointer data
)
133 _wapi_handle_ops_close (handle
, NULL
);
140 g_message ("%s: cleaning up", __func__
);
143 if (--startup_count
) {
148 _wapi_handle_foreach (WAPI_HANDLE_SOCKET
, cleanup_close
, NULL
);
152 void WSASetLastError(int error
)
154 SetLastError (error
);
157 int WSAGetLastError(void)
159 return(GetLastError ());
162 int closesocket(guint32 fd
)
164 gpointer handle
= GUINT_TO_POINTER (fd
);
166 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
167 WSASetLastError (WSAENOTSOCK
);
171 _wapi_handle_unref (handle
);
175 guint32
_wapi_accept(guint32 fd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
177 gpointer handle
= GUINT_TO_POINTER (fd
);
179 struct _WapiHandle_socket
*socket_handle
;
180 struct _WapiHandle_socket new_socket_handle
= {0};
184 if (startup_count
== 0) {
185 WSASetLastError (WSANOTINITIALISED
);
186 return(INVALID_SOCKET
);
189 if (addr
!= NULL
&& *addrlen
< sizeof(struct sockaddr
)) {
190 WSASetLastError (WSAEFAULT
);
191 return(INVALID_SOCKET
);
194 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
195 WSASetLastError (WSAENOTSOCK
);
196 return(INVALID_SOCKET
);
199 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
200 (gpointer
*)&socket_handle
);
202 g_warning ("%s: error looking up socket handle %p",
204 WSASetLastError (WSAENOTSOCK
);
205 return(INVALID_SOCKET
);
209 new_fd
= accept (fd
, addr
, addrlen
);
210 } while (new_fd
== -1 && errno
== EINTR
&&
211 !_wapi_thread_cur_apc_pending());
216 g_message ("%s: accept error: %s", __func__
, strerror(errno
));
219 errnum
= errno_to_WSA (errnum
, __func__
);
220 WSASetLastError (errnum
);
222 return(INVALID_SOCKET
);
225 if (new_fd
>= _wapi_fd_reserve
) {
227 g_message ("%s: File descriptor is too big", __func__
);
230 WSASetLastError (WSASYSCALLFAILURE
);
234 return(INVALID_SOCKET
);
237 new_socket_handle
.domain
= socket_handle
->domain
;
238 new_socket_handle
.type
= socket_handle
->type
;
239 new_socket_handle
.protocol
= socket_handle
->protocol
;
240 new_socket_handle
.still_readable
= 1;
242 new_handle
= _wapi_handle_new_fd (WAPI_HANDLE_SOCKET
, new_fd
,
244 if(new_handle
== _WAPI_HANDLE_INVALID
) {
245 g_warning ("%s: error creating socket handle", __func__
);
246 WSASetLastError (ERROR_GEN_FAILURE
);
247 return(INVALID_SOCKET
);
251 g_message ("%s: returning newly accepted socket handle %p with",
252 __func__
, new_handle
);
258 int _wapi_bind(guint32 fd
, struct sockaddr
*my_addr
, socklen_t addrlen
)
260 gpointer handle
= GUINT_TO_POINTER (fd
);
263 if (startup_count
== 0) {
264 WSASetLastError (WSANOTINITIALISED
);
265 return(SOCKET_ERROR
);
268 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
269 WSASetLastError (WSAENOTSOCK
);
270 return(SOCKET_ERROR
);
273 ret
= bind (fd
, my_addr
, addrlen
);
277 g_message ("%s: bind error: %s", __func__
, strerror(errno
));
279 errnum
= errno_to_WSA (errnum
, __func__
);
280 WSASetLastError (errnum
);
282 return(SOCKET_ERROR
);
287 int _wapi_connect(guint32 fd
, const struct sockaddr
*serv_addr
,
290 gpointer handle
= GUINT_TO_POINTER (fd
);
291 struct _WapiHandle_socket
*socket_handle
;
295 if (startup_count
== 0) {
296 WSASetLastError (WSANOTINITIALISED
);
297 return(SOCKET_ERROR
);
300 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
301 WSASetLastError (WSAENOTSOCK
);
302 return(SOCKET_ERROR
);
305 if (connect (fd
, serv_addr
, addrlen
) == -1) {
312 if (errno
!= EINTR
) {
314 g_message ("%s: connect error: %s", __func__
,
318 errnum
= errno_to_WSA (errnum
, __func__
);
319 if (errnum
== WSAEINPROGRESS
)
320 errnum
= WSAEWOULDBLOCK
; /* see bug #73053 */
322 WSASetLastError (errnum
);
325 * On solaris x86 getsockopt (SO_ERROR) is not set after
326 * connect () fails so we need to save this error.
328 * But don't do this for EWOULDBLOCK (bug 317315)
330 if (errnum
!= WSAEWOULDBLOCK
) {
331 ok
= _wapi_lookup_handle (handle
,
333 (gpointer
*)&socket_handle
);
335 g_warning ("%s: error looking up socket handle %p", __func__
, handle
);
337 socket_handle
->saved_error
= errnum
;
340 return(SOCKET_ERROR
);
344 fds
.events
= POLLOUT
;
345 while (poll (&fds
, 1, -1) == -1 &&
346 !_wapi_thread_cur_apc_pending ()) {
347 if (errno
!= EINTR
) {
348 errnum
= errno_to_WSA (errno
, __func__
);
351 g_message ("%s: connect poll error: %s",
352 __func__
, strerror (errno
));
355 WSASetLastError (errnum
);
356 return(SOCKET_ERROR
);
360 len
= sizeof(so_error
);
361 if (getsockopt (fd
, SOL_SOCKET
, SO_ERROR
, &so_error
,
363 errnum
= errno_to_WSA (errno
, __func__
);
366 g_message ("%s: connect getsockopt error: %s",
367 __func__
, strerror (errno
));
370 WSASetLastError (errnum
);
371 return(SOCKET_ERROR
);
375 errnum
= errno_to_WSA (so_error
, __func__
);
377 /* Need to save this socket error */
378 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
379 (gpointer
*)&socket_handle
);
381 g_warning ("%s: error looking up socket handle %p", __func__
, handle
);
383 socket_handle
->saved_error
= errnum
;
387 g_message ("%s: connect getsockopt returned error: %s",
388 __func__
, strerror (so_error
));
391 WSASetLastError (errnum
);
392 return(SOCKET_ERROR
);
399 int _wapi_getpeername(guint32 fd
, struct sockaddr
*name
, socklen_t
*namelen
)
401 gpointer handle
= GUINT_TO_POINTER (fd
);
404 if (startup_count
== 0) {
405 WSASetLastError (WSANOTINITIALISED
);
406 return(SOCKET_ERROR
);
409 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
410 WSASetLastError (WSAENOTSOCK
);
411 return(SOCKET_ERROR
);
414 ret
= getpeername (fd
, name
, namelen
);
418 g_message ("%s: getpeername error: %s", __func__
,
422 errnum
= errno_to_WSA (errnum
, __func__
);
423 WSASetLastError (errnum
);
425 return(SOCKET_ERROR
);
431 int _wapi_getsockname(guint32 fd
, struct sockaddr
*name
, socklen_t
*namelen
)
433 gpointer handle
= GUINT_TO_POINTER (fd
);
436 if (startup_count
== 0) {
437 WSASetLastError (WSANOTINITIALISED
);
438 return(SOCKET_ERROR
);
441 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
442 WSASetLastError (WSAENOTSOCK
);
443 return(SOCKET_ERROR
);
446 ret
= getsockname (fd
, name
, namelen
);
450 g_message ("%s: getsockname error: %s", __func__
,
454 errnum
= errno_to_WSA (errnum
, __func__
);
455 WSASetLastError (errnum
);
457 return(SOCKET_ERROR
);
463 int _wapi_getsockopt(guint32 fd
, int level
, int optname
, void *optval
,
466 gpointer handle
= GUINT_TO_POINTER (fd
);
470 struct _WapiHandle_socket
*socket_handle
;
473 if (startup_count
== 0) {
474 WSASetLastError (WSANOTINITIALISED
);
475 return(SOCKET_ERROR
);
478 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
479 WSASetLastError (WSAENOTSOCK
);
480 return(SOCKET_ERROR
);
484 if (level
== SOL_SOCKET
&&
485 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
487 *optlen
= sizeof (tv
);
490 ret
= getsockopt (fd
, level
, optname
, tmp_val
, optlen
);
494 g_message ("%s: getsockopt error: %s", __func__
,
498 errnum
= errno_to_WSA (errnum
, __func__
);
499 WSASetLastError (errnum
);
501 return(SOCKET_ERROR
);
504 if (level
== SOL_SOCKET
&&
505 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
506 *((int *) optval
) = tv
.tv_sec
* 1000 + (tv
.tv_usec
/ 1000); // milli from micro
507 *optlen
= sizeof (int);
510 if (optname
== SO_ERROR
) {
511 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
512 (gpointer
*)&socket_handle
);
514 g_warning ("%s: error looking up socket handle %p",
517 /* can't extract the last error */
518 *((int *) optval
) = errno_to_WSA (*((int *)optval
),
521 if (*((int *)optval
) != 0) {
522 *((int *) optval
) = errno_to_WSA (*((int *)optval
),
524 socket_handle
->saved_error
= *((int *)optval
);
526 *((int *)optval
) = socket_handle
->saved_error
;
534 int _wapi_listen(guint32 fd
, int backlog
)
536 gpointer handle
= GUINT_TO_POINTER (fd
);
539 if (startup_count
== 0) {
540 WSASetLastError (WSANOTINITIALISED
);
541 return(SOCKET_ERROR
);
544 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
545 WSASetLastError (WSAENOTSOCK
);
546 return(SOCKET_ERROR
);
549 ret
= listen (fd
, backlog
);
553 g_message ("%s: listen error: %s", __func__
, strerror (errno
));
556 errnum
= errno_to_WSA (errnum
, __func__
);
557 WSASetLastError (errnum
);
559 return(SOCKET_ERROR
);
565 int _wapi_recv(guint32 fd
, void *buf
, size_t len
, int recv_flags
)
567 return(_wapi_recvfrom (fd
, buf
, len
, recv_flags
, NULL
, 0));
570 int _wapi_recvfrom(guint32 fd
, void *buf
, size_t len
, int recv_flags
,
571 struct sockaddr
*from
, socklen_t
*fromlen
)
573 gpointer handle
= GUINT_TO_POINTER (fd
);
574 struct _WapiHandle_socket
*socket_handle
;
578 if (startup_count
== 0) {
579 WSASetLastError (WSANOTINITIALISED
);
580 return(SOCKET_ERROR
);
583 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
584 WSASetLastError (WSAENOTSOCK
);
585 return(SOCKET_ERROR
);
589 ret
= recvfrom (fd
, buf
, len
, recv_flags
, from
, fromlen
);
590 } while (ret
== -1 && errno
== EINTR
&&
591 !_wapi_thread_cur_apc_pending ());
593 if (ret
== 0 && len
> 0) {
594 /* According to the Linux man page, recvfrom only
595 * returns 0 when the socket has been shut down
596 * cleanly. Turn this into an EINTR to simulate win32
597 * behaviour of returning EINTR when a socket is
598 * closed while the recvfrom is blocking (we use a
599 * shutdown() in socket_close() to trigger this.) See
602 /* Distinguish between the socket being shut down at
603 * the local or remote ends, and reads that request 0
607 /* If this returns FALSE, it means the socket has been
608 * closed locally. If it returns TRUE, but
609 * still_readable != 1 then shutdown
610 * (SHUT_RD|SHUT_RDWR) has been called locally.
612 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
613 (gpointer
*)&socket_handle
);
614 if (ok
== FALSE
|| socket_handle
->still_readable
!= 1) {
623 g_message ("%s: recv error: %s", __func__
, strerror(errno
));
626 errnum
= errno_to_WSA (errnum
, __func__
);
627 WSASetLastError (errnum
);
629 return(SOCKET_ERROR
);
634 int _wapi_send(guint32 fd
, const void *msg
, size_t len
, int send_flags
)
636 gpointer handle
= GUINT_TO_POINTER (fd
);
639 if (startup_count
== 0) {
640 WSASetLastError (WSANOTINITIALISED
);
641 return(SOCKET_ERROR
);
644 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
645 WSASetLastError (WSAENOTSOCK
);
646 return(SOCKET_ERROR
);
650 ret
= send (fd
, msg
, len
, send_flags
);
651 } while (ret
== -1 && errno
== EINTR
&&
652 !_wapi_thread_cur_apc_pending ());
657 g_message ("%s: send error: %s", __func__
, strerror (errno
));
660 errnum
= errno_to_WSA (errnum
, __func__
);
661 WSASetLastError (errnum
);
663 return(SOCKET_ERROR
);
668 int _wapi_sendto(guint32 fd
, const void *msg
, size_t len
, int send_flags
,
669 const struct sockaddr
*to
, socklen_t tolen
)
671 gpointer handle
= GUINT_TO_POINTER (fd
);
674 if (startup_count
== 0) {
675 WSASetLastError (WSANOTINITIALISED
);
676 return(SOCKET_ERROR
);
679 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
680 WSASetLastError (WSAENOTSOCK
);
681 return(SOCKET_ERROR
);
685 ret
= sendto (fd
, msg
, len
, send_flags
, to
, tolen
);
686 } while (ret
== -1 && errno
== EINTR
&&
687 !_wapi_thread_cur_apc_pending ());
692 g_message ("%s: send error: %s", __func__
, strerror (errno
));
695 errnum
= errno_to_WSA (errnum
, __func__
);
696 WSASetLastError (errnum
);
698 return(SOCKET_ERROR
);
703 int _wapi_setsockopt(guint32 fd
, int level
, int optname
,
704 const void *optval
, socklen_t optlen
)
706 gpointer handle
= GUINT_TO_POINTER (fd
);
711 if (startup_count
== 0) {
712 WSASetLastError (WSANOTINITIALISED
);
713 return(SOCKET_ERROR
);
716 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
717 WSASetLastError (WSAENOTSOCK
);
718 return(SOCKET_ERROR
);
722 if (level
== SOL_SOCKET
&&
723 (optname
== SO_RCVTIMEO
|| optname
== SO_SNDTIMEO
)) {
724 int ms
= *((int *) optval
);
725 tv
.tv_sec
= ms
/ 1000;
726 tv
.tv_usec
= (ms
% 1000) * 1000; // micro from milli
728 optlen
= sizeof (tv
);
729 #if defined (__linux__)
730 } else if (level
== SOL_SOCKET
&&
731 (optname
== SO_SNDBUF
|| optname
== SO_RCVBUF
)) {
732 /* According to socket(7) the Linux kernel doubles the
733 * buffer sizes "to allow space for bookkeeping
736 int bufsize
= *((int *) optval
);
743 ret
= setsockopt (fd
, level
, optname
, tmp_val
, optlen
);
747 g_message ("%s: setsockopt error: %s", __func__
,
751 errnum
= errno_to_WSA (errnum
, __func__
);
752 WSASetLastError (errnum
);
754 return(SOCKET_ERROR
);
757 #if defined (SO_REUSEPORT)
758 /* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. */
759 if (level
== SOL_SOCKET
&& optname
== SO_REUSEADDR
) {
761 int type_len
= sizeof (type
);
763 if (!getsockopt (fd
, level
, SO_TYPE
, &type
, &type_len
)) {
764 if (type
== SOCK_DGRAM
)
765 setsockopt (fd
, level
, SO_REUSEPORT
, tmp_val
, optlen
);
773 int _wapi_shutdown(guint32 fd
, int how
)
775 struct _WapiHandle_socket
*socket_handle
;
777 gpointer handle
= GUINT_TO_POINTER (fd
);
780 if (startup_count
== 0) {
781 WSASetLastError (WSANOTINITIALISED
);
782 return(SOCKET_ERROR
);
785 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
786 WSASetLastError (WSAENOTSOCK
);
787 return(SOCKET_ERROR
);
790 if (how
== SHUT_RD
||
792 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
793 (gpointer
*)&socket_handle
);
795 g_warning ("%s: error looking up socket handle %p",
797 WSASetLastError (WSAENOTSOCK
);
798 return(SOCKET_ERROR
);
801 socket_handle
->still_readable
= 0;
804 ret
= shutdown (fd
, how
);
808 g_message ("%s: shutdown error: %s", __func__
,
812 errnum
= errno_to_WSA (errnum
, __func__
);
813 WSASetLastError (errnum
);
815 return(SOCKET_ERROR
);
821 guint32
_wapi_socket(int domain
, int type
, int protocol
, void *unused
,
822 guint32 unused2
, guint32 unused3
)
824 struct _WapiHandle_socket socket_handle
= {0};
828 socket_handle
.domain
= domain
;
829 socket_handle
.type
= type
;
830 socket_handle
.protocol
= protocol
;
831 socket_handle
.still_readable
= 1;
833 fd
= socket (domain
, type
, protocol
);
834 if (fd
== -1 && domain
== AF_INET
&& type
== SOCK_RAW
&&
836 /* Retry with protocol == 4 (see bug #54565) */
837 socket_handle
.protocol
= 4;
838 fd
= socket (AF_INET
, SOCK_RAW
, 4);
844 g_message ("%s: socket error: %s", __func__
, strerror (errno
));
846 errnum
= errno_to_WSA (errnum
, __func__
);
847 WSASetLastError (errnum
);
849 return(INVALID_SOCKET
);
852 if (fd
>= _wapi_fd_reserve
) {
854 g_message ("%s: File descriptor is too big (%d >= %d)",
855 __func__
, fd
, _wapi_fd_reserve
);
858 WSASetLastError (WSASYSCALLFAILURE
);
861 return(INVALID_SOCKET
);
864 /* .net seems to set this by default for SOCK_STREAM, not for
865 * SOCK_DGRAM (see bug #36322)
867 * It seems winsock has a rather different idea of what
868 * SO_REUSEADDR means. If it's set, then a new socket can be
869 * bound over an existing listening socket. There's a new
870 * windows-specific option called SO_EXCLUSIVEADDRUSE but
871 * using that means the socket MUST be closed properly, or a
872 * denial of service can occur. Luckily for us, winsock
873 * behaves as though any other system would when SO_REUSEADDR
874 * is true, so we don't need to do anything else here. See
880 ret
= setsockopt (fd
, SOL_SOCKET
, SO_REUSEADDR
, &true,
886 g_message ("%s: Error setting SO_REUSEADDR", __func__
);
889 errnum
= errno_to_WSA (errnum
, __func__
);
890 WSASetLastError (errnum
);
894 return(INVALID_SOCKET
);
899 mono_once (&socket_ops_once
, socket_ops_init
);
901 handle
= _wapi_handle_new_fd (WAPI_HANDLE_SOCKET
, fd
, &socket_handle
);
902 if (handle
== _WAPI_HANDLE_INVALID
) {
903 g_warning ("%s: error creating socket handle", __func__
);
904 WSASetLastError (WSASYSCALLFAILURE
);
906 return(INVALID_SOCKET
);
910 g_message ("%s: returning socket handle %p", __func__
, handle
);
916 struct hostent
*_wapi_gethostbyname(const char *hostname
)
920 if (startup_count
== 0) {
921 WSASetLastError (WSANOTINITIALISED
);
925 he
= gethostbyname (hostname
);
928 g_message ("%s: gethostbyname error: %s", __func__
,
934 WSASetLastError (WSAHOST_NOT_FOUND
);
936 #if NO_ADDRESS != NO_DATA
940 WSASetLastError (WSANO_DATA
);
943 WSASetLastError (WSANO_RECOVERY
);
946 WSASetLastError (WSATRY_AGAIN
);
949 g_warning ("%s: Need to translate %d into winsock error", __func__
, h_errno
);
957 static gboolean
socket_disconnect (guint32 fd
)
959 struct _WapiHandle_socket
*socket_handle
;
961 gpointer handle
= GUINT_TO_POINTER (fd
);
964 ok
= _wapi_lookup_handle (handle
, WAPI_HANDLE_SOCKET
,
965 (gpointer
*)&socket_handle
);
967 g_warning ("%s: error looking up socket handle %p", __func__
,
969 WSASetLastError (WSAENOTSOCK
);
973 newsock
= socket (socket_handle
->domain
, socket_handle
->type
,
974 socket_handle
->protocol
);
979 g_message ("%s: socket error: %s", __func__
, strerror (errno
));
982 errnum
= errno_to_WSA (errnum
, __func__
);
983 WSASetLastError (errnum
);
988 /* According to Stevens "Advanced Programming in the UNIX
989 * Environment: UNIX File I/O" dup2() is atomic so there
990 * should not be a race condition between the old fd being
991 * closed and the new socket fd being copied over
994 ret
= dup2 (newsock
, fd
);
995 } while (ret
== -1 && errno
== EAGAIN
);
1001 g_message ("%s: dup2 error: %s", __func__
, strerror (errno
));
1004 errnum
= errno_to_WSA (errnum
, __func__
);
1005 WSASetLastError (errnum
);
1015 static gboolean
wapi_disconnectex (guint32 fd
, WapiOverlapped
*overlapped
,
1016 guint32 flags
, guint32 reserved
)
1019 g_message ("%s: called on socket %d!", __func__
, fd
);
1022 if (reserved
!= 0) {
1023 WSASetLastError (WSAEINVAL
);
1027 /* We could check the socket type here and fail unless its
1028 * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
1029 * if we really wanted to
1032 return(socket_disconnect (fd
));
1035 /* NB only supports NULL file handle, NULL buffers and
1036 * TF_DISCONNECT|TF_REUSE_SOCKET flags to disconnect the socket fd.
1037 * Shouldn't actually ever need to be called anyway though, because we
1038 * have DisconnectEx ().
1040 static gboolean
wapi_transmitfile (guint32 fd
, gpointer file
,
1041 guint32 num_write
, guint32 num_per_send
,
1042 WapiOverlapped
*overlapped
,
1043 WapiTransmitFileBuffers
*buffers
,
1044 WapiTransmitFileFlags flags
)
1047 g_message ("%s: called on socket %d!", __func__
, fd
);
1050 g_assert (file
== NULL
);
1051 g_assert (overlapped
== NULL
);
1052 g_assert (buffers
== NULL
);
1053 g_assert (num_write
== 0);
1054 g_assert (num_per_send
== 0);
1055 g_assert (flags
== (TF_DISCONNECT
| TF_REUSE_SOCKET
));
1057 return(socket_disconnect (fd
));
1064 } extension_functions
[] = {
1065 {WSAID_DISCONNECTEX
, wapi_disconnectex
},
1066 {WSAID_TRANSMITFILE
, wapi_transmitfile
},
1071 WSAIoctl (guint32 fd
, gint32 command
,
1072 gchar
*input
, gint i_len
,
1073 gchar
*output
, gint o_len
, glong
*written
,
1074 void *unused1
, void *unused2
)
1076 gpointer handle
= GUINT_TO_POINTER (fd
);
1078 gchar
*buffer
= NULL
;
1080 if (startup_count
== 0) {
1081 WSASetLastError (WSANOTINITIALISED
);
1082 return(SOCKET_ERROR
);
1085 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1086 WSASetLastError (WSAENOTSOCK
);
1087 return SOCKET_ERROR
;
1090 if (command
== SIO_GET_EXTENSION_FUNCTION_POINTER
) {
1092 WapiGuid
*guid
= (WapiGuid
*)input
;
1094 if (i_len
< sizeof(WapiGuid
)) {
1095 /* As far as I can tell, windows doesn't
1096 * actually set an error here...
1098 WSASetLastError (WSAEINVAL
);
1099 return(SOCKET_ERROR
);
1102 if (o_len
< sizeof(gpointer
)) {
1104 WSASetLastError (WSAEINVAL
);
1105 return(SOCKET_ERROR
);
1108 if (output
== NULL
) {
1110 WSASetLastError (WSAEINVAL
);
1111 return(SOCKET_ERROR
);
1114 while(extension_functions
[i
].func
!= NULL
) {
1115 if (!memcmp (guid
, &extension_functions
[i
].guid
,
1116 sizeof(WapiGuid
))) {
1117 memcpy (output
, &extension_functions
[i
].func
,
1119 *written
= sizeof(gpointer
);
1126 WSASetLastError (WSAEINVAL
);
1127 return(SOCKET_ERROR
);
1131 buffer
= g_memdup (input
, i_len
);
1134 ret
= ioctl (fd
, command
, buffer
);
1136 gint errnum
= errno
;
1138 g_message("%s: WSAIoctl error: %s", __func__
,
1142 errnum
= errno_to_WSA (errnum
, __func__
);
1143 WSASetLastError (errnum
);
1146 return(SOCKET_ERROR
);
1149 if (buffer
== NULL
) {
1152 /* We just copy the buffer to the output. Some ioctls
1153 * don't even output any data, but, well...
1155 * NB windows returns WSAEFAULT if o_len is too small
1157 i_len
= (i_len
> o_len
) ? o_len
: i_len
;
1159 if (i_len
> 0 && output
!= NULL
) {
1160 memcpy (output
, buffer
, i_len
);
1170 int ioctlsocket(guint32 fd
, gint32 command
, gpointer arg
)
1172 gpointer handle
= GUINT_TO_POINTER (fd
);
1175 if (startup_count
== 0) {
1176 WSASetLastError (WSANOTINITIALISED
);
1177 return(SOCKET_ERROR
);
1180 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1181 WSASetLastError (WSAENOTSOCK
);
1182 return(SOCKET_ERROR
);
1188 /* This works better than ioctl(...FIONBIO...)
1189 * on Linux (it causes connect to return
1190 * EINPROGRESS, but the ioctl doesn't seem to)
1192 ret
= fcntl(fd
, F_GETFL
, 0);
1194 if (*(gboolean
*)arg
) {
1199 ret
= fcntl(fd
, F_SETFL
, ret
);
1202 #endif /* O_NONBLOCK */
1205 ret
= ioctl (fd
, command
, arg
);
1208 WSASetLastError (WSAEINVAL
);
1209 return(SOCKET_ERROR
);
1213 gint errnum
= errno
;
1215 g_message ("%s: ioctl error: %s", __func__
, strerror (errno
));
1218 errnum
= errno_to_WSA (errnum
, __func__
);
1219 WSASetLastError (errnum
);
1221 return(SOCKET_ERROR
);
1227 int _wapi_select(int nfds G_GNUC_UNUSED
, fd_set
*readfds
, fd_set
*writefds
,
1228 fd_set
*exceptfds
, struct timeval
*timeout
)
1232 if (startup_count
== 0) {
1233 WSASetLastError (WSANOTINITIALISED
);
1234 return(SOCKET_ERROR
);
1237 for (maxfd
= FD_SETSIZE
-1; maxfd
>= 0; maxfd
--) {
1238 if ((readfds
&& FD_ISSET (maxfd
, readfds
)) ||
1239 (writefds
&& FD_ISSET (maxfd
, writefds
)) ||
1240 (exceptfds
&& FD_ISSET (maxfd
, exceptfds
))) {
1246 WSASetLastError (WSAEINVAL
);
1247 return(SOCKET_ERROR
);
1251 ret
= select(maxfd
+ 1, readfds
, writefds
, exceptfds
,
1253 } while (ret
== -1 && errno
== EINTR
&&
1254 !_wapi_thread_cur_apc_pending ());
1257 gint errnum
= errno
;
1259 g_message ("%s: select error: %s", __func__
, strerror (errno
));
1261 errnum
= errno_to_WSA (errnum
, __func__
);
1262 WSASetLastError (errnum
);
1264 return(SOCKET_ERROR
);
1270 void _wapi_FD_CLR(guint32 fd
, fd_set
*set
)
1272 gpointer handle
= GUINT_TO_POINTER (fd
);
1274 if (fd
>= FD_SETSIZE
) {
1275 WSASetLastError (WSAEINVAL
);
1279 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1280 WSASetLastError (WSAENOTSOCK
);
1287 int _wapi_FD_ISSET(guint32 fd
, fd_set
*set
)
1289 gpointer handle
= GUINT_TO_POINTER (fd
);
1291 if (fd
>= FD_SETSIZE
) {
1292 WSASetLastError (WSAEINVAL
);
1296 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1297 WSASetLastError (WSAENOTSOCK
);
1301 return(FD_ISSET (fd
, set
));
1304 void _wapi_FD_SET(guint32 fd
, fd_set
*set
)
1306 gpointer handle
= GUINT_TO_POINTER (fd
);
1308 if (fd
>= FD_SETSIZE
) {
1309 WSASetLastError (WSAEINVAL
);
1313 if (_wapi_handle_type (handle
) != WAPI_HANDLE_SOCKET
) {
1314 WSASetLastError (WSAENOTSOCK
);
1321 int WSARecv (guint32 fd
, WapiWSABuf
*buffers
, guint32 count
, guint32
*received
,
1322 guint32
*flags
, WapiOverlapped
*overlapped
,
1323 WapiOverlappedCB
*complete
)
1325 int ret
, i
, buflen
= 0, offset
= 0, copylen
;
1328 g_assert (overlapped
== NULL
);
1329 g_assert (complete
== NULL
);
1331 for(i
= 0; i
< count
; i
++) {
1332 buflen
+= buffers
[i
].len
;
1335 recvbuf
= g_new0 (gint8
, buflen
);
1336 ret
= _wapi_recvfrom (fd
, recvbuf
, buflen
, *flags
, NULL
, 0);
1337 if(ret
== SOCKET_ERROR
) {
1342 for(i
= 0; i
< count
; i
++) {
1343 copylen
= buffers
[i
].len
> (buflen
- offset
)? (buflen
- offset
):buffers
[i
].len
;
1344 memcpy (buffers
[i
].buf
, recvbuf
+ offset
, copylen
);
1346 if (copylen
!= buffers
[i
].len
) {
1356 int WSASend (guint32 fd
, WapiWSABuf
*buffers
, guint32 count
, guint32
*sent
,
1357 guint32 flags
, WapiOverlapped
*overlapped
,
1358 WapiOverlappedCB
*complete
)
1360 int ret
, i
, buflen
= 0, offset
= 0, copylen
;
1363 g_assert (overlapped
== NULL
);
1364 g_assert (complete
== NULL
);
1367 ret
= _wapi_sendto (fd
, buffers
[0].buf
, buffers
[0].len
, flags
, NULL
, 0);
1369 for(i
= 0; i
< count
; i
++) {
1370 buflen
+= buffers
[i
].len
;
1373 sendbuf
= g_new0 (gint8
, buflen
);
1374 for(i
= 0; i
< count
; i
++) {
1375 copylen
= buffers
[i
].len
;
1376 memcpy (sendbuf
+ offset
, buffers
[i
].buf
, copylen
);
1380 ret
= _wapi_sendto (fd
, sendbuf
, buflen
, flags
, NULL
, 0);
1385 if(ret
== SOCKET_ERROR
)