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>
18 #ifdef HAVE_SYS_FILIO_H
19 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
21 #ifdef HAVE_SYS_SOCKIO_H
22 #include <sys/sockio.h> /* defines SIOCATMARK */
27 #ifndef HAVE_MSG_NOSIGNAL
31 #include <mono/io-layer/wapi.h>
32 #include <mono/io-layer/wapi-private.h>
33 #include <mono/io-layer/socket-private.h>
34 #include <mono/io-layer/handles-private.h>
38 static guint32 startup_count=0;
39 static GPtrArray *sockets=NULL;
40 static pthread_key_t error_key;
41 static mono_once_t error_key_once=MONO_ONCE_INIT;
43 static void socket_close_private (gpointer handle);
45 struct _WapiHandleOps _wapi_socket_ops = {
46 NULL, /* close_shared */
47 socket_close_private, /* close_private */
53 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
55 static void socket_ops_init (void)
57 /* No capabilities to register */
60 static void socket_close_private (gpointer handle)
63 g_message(G_GNUC_PRETTY_FUNCTION ": closing socket handle %p",
67 closesocket(GPOINTER_TO_UINT (handle));
70 int WSAStartup(guint32 requested, WapiWSAData *data)
77 if(requested < MAKEWORD(2,0)) {
78 return(WSAVERNOTSUPPORTED);
81 if(startup_count==0) {
82 sockets=g_ptr_array_new();
87 /* I've no idea what is the minor version of the spec I read */
88 data->wHighVersion=MAKEWORD(2,0);
90 data->wVersion=requested < data->wHighVersion? requested:
94 g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
98 strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
99 strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
109 g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
112 if(--startup_count) {
117 /* Close down all sockets */
118 for(i=0; i<sockets->len; i++) {
121 handle=g_ptr_array_index(sockets, i);
122 _wapi_handle_ops_close_private (handle);
125 g_ptr_array_free(sockets, FALSE);
131 static void error_init(void)
133 pthread_key_create(&error_key, NULL);
136 void WSASetLastError(int error)
138 mono_once(&error_key_once, error_init);
139 pthread_setspecific(error_key, GINT_TO_POINTER(error));
142 int WSAGetLastError(void)
147 mono_once(&error_key_once, error_init);
148 errptr=pthread_getspecific(error_key);
149 err=GPOINTER_TO_INT(errptr);
154 int closesocket(guint32 handle)
156 struct _WapiHandlePrivate_socket *socket_private_handle;
161 g_message (G_GNUC_PRETTY_FUNCTION ": closing socket handle 0x%x",
165 if(startup_count==0) {
166 WSASetLastError(WSANOTINITIALISED);
167 return(SOCKET_ERROR);
170 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
171 NULL, (gpointer *)&socket_private_handle);
173 g_warning (G_GNUC_PRETTY_FUNCTION
174 ": error looking up socket handle 0x%x", handle);
175 WSASetLastError(WSAENOTSOCK);
176 return(SOCKET_ERROR);
179 g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle));
181 ret=close(socket_private_handle->fd);
185 g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
188 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
189 WSASetLastError (errnum);
196 guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
199 struct _WapiHandlePrivate_socket *socket_private_handle;
200 struct _WapiHandlePrivate_socket *new_socket_private_handle;
205 if(startup_count==0) {
206 WSASetLastError(WSANOTINITIALISED);
207 return(INVALID_SOCKET);
210 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
211 NULL, (gpointer *)&socket_private_handle);
213 g_warning (G_GNUC_PRETTY_FUNCTION
214 ": error looking up socket handle 0x%x", handle);
215 WSASetLastError(WSAENOTSOCK);
216 return(INVALID_SOCKET);
219 fd=accept(socket_private_handle->fd, addr, addrlen);
223 g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
227 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
228 WSASetLastError (errnum);
230 return(INVALID_SOCKET);
233 new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
234 if(new_handle==_WAPI_HANDLE_INVALID) {
235 g_warning (G_GNUC_PRETTY_FUNCTION
236 ": error creating socket handle");
237 return(INVALID_SOCKET);
240 _wapi_handle_lock_handle (new_handle);
242 ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
243 (gpointer *)&new_socket_private_handle);
245 g_warning (G_GNUC_PRETTY_FUNCTION
246 ": error looking up socket handle 0x%x", handle);
247 _wapi_handle_unlock_handle (new_handle);
248 return(INVALID_SOCKET);
251 new_socket_private_handle->fd=fd;
254 g_message(G_GNUC_PRETTY_FUNCTION
255 ": returning newly accepted socket handle %p with fd %d",
256 new_handle, new_socket_private_handle->fd);
259 _wapi_handle_unlock_handle (new_handle);
261 return(GPOINTER_TO_UINT (new_handle));
264 int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
266 struct _WapiHandlePrivate_socket *socket_private_handle;
270 if(startup_count==0) {
271 WSASetLastError(WSANOTINITIALISED);
272 return(SOCKET_ERROR);
275 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
276 NULL, (gpointer *)&socket_private_handle);
278 g_warning (G_GNUC_PRETTY_FUNCTION
279 ": error looking up socket handle 0x%x", handle);
280 WSASetLastError(WSAENOTSOCK);
281 return(SOCKET_ERROR);
284 ret=bind(socket_private_handle->fd, my_addr, addrlen);
288 g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
291 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
292 WSASetLastError (errnum);
294 return(SOCKET_ERROR);
299 int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr,
302 struct _WapiHandlePrivate_socket *socket_private_handle;
306 if(startup_count==0) {
307 WSASetLastError(WSANOTINITIALISED);
308 return(SOCKET_ERROR);
311 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
312 NULL, (gpointer *)&socket_private_handle);
314 g_warning (G_GNUC_PRETTY_FUNCTION
315 ": error looking up socket handle 0x%x", handle);
316 WSASetLastError(WSAENOTSOCK);
317 return(SOCKET_ERROR);
320 ret=connect(socket_private_handle->fd, serv_addr, addrlen);
324 g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
327 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
328 WSASetLastError (errnum);
330 return(SOCKET_ERROR);
335 int _wapi_getpeername(guint32 handle, struct sockaddr *name,
338 struct _WapiHandlePrivate_socket *socket_private_handle;
342 if(startup_count==0) {
343 WSASetLastError(WSANOTINITIALISED);
344 return(SOCKET_ERROR);
347 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
348 NULL, (gpointer *)&socket_private_handle);
350 g_warning (G_GNUC_PRETTY_FUNCTION
351 ": error looking up socket handle 0x%x", handle);
352 WSASetLastError(WSAENOTSOCK);
353 return(SOCKET_ERROR);
356 ret=getpeername(socket_private_handle->fd, name, namelen);
360 g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
364 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
365 WSASetLastError (errnum);
367 return(SOCKET_ERROR);
373 int _wapi_getsockname(guint32 handle, struct sockaddr *name,
376 struct _WapiHandlePrivate_socket *socket_private_handle;
380 if(startup_count==0) {
381 WSASetLastError(WSANOTINITIALISED);
382 return(SOCKET_ERROR);
385 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
386 NULL, (gpointer *)&socket_private_handle);
388 g_warning (G_GNUC_PRETTY_FUNCTION
389 ": error looking up socket handle 0x%x", handle);
390 WSASetLastError(WSAENOTSOCK);
391 return(SOCKET_ERROR);
394 ret=getsockname(socket_private_handle->fd, name, namelen);
398 g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
402 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
403 WSASetLastError (errnum);
405 return(SOCKET_ERROR);
411 int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval,
414 struct _WapiHandlePrivate_socket *socket_private_handle;
418 if(startup_count==0) {
419 WSASetLastError(WSANOTINITIALISED);
420 return(SOCKET_ERROR);
423 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
424 NULL, (gpointer *)&socket_private_handle);
426 g_warning (G_GNUC_PRETTY_FUNCTION
427 ": error looking up socket handle 0x%x", handle);
428 WSASetLastError(WSAENOTSOCK);
429 return(SOCKET_ERROR);
432 ret=getsockopt(socket_private_handle->fd, level, optname, optval,
437 g_message(G_GNUC_PRETTY_FUNCTION ": getsockopt error: %s",
441 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
442 WSASetLastError (errnum);
444 return(SOCKET_ERROR);
450 int _wapi_listen(guint32 handle, int backlog)
452 struct _WapiHandlePrivate_socket *socket_private_handle;
456 if(startup_count==0) {
457 WSASetLastError(WSANOTINITIALISED);
458 return(SOCKET_ERROR);
461 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
462 NULL, (gpointer *)&socket_private_handle);
464 g_warning (G_GNUC_PRETTY_FUNCTION
465 ": error looking up socket handle 0x%x", handle);
466 WSASetLastError(WSAENOTSOCK);
467 return(SOCKET_ERROR);
470 ret=listen(socket_private_handle->fd, backlog);
474 g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
478 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
479 WSASetLastError (errnum);
481 return(SOCKET_ERROR);
487 int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags)
489 return(_wapi_recvfrom(handle, buf, len, recv_flags, NULL, 0));
492 int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags,
493 struct sockaddr *from, socklen_t *fromlen)
495 #ifndef HAVE_MSG_NOSIGNAL
496 void (*old_sigpipe)(int); // old SIGPIPE handler
498 struct _WapiHandlePrivate_socket *socket_private_handle;
502 if(startup_count==0) {
503 WSASetLastError(WSANOTINITIALISED);
504 return(SOCKET_ERROR);
507 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
508 NULL, (gpointer *)&socket_private_handle);
510 g_warning (G_GNUC_PRETTY_FUNCTION
511 ": error looking up socket handle 0x%x", handle);
512 WSASetLastError(WSAENOTSOCK);
513 return(SOCKET_ERROR);
516 #ifdef HAVE_MSG_NOSIGNAL
517 ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
520 old_sigpipe = signal(SIGPIPE, SIG_IGN);
521 ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags, from,
523 signal(SIGPIPE, old_sigpipe);
529 g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
533 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
534 WSASetLastError (errnum);
536 return(SOCKET_ERROR);
541 int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags)
543 #ifndef HAVE_MSG_NOSIGNAL
544 void (*old_sigpipe)(int); // old SIGPIPE handler
546 struct _WapiHandlePrivate_socket *socket_private_handle;
550 if(startup_count==0) {
551 WSASetLastError(WSANOTINITIALISED);
552 return(SOCKET_ERROR);
555 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
556 NULL, (gpointer *)&socket_private_handle);
558 g_warning (G_GNUC_PRETTY_FUNCTION
559 ": error looking up socket handle 0x%x", handle);
560 WSASetLastError(WSAENOTSOCK);
561 return(SOCKET_ERROR);
564 #ifdef HAVE_MSG_NOSIGNAL
565 ret=send(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL);
567 old_sigpipe = signal(SIGPIPE, SIG_IGN);
568 ret=send(socket_private_handle->fd, msg, len, send_flags);
569 signal(SIGPIPE, old_sigpipe);
574 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
578 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
579 WSASetLastError (errnum);
581 return(SOCKET_ERROR);
586 int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags,
587 const struct sockaddr *to, socklen_t tolen)
589 #ifndef HAVE_MSG_NOSIGNAL
590 void (*old_sigpipe)(int); // old SIGPIPE handler
592 struct _WapiHandlePrivate_socket *socket_private_handle;
596 if(startup_count==0) {
597 WSASetLastError(WSANOTINITIALISED);
598 return(SOCKET_ERROR);
601 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
602 NULL, (gpointer *)&socket_private_handle);
604 g_warning (G_GNUC_PRETTY_FUNCTION
605 ": error looking up socket handle 0x%x", handle);
606 WSASetLastError(WSAENOTSOCK);
607 return(SOCKET_ERROR);
610 #ifdef HAVE_MSG_NOSIGNAL
611 ret=sendto(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
613 old_sigpipe = signal(SIGPIPE, SIG_IGN);
614 ret=sendto(socket_private_handle->fd, msg, len, send_flags, to, tolen);
615 signal(SIGPIPE, old_sigpipe);
620 g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
624 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
625 WSASetLastError (errnum);
627 return(SOCKET_ERROR);
632 int _wapi_setsockopt(guint32 handle, int level, int optname,
633 const void *optval, socklen_t optlen)
635 struct _WapiHandlePrivate_socket *socket_private_handle;
639 if(startup_count==0) {
640 WSASetLastError(WSANOTINITIALISED);
641 return(SOCKET_ERROR);
644 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
645 NULL, (gpointer *)&socket_private_handle);
647 g_warning (G_GNUC_PRETTY_FUNCTION
648 ": error looking up socket handle 0x%x", handle);
649 WSASetLastError(WSAENOTSOCK);
650 return(SOCKET_ERROR);
653 ret=setsockopt(socket_private_handle->fd, level, optname, optval,
658 g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
662 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
663 WSASetLastError (errnum);
665 return(SOCKET_ERROR);
671 int _wapi_shutdown(guint32 handle, int how)
673 struct _WapiHandlePrivate_socket *socket_private_handle;
677 if(startup_count==0) {
678 WSASetLastError(WSANOTINITIALISED);
679 return(SOCKET_ERROR);
682 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
683 NULL, (gpointer *)&socket_private_handle);
685 g_warning (G_GNUC_PRETTY_FUNCTION
686 ": error looking up socket handle 0x%x", handle);
687 WSASetLastError(WSAENOTSOCK);
688 return(SOCKET_ERROR);
691 ret=shutdown(socket_private_handle->fd, how);
695 g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
699 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
700 WSASetLastError (errnum);
702 return(SOCKET_ERROR);
708 guint32 _wapi_socket(int domain, int type, int protocol)
710 struct _WapiHandlePrivate_socket *socket_private_handle;
715 fd=socket(domain, type, protocol);
718 g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
721 return(INVALID_SOCKET);
724 mono_once (&socket_ops_once, socket_ops_init);
726 handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
727 if(handle==_WAPI_HANDLE_INVALID) {
728 g_warning (G_GNUC_PRETTY_FUNCTION
729 ": error creating socket handle");
730 return(INVALID_SOCKET);
733 _wapi_handle_lock_handle (handle);
735 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
736 (gpointer *)&socket_private_handle);
738 g_warning (G_GNUC_PRETTY_FUNCTION
739 ": error looking up socket handle %p", handle);
740 _wapi_handle_unlock_handle (handle);
741 return(INVALID_SOCKET);
744 socket_private_handle->fd=fd;
747 g_message(G_GNUC_PRETTY_FUNCTION
748 ": returning socket handle %p with fd %d", handle,
749 socket_private_handle->fd);
752 _wapi_handle_unlock_handle (handle);
754 return(GPOINTER_TO_UINT (handle));
757 struct hostent *_wapi_gethostbyname(const char *hostname)
761 if(startup_count==0) {
762 WSASetLastError(WSANOTINITIALISED);
766 he=gethostbyname(hostname);
769 g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
775 WSASetLastError(WSAHOST_NOT_FOUND);
777 #if NO_ADDRESS != NO_DATA
781 WSASetLastError(WSANO_DATA);
784 WSASetLastError(WSANO_RECOVERY);
787 WSASetLastError(WSATRY_AGAIN);
790 g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
798 int ioctlsocket(guint32 handle, gint32 command, gpointer arg)
800 struct _WapiHandlePrivate_socket *socket_private_handle;
804 if(startup_count==0) {
805 WSASetLastError(WSANOTINITIALISED);
806 return(SOCKET_ERROR);
809 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
810 NULL, (gpointer *)&socket_private_handle);
812 g_warning (G_GNUC_PRETTY_FUNCTION
813 ": error looking up socket handle 0x%x", handle);
814 WSASetLastError(WSAENOTSOCK);
815 return(SOCKET_ERROR);
818 if(command!=FIONBIO &&
820 command!=SIOCATMARK) {
821 /* Not listed in the MSDN specs, but ioctl(2) returns
822 * this if command is invalid
824 WSASetLastError(WSAEINVAL);
825 return(SOCKET_ERROR);
829 /* This works better than ioctl(...FIONBIO...) on Linux (it causes
830 * connect to return EINPROGRESS, but the ioctl doesn't seem to)
832 if(command==FIONBIO) {
833 ret=fcntl(socket_private_handle->fd, F_GETFL, 0);
835 if(*(gboolean *)arg) {
840 ret=fcntl(socket_private_handle->fd, F_SETFL, ret);
843 #endif /* O_NONBLOCK */
845 ret=ioctl(socket_private_handle->fd, command, arg);
850 g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
854 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
855 WSASetLastError (errnum);
857 return(SOCKET_ERROR);
863 int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
864 fd_set *exceptfds, struct timeval *timeout)
868 if(startup_count==0) {
869 WSASetLastError(WSANOTINITIALISED);
870 return(SOCKET_ERROR);
873 ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
877 g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
880 errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
881 WSASetLastError (errnum);
883 return(SOCKET_ERROR);
889 void _wapi_FD_CLR(guint32 handle, fd_set *set)
891 struct _WapiHandlePrivate_socket *socket_private_handle;
894 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
895 NULL, (gpointer *)&socket_private_handle);
897 g_warning (G_GNUC_PRETTY_FUNCTION
898 ": error looking up socket handle 0x%x", handle);
899 WSASetLastError(WSAENOTSOCK);
903 FD_CLR(socket_private_handle->fd, set);
906 int _wapi_FD_ISSET(guint32 handle, fd_set *set)
908 struct _WapiHandlePrivate_socket *socket_private_handle;
911 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
912 NULL, (gpointer *)&socket_private_handle);
914 g_warning (G_GNUC_PRETTY_FUNCTION
915 ": error looking up socket handle 0x%x", handle);
916 WSASetLastError(WSAENOTSOCK);
920 return(FD_ISSET(socket_private_handle->fd, set));
923 void _wapi_FD_SET(guint32 handle, fd_set *set)
925 struct _WapiHandlePrivate_socket *socket_private_handle;
928 ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
929 NULL, (gpointer *)&socket_private_handle);
931 g_warning (G_GNUC_PRETTY_FUNCTION
932 ": error looking up socket handle 0x%x", handle);
933 WSASetLastError(WSAENOTSOCK);
937 FD_SET(socket_private_handle->fd, set);