2009-02-16 Zoltan Varga <vargaz@gmail.com>
[mono-debugger.git] / mono / io-layer / sockets.c
blob09afdd8300598f200fd8e5e32fb2e145308967de
1 /*
2 * sockets.c: Socket handles
4 * Author:
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
8 */
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <sys/poll.h>
19 #ifdef HAVE_SYS_FILIO_H
20 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
21 #endif
22 #ifdef HAVE_SYS_SOCKIO_H
23 #include <sys/sockio.h> /* defines SIOCATMARK */
24 #endif
25 #include <unistd.h>
26 #include <fcntl.h>
28 #ifndef HAVE_MSG_NOSIGNAL
29 #include <signal.h>
30 #endif
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>
40 #include <netdb.h>
41 #include <arpa/inet.h>
43 #undef DEBUG
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 */
51 NULL, /* signal */
52 NULL, /* own */
53 NULL, /* is_owned */
54 NULL, /* special_wait */
55 NULL /* prewait */
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)
67 int ret;
68 struct _WapiHandle_socket *socket_handle = (struct _WapiHandle_socket *)data;
70 #ifdef DEBUG
71 g_message ("%s: closing socket handle %p", __func__, handle);
72 #endif
74 if (startup_count == 0) {
75 WSASetLastError (WSANOTINITIALISED);
76 return;
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);
84 do {
85 ret = close (GPOINTER_TO_UINT(handle));
86 } while (ret == -1 && errno == EINTR &&
87 !_wapi_thread_cur_apc_pending ());
89 if (ret == -1) {
90 gint errnum = errno;
91 #ifdef DEBUG
92 g_message ("%s: close error: %s", __func__, strerror (errno));
93 #endif
94 errnum = errno_to_WSA (errnum, __func__);
95 WSASetLastError (errnum);
98 socket_handle->saved_error = 0;
101 int WSAStartup(guint32 requested, WapiWSAData *data)
103 if (data == NULL) {
104 return(WSAEFAULT);
107 /* Insist on v2.0+ */
108 if (requested < MAKEWORD(2,0)) {
109 return(WSAVERNOTSUPPORTED);
112 startup_count++;
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:
118 data->wHighVersion;
120 #ifdef DEBUG
121 g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
122 #endif
124 strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
125 strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
127 return(0);
130 static gboolean
131 cleanup_close (gpointer handle, gpointer data)
133 _wapi_handle_ops_close (handle, NULL);
134 return TRUE;
137 int WSACleanup(void)
139 #ifdef DEBUG
140 g_message ("%s: cleaning up", __func__);
141 #endif
143 if (--startup_count) {
144 /* Do nothing */
145 return(0);
148 _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
149 return(0);
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);
168 return(0);
171 _wapi_handle_unref (handle);
172 return(0);
175 guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
177 gpointer handle = GUINT_TO_POINTER (fd);
178 gpointer new_handle;
179 struct _WapiHandle_socket *socket_handle;
180 struct _WapiHandle_socket new_socket_handle = {0};
181 gboolean ok;
182 int new_fd;
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);
201 if (ok == FALSE) {
202 g_warning ("%s: error looking up socket handle %p",
203 __func__, handle);
204 WSASetLastError (WSAENOTSOCK);
205 return(INVALID_SOCKET);
208 do {
209 new_fd = accept (fd, addr, addrlen);
210 } while (new_fd == -1 && errno == EINTR &&
211 !_wapi_thread_cur_apc_pending());
213 if (new_fd == -1) {
214 gint errnum = errno;
215 #ifdef DEBUG
216 g_message ("%s: accept error: %s", __func__, strerror(errno));
217 #endif
219 errnum = errno_to_WSA (errnum, __func__);
220 WSASetLastError (errnum);
222 return(INVALID_SOCKET);
225 if (new_fd >= _wapi_fd_reserve) {
226 #ifdef DEBUG
227 g_message ("%s: File descriptor is too big", __func__);
228 #endif
230 WSASetLastError (WSASYSCALLFAILURE);
232 close (new_fd);
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,
243 &new_socket_handle);
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);
250 #ifdef DEBUG
251 g_message ("%s: returning newly accepted socket handle %p with",
252 __func__, new_handle);
253 #endif
255 return(new_fd);
258 int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
260 gpointer handle = GUINT_TO_POINTER (fd);
261 int ret;
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);
274 if (ret == -1) {
275 gint errnum = errno;
276 #ifdef DEBUG
277 g_message ("%s: bind error: %s", __func__, strerror(errno));
278 #endif
279 errnum = errno_to_WSA (errnum, __func__);
280 WSASetLastError (errnum);
282 return(SOCKET_ERROR);
284 return(ret);
287 int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
288 socklen_t addrlen)
290 gpointer handle = GUINT_TO_POINTER (fd);
291 struct _WapiHandle_socket *socket_handle;
292 gboolean ok;
293 gint errnum;
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) {
306 struct pollfd fds;
307 int so_error;
308 socklen_t len;
310 errnum = errno;
312 if (errno != EINTR) {
313 #ifdef DEBUG
314 g_message ("%s: connect error: %s", __func__,
315 strerror (errnum));
316 #endif
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,
332 WAPI_HANDLE_SOCKET,
333 (gpointer *)&socket_handle);
334 if (ok == FALSE) {
335 g_warning ("%s: error looking up socket handle %p", __func__, handle);
336 } else {
337 socket_handle->saved_error = errnum;
340 return(SOCKET_ERROR);
343 fds.fd = fd;
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__);
350 #ifdef DEBUG
351 g_message ("%s: connect poll error: %s",
352 __func__, strerror (errno));
353 #endif
355 WSASetLastError (errnum);
356 return(SOCKET_ERROR);
360 len = sizeof(so_error);
361 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
362 &len) == -1) {
363 errnum = errno_to_WSA (errno, __func__);
365 #ifdef DEBUG
366 g_message ("%s: connect getsockopt error: %s",
367 __func__, strerror (errno));
368 #endif
370 WSASetLastError (errnum);
371 return(SOCKET_ERROR);
374 if (so_error != 0) {
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);
380 if (ok == FALSE) {
381 g_warning ("%s: error looking up socket handle %p", __func__, handle);
382 } else {
383 socket_handle->saved_error = errnum;
386 #ifdef DEBUG
387 g_message ("%s: connect getsockopt returned error: %s",
388 __func__, strerror (so_error));
389 #endif
391 WSASetLastError (errnum);
392 return(SOCKET_ERROR);
396 return(0);
399 int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
401 gpointer handle = GUINT_TO_POINTER (fd);
402 int ret;
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);
415 if (ret == -1) {
416 gint errnum = errno;
417 #ifdef DEBUG
418 g_message ("%s: getpeername error: %s", __func__,
419 strerror (errno));
420 #endif
422 errnum = errno_to_WSA (errnum, __func__);
423 WSASetLastError (errnum);
425 return(SOCKET_ERROR);
428 return(ret);
431 int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
433 gpointer handle = GUINT_TO_POINTER (fd);
434 int ret;
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);
447 if (ret == -1) {
448 gint errnum = errno;
449 #ifdef DEBUG
450 g_message ("%s: getsockname error: %s", __func__,
451 strerror (errno));
452 #endif
454 errnum = errno_to_WSA (errnum, __func__);
455 WSASetLastError (errnum);
457 return(SOCKET_ERROR);
460 return(ret);
463 int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
464 socklen_t *optlen)
466 gpointer handle = GUINT_TO_POINTER (fd);
467 int ret;
468 struct timeval tv;
469 void *tmp_val;
470 struct _WapiHandle_socket *socket_handle;
471 gboolean ok;
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);
483 tmp_val = optval;
484 if (level == SOL_SOCKET &&
485 (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
486 tmp_val = &tv;
487 *optlen = sizeof (tv);
490 ret = getsockopt (fd, level, optname, tmp_val, optlen);
491 if (ret == -1) {
492 gint errnum = errno;
493 #ifdef DEBUG
494 g_message ("%s: getsockopt error: %s", __func__,
495 strerror (errno));
496 #endif
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);
513 if (ok == FALSE) {
514 g_warning ("%s: error looking up socket handle %p",
515 __func__, handle);
517 /* can't extract the last error */
518 *((int *) optval) = errno_to_WSA (*((int *)optval),
519 __func__);
520 } else {
521 if (*((int *)optval) != 0) {
522 *((int *) optval) = errno_to_WSA (*((int *)optval),
523 __func__);
524 socket_handle->saved_error = *((int *)optval);
525 } else {
526 *((int *)optval) = socket_handle->saved_error;
531 return(ret);
534 int _wapi_listen(guint32 fd, int backlog)
536 gpointer handle = GUINT_TO_POINTER (fd);
537 int ret;
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);
550 if (ret == -1) {
551 gint errnum = errno;
552 #ifdef DEBUG
553 g_message ("%s: listen error: %s", __func__, strerror (errno));
554 #endif
556 errnum = errno_to_WSA (errnum, __func__);
557 WSASetLastError (errnum);
559 return(SOCKET_ERROR);
562 return(0);
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;
575 gboolean ok;
576 int ret;
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);
588 do {
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
600 * bug 75705.
602 /* Distinguish between the socket being shut down at
603 * the local or remote ends, and reads that request 0
604 * bytes to be read
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) {
615 ret = -1;
616 errno = EINTR;
620 if (ret == -1) {
621 gint errnum = errno;
622 #ifdef DEBUG
623 g_message ("%s: recv error: %s", __func__, strerror(errno));
624 #endif
626 errnum = errno_to_WSA (errnum, __func__);
627 WSASetLastError (errnum);
629 return(SOCKET_ERROR);
631 return(ret);
634 int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
636 gpointer handle = GUINT_TO_POINTER (fd);
637 int ret;
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);
649 do {
650 ret = send (fd, msg, len, send_flags);
651 } while (ret == -1 && errno == EINTR &&
652 !_wapi_thread_cur_apc_pending ());
654 if (ret == -1) {
655 gint errnum = errno;
656 #ifdef DEBUG
657 g_message ("%s: send error: %s", __func__, strerror (errno));
658 #endif
660 errnum = errno_to_WSA (errnum, __func__);
661 WSASetLastError (errnum);
663 return(SOCKET_ERROR);
665 return(ret);
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);
672 int ret;
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);
684 do {
685 ret = sendto (fd, msg, len, send_flags, to, tolen);
686 } while (ret == -1 && errno == EINTR &&
687 !_wapi_thread_cur_apc_pending ());
689 if (ret == -1) {
690 gint errnum = errno;
691 #ifdef DEBUG
692 g_message ("%s: send error: %s", __func__, strerror (errno));
693 #endif
695 errnum = errno_to_WSA (errnum, __func__);
696 WSASetLastError (errnum);
698 return(SOCKET_ERROR);
700 return(ret);
703 int _wapi_setsockopt(guint32 fd, int level, int optname,
704 const void *optval, socklen_t optlen)
706 gpointer handle = GUINT_TO_POINTER (fd);
707 int ret;
708 const void *tmp_val;
709 struct timeval tv;
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);
721 tmp_val = optval;
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
727 tmp_val = &tv;
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
734 * overhead."
736 int bufsize = *((int *) optval);
738 bufsize /= 2;
739 tmp_val = &bufsize;
740 #endif
743 ret = setsockopt (fd, level, optname, tmp_val, optlen);
744 if (ret == -1) {
745 gint errnum = errno;
746 #ifdef DEBUG
747 g_message ("%s: setsockopt error: %s", __func__,
748 strerror (errno));
749 #endif
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) {
760 int type;
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);
768 #endif
770 return(ret);
773 int _wapi_shutdown(guint32 fd, int how)
775 struct _WapiHandle_socket *socket_handle;
776 gboolean ok;
777 gpointer handle = GUINT_TO_POINTER (fd);
778 int ret;
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 ||
791 how == SHUT_RDWR) {
792 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
793 (gpointer *)&socket_handle);
794 if (ok == FALSE) {
795 g_warning ("%s: error looking up socket handle %p",
796 __func__, handle);
797 WSASetLastError (WSAENOTSOCK);
798 return(SOCKET_ERROR);
801 socket_handle->still_readable = 0;
804 ret = shutdown (fd, how);
805 if (ret == -1) {
806 gint errnum = errno;
807 #ifdef DEBUG
808 g_message ("%s: shutdown error: %s", __func__,
809 strerror (errno));
810 #endif
812 errnum = errno_to_WSA (errnum, __func__);
813 WSASetLastError (errnum);
815 return(SOCKET_ERROR);
818 return(ret);
821 guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
822 guint32 unused2, guint32 unused3)
824 struct _WapiHandle_socket socket_handle = {0};
825 gpointer handle;
826 int fd;
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 &&
835 protocol == 0) {
836 /* Retry with protocol == 4 (see bug #54565) */
837 socket_handle.protocol = 4;
838 fd = socket (AF_INET, SOCK_RAW, 4);
841 if (fd == -1) {
842 gint errnum = errno;
843 #ifdef DEBUG
844 g_message ("%s: socket error: %s", __func__, strerror (errno));
845 #endif
846 errnum = errno_to_WSA (errnum, __func__);
847 WSASetLastError (errnum);
849 return(INVALID_SOCKET);
852 if (fd >= _wapi_fd_reserve) {
853 #ifdef DEBUG
854 g_message ("%s: File descriptor is too big (%d >= %d)",
855 __func__, fd, _wapi_fd_reserve);
856 #endif
858 WSASetLastError (WSASYSCALLFAILURE);
859 close (fd);
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
875 * bug 53992.
878 int ret, true = 1;
880 ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true,
881 sizeof (true));
882 if (ret == -1) {
883 int errnum = errno;
885 #ifdef DEBUG
886 g_message ("%s: Error setting SO_REUSEADDR", __func__);
887 #endif
889 errnum = errno_to_WSA (errnum, __func__);
890 WSASetLastError (errnum);
892 close (fd);
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);
905 close (fd);
906 return(INVALID_SOCKET);
909 #ifdef DEBUG
910 g_message ("%s: returning socket handle %p", __func__, handle);
911 #endif
913 return(fd);
916 struct hostent *_wapi_gethostbyname(const char *hostname)
918 struct hostent *he;
920 if (startup_count == 0) {
921 WSASetLastError (WSANOTINITIALISED);
922 return(NULL);
925 he = gethostbyname (hostname);
926 if (he == NULL) {
927 #ifdef DEBUG
928 g_message ("%s: gethostbyname error: %s", __func__,
929 strerror (h_errno));
930 #endif
932 switch(h_errno) {
933 case HOST_NOT_FOUND:
934 WSASetLastError (WSAHOST_NOT_FOUND);
935 break;
936 #if NO_ADDRESS != NO_DATA
937 case NO_ADDRESS:
938 #endif
939 case NO_DATA:
940 WSASetLastError (WSANO_DATA);
941 break;
942 case NO_RECOVERY:
943 WSASetLastError (WSANO_RECOVERY);
944 break;
945 case TRY_AGAIN:
946 WSASetLastError (WSATRY_AGAIN);
947 break;
948 default:
949 g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
950 break;
954 return(he);
957 static gboolean socket_disconnect (guint32 fd)
959 struct _WapiHandle_socket *socket_handle;
960 gboolean ok;
961 gpointer handle = GUINT_TO_POINTER (fd);
962 int newsock, ret;
964 ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET,
965 (gpointer *)&socket_handle);
966 if (ok == FALSE) {
967 g_warning ("%s: error looking up socket handle %p", __func__,
968 handle);
969 WSASetLastError (WSAENOTSOCK);
970 return(FALSE);
973 newsock = socket (socket_handle->domain, socket_handle->type,
974 socket_handle->protocol);
975 if (newsock == -1) {
976 gint errnum = errno;
978 #ifdef DEBUG
979 g_message ("%s: socket error: %s", __func__, strerror (errno));
980 #endif
982 errnum = errno_to_WSA (errnum, __func__);
983 WSASetLastError (errnum);
985 return(FALSE);
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
993 do {
994 ret = dup2 (newsock, fd);
995 } while (ret == -1 && errno == EAGAIN);
997 if (ret == -1) {
998 gint errnum = errno;
1000 #ifdef DEBUG
1001 g_message ("%s: dup2 error: %s", __func__, strerror (errno));
1002 #endif
1004 errnum = errno_to_WSA (errnum, __func__);
1005 WSASetLastError (errnum);
1007 return(FALSE);
1010 close (newsock);
1012 return(TRUE);
1015 static gboolean wapi_disconnectex (guint32 fd, WapiOverlapped *overlapped,
1016 guint32 flags, guint32 reserved)
1018 #ifdef DEBUG
1019 g_message ("%s: called on socket %d!", __func__, fd);
1020 #endif
1022 if (reserved != 0) {
1023 WSASetLastError (WSAEINVAL);
1024 return(FALSE);
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)
1046 #ifdef DEBUG
1047 g_message ("%s: called on socket %d!", __func__, fd);
1048 #endif
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));
1060 static struct
1062 WapiGuid guid;
1063 gpointer func;
1064 } extension_functions[] = {
1065 {WSAID_DISCONNECTEX, wapi_disconnectex},
1066 {WSAID_TRANSMITFILE, wapi_transmitfile},
1067 {{0}, NULL},
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);
1077 int ret;
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) {
1091 int i = 0;
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)) {
1103 /* Or here... */
1104 WSASetLastError (WSAEINVAL);
1105 return(SOCKET_ERROR);
1108 if (output == NULL) {
1109 /* Or here */
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,
1118 sizeof(gpointer));
1119 *written = sizeof(gpointer);
1120 return(0);
1123 i++;
1126 WSASetLastError (WSAEINVAL);
1127 return(SOCKET_ERROR);
1130 if (i_len > 0) {
1131 buffer = g_memdup (input, i_len);
1134 ret = ioctl (fd, command, buffer);
1135 if (ret == -1) {
1136 gint errnum = errno;
1137 #ifdef DEBUG
1138 g_message("%s: WSAIoctl error: %s", __func__,
1139 strerror (errno));
1140 #endif
1142 errnum = errno_to_WSA (errnum, __func__);
1143 WSASetLastError (errnum);
1144 g_free (buffer);
1146 return(SOCKET_ERROR);
1149 if (buffer == NULL) {
1150 *written = 0;
1151 } else {
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);
1163 g_free (buffer);
1164 *written = i_len;
1167 return(0);
1170 int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
1172 gpointer handle = GUINT_TO_POINTER (fd);
1173 int ret;
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);
1185 switch(command){
1186 case FIONBIO:
1187 #ifdef O_NONBLOCK
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);
1193 if (ret != -1) {
1194 if (*(gboolean *)arg) {
1195 ret |= O_NONBLOCK;
1196 } else {
1197 ret &= ~O_NONBLOCK;
1199 ret = fcntl(fd, F_SETFL, ret);
1201 break;
1202 #endif /* O_NONBLOCK */
1203 case FIONREAD:
1204 case SIOCATMARK:
1205 ret = ioctl (fd, command, arg);
1206 break;
1207 default:
1208 WSASetLastError (WSAEINVAL);
1209 return(SOCKET_ERROR);
1212 if (ret == -1) {
1213 gint errnum = errno;
1214 #ifdef DEBUG
1215 g_message ("%s: ioctl error: %s", __func__, strerror (errno));
1216 #endif
1218 errnum = errno_to_WSA (errnum, __func__);
1219 WSASetLastError (errnum);
1221 return(SOCKET_ERROR);
1224 return(0);
1227 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
1228 fd_set *exceptfds, struct timeval *timeout)
1230 int ret, maxfd;
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))) {
1241 break;
1245 if (maxfd == -1) {
1246 WSASetLastError (WSAEINVAL);
1247 return(SOCKET_ERROR);
1250 do {
1251 ret = select(maxfd + 1, readfds, writefds, exceptfds,
1252 timeout);
1253 } while (ret == -1 && errno == EINTR &&
1254 !_wapi_thread_cur_apc_pending ());
1256 if (ret == -1) {
1257 gint errnum = errno;
1258 #ifdef DEBUG
1259 g_message ("%s: select error: %s", __func__, strerror (errno));
1260 #endif
1261 errnum = errno_to_WSA (errnum, __func__);
1262 WSASetLastError (errnum);
1264 return(SOCKET_ERROR);
1267 return(ret);
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);
1276 return;
1279 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1280 WSASetLastError (WSAENOTSOCK);
1281 return;
1284 FD_CLR (fd, set);
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);
1293 return(0);
1296 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1297 WSASetLastError (WSAENOTSOCK);
1298 return(0);
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);
1310 return;
1313 if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
1314 WSASetLastError (WSAENOTSOCK);
1315 return;
1318 FD_SET (fd, set);
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;
1326 gint8 *recvbuf;
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) {
1338 g_free (recvbuf);
1339 return(ret);
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) {
1347 break;
1349 offset += copylen;
1352 *received = ret;
1353 return(0);
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;
1361 gint8 *sendbuf;
1363 g_assert (overlapped == NULL);
1364 g_assert (complete == NULL);
1366 if (count == 1)
1367 ret = _wapi_sendto (fd, buffers [0].buf, buffers [0].len, flags, NULL, 0);
1368 else {
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);
1377 offset += copylen;
1380 ret = _wapi_sendto (fd, sendbuf, buflen, flags, NULL, 0);
1381 g_free (sendbuf);
1385 if(ret == SOCKET_ERROR)
1386 return ret;
1388 *sent = ret;
1389 return 0;