3 * Socket IO internal calls
6 * Dick Porter (dick@ximian.com)
7 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * This file has been re-licensed under the MIT License:
13 * http://opensource.org/licenses/MIT
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
19 #include <mono/metadata/w32socket.h>
21 #if !defined(DISABLE_SOCKETS) && !defined(ENABLE_NETCORE)
23 #if defined(__APPLE__) || defined(__FreeBSD__)
24 #define __APPLE_USE_RFC_3542
33 #include <sys/socket.h>
34 #ifdef HAVE_SYS_IOCTL_H
35 #include <sys/ioctl.h>
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
42 #ifdef HAVE_NETINET_TCP_H
43 #include <arpa/inet.h>
50 #include <mono/utils/mono-errno.h>
52 #include <sys/types.h>
54 #include <mono/metadata/object.h>
55 #include <mono/metadata/exception.h>
56 #include <mono/metadata/assembly-internals.h>
57 #include <mono/metadata/appdomain.h>
58 #include <mono/metadata/w32file.h>
59 #include <mono/metadata/threads.h>
60 #include <mono/metadata/threads-types.h>
61 #include <mono/metadata/threadpool-io.h>
62 #include <mono/utils/mono-poll.h>
63 /* FIXME change this code to not mess so much with the internals */
64 #include <mono/metadata/class-internals.h>
65 #include <mono/metadata/domain-internals.h>
66 #include <mono/metadata/image-internals.h>
67 #include <mono/utils/mono-threads.h>
68 #include <mono/utils/mono-memory-model.h>
69 #include <mono/utils/networking.h>
70 #include <mono/metadata/w32handle.h>
71 #include <mono/metadata/w32socket-internals.h>
72 #include <mono/metadata/w32error.h>
75 #ifdef HAVE_SYS_TIME_H
78 #ifdef HAVE_SYS_IOCTL_H
79 #include <sys/ioctl.h>
88 #ifdef HAVE_SYS_FILIO_H
89 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
91 #ifdef HAVE_SYS_SOCKIO_H
92 #include <sys/sockio.h> /* defines SIOCATMARK */
98 #ifdef HAVE_GETIFADDRS
99 // <net/if.h> must be included before <ifaddrs.h>
101 #elif defined(HAVE_QP2GETIFADDRS)
102 /* Bizarrely, IBM i implements this, but AIX doesn't, so on i, it has a different name... */
103 #include <as400_types.h>
104 #include <as400_protos.h>
105 /* Defines to just reuse ifaddrs code */
106 #define ifaddrs ifaddrs_pase
107 #define freeifaddrs Qp2freeifaddrs
108 #define getifaddrs Qp2getifaddrs
111 #if defined(_MSC_VER) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
114 #include "icall-decl.h"
116 #define LOGDEBUG(...)
117 /* define LOGDEBUG(...) g_message(__VA_ARGS__) */
120 addrinfo_to_IPHostEntry_handles (MonoAddressInfo
*info
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gboolean add_local_ips
, MonoError
*error
);
122 static MonoObjectHandle
123 create_object_handle_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
);
125 static struct sockaddr
*
126 create_sockaddr_from_handle (MonoObjectHandle saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
);
131 mono_w32socket_socket (int domain
, int type
, int protocol
)
135 ret
= WSASocket (domain
, type
, protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
);
141 mono_w32socket_bind (SOCKET sock
, struct sockaddr
*addr
, socklen_t addrlen
)
145 ret
= bind (sock
, addr
, addrlen
);
151 mono_w32socket_getpeername (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
155 ret
= getpeername (sock
, name
, namelen
);
161 mono_w32socket_getsockname (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
165 ret
= getsockname (sock
, name
, namelen
);
171 mono_w32socket_getsockopt (SOCKET sock
, gint level
, gint optname
, gpointer optval
, socklen_t
*optlen
)
175 ret
= getsockopt (sock
, level
, optname
, (char*)optval
, optlen
);
181 mono_w32socket_setsockopt (SOCKET sock
, gint level
, gint optname
, gconstpointer optval
, socklen_t optlen
)
185 ret
= setsockopt (sock
, level
, optname
, (const char*)optval
, optlen
);
191 mono_w32socket_listen (SOCKET sock
, gint backlog
)
195 ret
= listen (sock
, backlog
);
201 mono_w32socket_shutdown (SOCKET sock
, gint how
)
205 ret
= shutdown (sock
, how
);
211 mono_w32socket_ioctl (SOCKET sock
, gint32 command
, gchar
*input
, gint inputlen
, gchar
*output
, gint outputlen
, DWORD
*written
)
215 ret
= WSAIoctl (sock
, command
, input
, inputlen
, output
, outputlen
, written
, NULL
, NULL
);
221 mono_w32socket_close (SOCKET sock
)
225 ret
= closesocket (sock
);
230 #endif /* HOST_WIN32 */
233 convert_family (MonoAddressFamily mono_family
)
235 switch (mono_family
) {
236 case AddressFamily_Unknown
:
237 case AddressFamily_ImpLink
:
238 case AddressFamily_Pup
:
239 case AddressFamily_Chaos
:
240 case AddressFamily_Iso
:
241 case AddressFamily_Ecma
:
242 case AddressFamily_DataKit
:
243 case AddressFamily_Ccitt
:
244 case AddressFamily_DataLink
:
245 case AddressFamily_Lat
:
246 case AddressFamily_HyperChannel
:
247 case AddressFamily_NetBios
:
248 case AddressFamily_VoiceView
:
249 case AddressFamily_FireFox
:
250 case AddressFamily_Banyan
:
251 case AddressFamily_Atm
:
252 case AddressFamily_Cluster
:
253 case AddressFamily_Ieee12844
:
254 case AddressFamily_NetworkDesigners
:
255 g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family
);
257 case AddressFamily_Unspecified
:
259 case AddressFamily_Unix
:
261 case AddressFamily_InterNetwork
:
263 case AddressFamily_AppleTalk
:
269 case AddressFamily_InterNetworkV6
:
270 #ifdef HAVE_STRUCT_SOCKADDR_IN6
275 case AddressFamily_DecNet
:
281 case AddressFamily_Ipx
:
287 case AddressFamily_Sna
:
293 case AddressFamily_Irda
:
300 g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family
);
305 static MonoAddressFamily
306 convert_to_mono_family (guint16 af_family
)
310 return AddressFamily_Unspecified
;
312 return AddressFamily_Unix
;
314 return AddressFamily_InterNetwork
;
317 return AddressFamily_Ipx
;
321 return AddressFamily_Sna
;
325 return AddressFamily_DecNet
;
329 return AddressFamily_AppleTalk
;
331 #ifdef HAVE_STRUCT_SOCKADDR_IN6
333 return AddressFamily_InterNetworkV6
;
337 return AddressFamily_Irda
;
340 g_warning ("unknown address family 0x%x", af_family
);
341 return AddressFamily_Unknown
;
346 convert_type (MonoSocketType mono_type
)
349 case SocketType_Stream
:
351 case SocketType_Dgram
:
361 case SocketType_Seqpacket
:
362 #ifdef SOCK_SEQPACKET
363 return SOCK_SEQPACKET
;
367 case SocketType_Unknown
:
368 g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type
);
371 g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type
);
377 convert_proto (MonoProtocolType mono_proto
)
379 switch (mono_proto
) {
380 case ProtocolType_IP
:
381 case ProtocolType_IPv6
:
382 case ProtocolType_Icmp
:
383 case ProtocolType_Igmp
:
384 case ProtocolType_Ggp
:
385 case ProtocolType_Tcp
:
386 case ProtocolType_Pup
:
387 case ProtocolType_Udp
:
388 case ProtocolType_Idp
:
389 /* These protocols are known (on my system at least) */
391 case ProtocolType_ND
:
392 case ProtocolType_Raw
:
393 case ProtocolType_Ipx
:
394 case ProtocolType_Spx
:
395 case ProtocolType_SpxII
:
396 case ProtocolType_Unknown
:
397 /* These protocols arent */
398 g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto
);
405 /* Convert MonoSocketFlags */
407 convert_socketflags (gint32 sflags
)
412 /* SocketFlags.None */
415 if (sflags
& ~(SocketFlags_OutOfBand
| SocketFlags_MaxIOVectorLength
| SocketFlags_Peek
|
416 SocketFlags_DontRoute
| SocketFlags_Partial
))
417 /* Contains invalid flag values */
421 if (sflags
& SocketFlags_OutOfBand
)
424 if (sflags
& SocketFlags_Peek
)
426 if (sflags
& SocketFlags_DontRoute
)
427 flags
|= MSG_DONTROUTE
;
429 /* Ignore Partial - see bug 349688. Don't return -1, because
430 * according to the comment in that bug ms runtime doesn't for
431 * UDP sockets (this means we will silently ignore it for TCP
435 if (sflags
& SocketFlags_Partial
)
439 /* Don't do anything for MaxIOVectorLength */
440 if (sflags
& SocketFlags_MaxIOVectorLength
)
448 * 0 on success (mapped mono_level and mono_name to system_level and system_name
450 * -2 on non-fatal error (ie, must ignore)
453 convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level
, MonoSocketOptionName mono_name
, int *system_level
, int *system_name
)
455 switch (mono_level
) {
456 case SocketOptionLevel_Socket
:
457 *system_level
= SOL_SOCKET
;
460 case SocketOptionName_DontLinger
:
461 /* This is SO_LINGER, because the setsockopt
462 * internal call maps DontLinger to SO_LINGER
465 *system_name
= SO_LINGER
;
468 case SocketOptionName_Debug
:
469 *system_name
= SO_DEBUG
;
473 case SocketOptionName_AcceptConnection
:
474 *system_name
= SO_ACCEPTCONN
;
477 case SocketOptionName_ReuseAddress
:
478 *system_name
= SO_REUSEADDR
;
480 case SocketOptionName_KeepAlive
:
481 *system_name
= SO_KEEPALIVE
;
484 case SocketOptionName_DontRoute
:
485 *system_name
= SO_DONTROUTE
;
488 case SocketOptionName_Broadcast
:
489 *system_name
= SO_BROADCAST
;
491 case SocketOptionName_Linger
:
492 *system_name
= SO_LINGER
;
495 case SocketOptionName_OutOfBandInline
:
496 *system_name
= SO_OOBINLINE
;
499 case SocketOptionName_SendBuffer
:
500 *system_name
= SO_SNDBUF
;
502 case SocketOptionName_ReceiveBuffer
:
503 *system_name
= SO_RCVBUF
;
505 case SocketOptionName_SendLowWater
:
506 *system_name
= SO_SNDLOWAT
;
508 case SocketOptionName_ReceiveLowWater
:
509 *system_name
= SO_RCVLOWAT
;
511 case SocketOptionName_SendTimeout
:
512 *system_name
= SO_SNDTIMEO
;
514 case SocketOptionName_ReceiveTimeout
:
515 *system_name
= SO_RCVTIMEO
;
517 case SocketOptionName_Error
:
518 *system_name
= SO_ERROR
;
520 case SocketOptionName_Type
:
521 *system_name
= SO_TYPE
;
524 case SocketOptionName_PeerCred
:
525 *system_name
= SO_PEERCRED
;
528 case SocketOptionName_ExclusiveAddressUse
:
529 #ifdef SO_EXCLUSIVEADDRUSE
530 *system_name
= SO_EXCLUSIVEADDRUSE
;
533 case SocketOptionName_UseLoopback
:
534 #ifdef SO_USELOOPBACK
535 *system_name
= SO_USELOOPBACK
;
538 case SocketOptionName_MaxConnections
:
540 *system_name
= SO_MAXCONN
;
542 #elif defined(SOMAXCONN)
543 *system_name
= SOMAXCONN
;
547 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name
);
552 case SocketOptionLevel_IP
:
553 *system_level
= mono_networking_get_ip_protocol ();
557 case SocketOptionName_IPOptions
:
558 *system_name
= IP_OPTIONS
;
562 case SocketOptionName_HeaderIncluded
:
563 *system_name
= IP_HDRINCL
;
567 case SocketOptionName_TypeOfService
:
568 *system_name
= IP_TOS
;
572 case SocketOptionName_IpTimeToLive
:
573 *system_name
= IP_TTL
;
576 case SocketOptionName_MulticastInterface
:
577 *system_name
= IP_MULTICAST_IF
;
579 case SocketOptionName_MulticastTimeToLive
:
580 *system_name
= IP_MULTICAST_TTL
;
582 case SocketOptionName_MulticastLoopback
:
583 *system_name
= IP_MULTICAST_LOOP
;
585 case SocketOptionName_AddMembership
:
586 *system_name
= IP_ADD_MEMBERSHIP
;
588 case SocketOptionName_DropMembership
:
589 *system_name
= IP_DROP_MEMBERSHIP
;
591 #ifdef HAVE_IP_PKTINFO
592 case SocketOptionName_PacketInformation
:
593 *system_name
= IP_PKTINFO
;
595 #endif /* HAVE_IP_PKTINFO */
597 case SocketOptionName_DontFragment
:
598 #ifdef HAVE_IP_DONTFRAGMENT
599 *system_name
= IP_DONTFRAGMENT
;
601 #elif defined HAVE_IP_MTU_DISCOVER
602 /* Not quite the same */
603 *system_name
= IP_MTU_DISCOVER
;
606 /* If the flag is not available on this system, we can ignore this error */
608 #endif /* HAVE_IP_DONTFRAGMENT */
609 case SocketOptionName_AddSourceMembership
:
610 case SocketOptionName_DropSourceMembership
:
611 case SocketOptionName_BlockSource
:
612 case SocketOptionName_UnblockSource
:
613 /* Can't figure out how to map these, so fall
617 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name
);
622 case SocketOptionLevel_IPv6
:
623 *system_level
= mono_networking_get_ipv6_protocol ();
626 case SocketOptionName_IpTimeToLive
:
627 case SocketOptionName_HopLimit
:
628 *system_name
= IPV6_UNICAST_HOPS
;
630 case SocketOptionName_MulticastInterface
:
631 *system_name
= IPV6_MULTICAST_IF
;
633 case SocketOptionName_MulticastTimeToLive
:
634 *system_name
= IPV6_MULTICAST_HOPS
;
636 case SocketOptionName_MulticastLoopback
:
637 *system_name
= IPV6_MULTICAST_LOOP
;
639 case SocketOptionName_AddMembership
:
640 *system_name
= IPV6_JOIN_GROUP
;
642 case SocketOptionName_DropMembership
:
643 *system_name
= IPV6_LEAVE_GROUP
;
645 case SocketOptionName_IPv6Only
:
647 *system_name
= IPV6_V6ONLY
;
652 case SocketOptionName_PacketInformation
:
653 #ifdef HAVE_IPV6_PKTINFO
654 *system_name
= IPV6_PKTINFO
;
657 case SocketOptionName_HeaderIncluded
:
658 case SocketOptionName_IPOptions
:
659 case SocketOptionName_TypeOfService
:
660 case SocketOptionName_DontFragment
:
661 case SocketOptionName_AddSourceMembership
:
662 case SocketOptionName_DropSourceMembership
:
663 case SocketOptionName_BlockSource
:
664 case SocketOptionName_UnblockSource
:
665 /* Can't figure out how to map these, so fall
669 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name
);
672 break; /* SocketOptionLevel_IPv6 */
674 case SocketOptionLevel_Tcp
:
675 *system_level
= mono_networking_get_tcp_protocol ();
678 case SocketOptionName_NoDelay
:
679 *system_name
= TCP_NODELAY
;
682 /* The documentation is talking complete
683 * bollocks here: rfc-1222 is titled
684 * 'Advancing the NSFNET Routing Architecture'
685 * and doesn't mention either of the words
686 * "expedite" or "urgent".
688 case SocketOptionName_BsdUrgent
:
689 case SocketOptionName_Expedited
:
692 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name
);
697 case SocketOptionLevel_Udp
:
698 g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level
);
701 case SocketOptionName_NoChecksum
:
702 case SocketOptionName_ChecksumCoverage
:
704 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name
);
711 g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level
);
719 get_socket_assembly (void)
721 MonoDomain
*domain
= mono_domain_get ();
723 if (domain
->socket_assembly
== NULL
) {
724 MonoImage
*socket_assembly
;
725 MonoAssemblyLoadContext
*alc
= mono_domain_default_alc (domain
);
727 socket_assembly
= mono_image_loaded_internal (alc
, "System", FALSE
);
728 if (!socket_assembly
) {
729 MonoAssemblyOpenRequest req
;
730 mono_assembly_request_prepare_open (&req
, MONO_ASMCTX_DEFAULT
, alc
);
731 MonoAssembly
*sa
= mono_assembly_request_open ("System.dll", &req
, NULL
);
734 g_assert_not_reached ();
736 socket_assembly
= mono_assembly_get_image_internal (sa
);
739 mono_atomic_store_release (&domain
->socket_assembly
, socket_assembly
);
742 return domain
->socket_assembly
;
746 ves_icall_System_Net_Sockets_Socket_Socket_icall (gint32 family
, gint32 type
, gint32 proto
, gint32
*werror
, MonoError
*error
)
756 sock_family
= convert_family ((MonoAddressFamily
)family
);
757 if (sock_family
== -1) {
758 *werror
= WSAEAFNOSUPPORT
;
762 sock_proto
= convert_proto ((MonoProtocolType
)proto
);
763 if (sock_proto
== -1) {
764 *werror
= WSAEPROTONOSUPPORT
;
768 sock_type
= convert_type ((MonoSocketType
)type
);
769 if (sock_type
== -1) {
770 *werror
= WSAESOCKTNOSUPPORT
;
774 sock
= mono_w32socket_socket (sock_family
, sock_type
, sock_proto
);
776 if (sock
== INVALID_SOCKET
) {
777 *werror
= mono_w32socket_get_last_error ();
781 return GUINT_TO_POINTER (sock
);
784 /* FIXME: the SOCKET parameter (here and in other functions in this
785 * file) is really an IntPtr which needs to be converted to a guint32.
788 ves_icall_System_Net_Sockets_Socket_Close_icall (gsize sock
, gint32
*werror
)
790 LOGDEBUG (g_message ("%s: closing 0x%x", __func__
, sock
));
794 /* Clear any pending work item from this socket if the underlying
795 * polling system does not notify when the socket is closed */
796 mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock
));
798 mono_w32socket_close ((SOCKET
) sock
);
802 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_icall (void)
804 LOGDEBUG (g_message("%s: returning %d", __func__
, mono_w32socket_get_last_error ()));
806 return mono_w32socket_get_last_error ();
810 ves_icall_System_Net_Sockets_Socket_Available_icall (gsize sock
, gint32
*werror
)
817 /* FIXME: this might require amount to be unsigned long. */
818 ret
= mono_w32socket_get_available (sock
, &amount
);
819 if (ret
== SOCKET_ERROR
) {
820 *werror
= mono_w32socket_get_last_error ();
828 ves_icall_System_Net_Sockets_Socket_Blocking_icall (gsize sock
, MonoBoolean block
, gint32
*werror
)
834 ret
= mono_w32socket_set_blocking (sock
, block
);
835 if (ret
== SOCKET_ERROR
)
836 *werror
= mono_w32socket_get_last_error ();
840 ves_icall_System_Net_Sockets_Socket_Accept_icall (gsize sock
, gint32
*werror
, MonoBoolean blocking
)
846 newsock
= mono_w32socket_accept (sock
, NULL
, 0, blocking
);
847 if (newsock
== INVALID_SOCKET
) {
848 *werror
= mono_w32socket_get_last_error ();
852 return GUINT_TO_POINTER (newsock
);
856 ves_icall_System_Net_Sockets_Socket_Listen_icall (gsize sock
, guint32 backlog
, gint32
*werror
)
862 ret
= mono_w32socket_listen (sock
, backlog
);
863 if (ret
== SOCKET_ERROR
)
864 *werror
= mono_w32socket_get_last_error ();
867 #ifdef HAVE_STRUCT_SOCKADDR_IN6
868 // Check whether it's ::ffff::0:0.
870 is_ipv4_mapped_any (const struct in6_addr
*addr
)
874 for (i
= 0; i
< 10; i
++) {
875 if (addr
->s6_addr
[i
])
878 if ((addr
->s6_addr
[10] != 0xff) || (addr
->s6_addr
[11] != 0xff))
880 for (i
= 12; i
< 16; i
++) {
881 if (addr
->s6_addr
[i
])
888 static MonoObjectHandle
889 create_object_handle_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
)
891 MonoDomain
*domain
= mono_domain_get ();
892 MonoAddressFamily family
;
896 /* Build a System.Net.SocketAddress object instance */
897 if (!domain
->sockaddr_class
)
898 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
899 MonoObjectHandle sockaddr_obj
= mono_object_new_handle (domain
, domain
->sockaddr_class
, error
);
900 return_val_if_nok (error
, MONO_HANDLE_NEW (MonoObject
, NULL
));
902 /* Locate the SocketAddress data buffer in the object */
903 if (!domain
->sockaddr_data_field
) {
904 domain
->sockaddr_data_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Buffer", NULL
);
905 g_assert (domain
->sockaddr_data_field
);
908 /* Locate the SocketAddress data buffer length in the object */
909 if (!domain
->sockaddr_data_length_field
) {
910 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Size", NULL
);
911 g_assert (domain
->sockaddr_data_length_field
);
914 /* May be the +2 here is too conservative, as sa_len returns
915 * the length of the entire sockaddr_in/in6, including
916 * sizeof (unsigned short) of the family */
917 /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
918 MonoArrayHandle data
= mono_array_new_handle (domain
, mono_get_byte_class (), sa_size
+ 2, error
);
919 return_val_if_nok (error
, MONO_HANDLE_NEW (MonoObject
, NULL
));
921 /* The data buffer is laid out as follows:
922 * bytes 0 and 1 are the address family
923 * bytes 2 and 3 are the port info
924 * the rest is the address info
927 family
= convert_to_mono_family (saddr
->sa_family
);
928 if (family
== AddressFamily_Unknown
) {
929 *werror
= WSAEAFNOSUPPORT
;
930 return MONO_HANDLE_NEW (MonoObject
, NULL
);
933 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 0, family
& 0x0FF);
934 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 1, (family
>> 8) & 0x0FF);
936 if (saddr
->sa_family
== AF_INET
) {
937 struct sockaddr_in
*sa_in
= (struct sockaddr_in
*)saddr
;
938 guint16 port
= ntohs (sa_in
->sin_port
);
939 guint32 address
= ntohl (sa_in
->sin_addr
.s_addr
);
942 if (sa_size
< buffer_size
) {
943 mono_error_set_generic_error (error
, "System", "SystemException", "");
944 return MONO_HANDLE_NEW (MonoObject
, NULL
);
947 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 2, (port
>>8) & 0xff);
948 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 3, (port
) & 0xff);
949 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 4, (address
>>24) & 0xff);
950 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 5, (address
>>16) & 0xff);
951 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 6, (address
>>8) & 0xff);
952 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 7, (address
) & 0xff);
954 mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj
), domain
->sockaddr_data_field
, MONO_HANDLE_RAW (data
)); /* FIXME: use handles for mono_field_set_value */
955 mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj
), domain
->sockaddr_data_length_field
, &buffer_size
); /* FIXME: use handles for mono_field_set_value */
959 #ifdef HAVE_STRUCT_SOCKADDR_IN6
960 else if (saddr
->sa_family
== AF_INET6
) {
961 struct sockaddr_in6
*sa_in
= (struct sockaddr_in6
*)saddr
;
963 int buffer_size
= 28;
965 guint16 port
= ntohs (sa_in
->sin6_port
);
967 if (sa_size
< buffer_size
) {
968 mono_error_set_generic_error (error
, "System", "SystemException", "");
969 return MONO_HANDLE_NEW (MonoObject
, NULL
);
972 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 2, (port
>>8) & 0xff);
973 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 3, (port
) & 0xff);
975 if (is_ipv4_mapped_any (&sa_in
->sin6_addr
)) {
976 // Map ::ffff:0:0 to :: (bug #5502)
977 for (i
= 0; i
< 16; i
++)
978 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 8 + i
, 0);
980 for (i
= 0; i
< 16; i
++) {
981 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 8 + i
,
982 sa_in
->sin6_addr
.s6_addr
[i
]);
986 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 24, sa_in
->sin6_scope_id
& 0xff);
987 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 25,
988 (sa_in
->sin6_scope_id
>> 8) & 0xff);
989 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 26,
990 (sa_in
->sin6_scope_id
>> 16) & 0xff);
991 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 27,
992 (sa_in
->sin6_scope_id
>> 24) & 0xff);
994 mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj
), domain
->sockaddr_data_field
, MONO_HANDLE_RAW (data
)); /* FIXME: use handles for mono_field_set_value */
995 mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj
), domain
->sockaddr_data_length_field
, &buffer_size
); /* FIXME: use handles for mono_field_set_value */
1000 #ifdef HAVE_SYS_UN_H
1001 else if (saddr
->sa_family
== AF_UNIX
) {
1003 int buffer_size
= sa_size
+ 2;
1005 for (i
= 0; i
< sa_size
; i
++)
1006 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, i
+ 2, saddr
->sa_data
[i
]);
1008 mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj
), domain
->sockaddr_data_field
, MONO_HANDLE_RAW (data
)); /* FIXME: use handles for mono_field_set_value */
1009 mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj
), domain
->sockaddr_data_length_field
, &buffer_size
); /* FIXME: use handles for mono_field_set_value */
1011 return sockaddr_obj
;
1015 *werror
= WSAEAFNOSUPPORT
;
1016 return MONO_HANDLE_NEW (MonoObject
, NULL
);
1021 get_sockaddr_size (int family
)
1026 if (family
== AF_INET
) {
1027 size
= sizeof (struct sockaddr_in
);
1029 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1030 else if (family
== AF_INET6
) {
1031 size
= sizeof (struct sockaddr_in6
);
1034 #ifdef HAVE_SYS_UN_H
1035 else if (family
== AF_UNIX
) {
1036 size
= sizeof (struct sockaddr_un
);
1042 static MonoObjectHandle
1043 mono_w32socket_getname (gsize sock
, gint32 af
, gboolean local
, gint32
*werror
, MonoError
*error
)
1046 socklen_t salen
= 0;
1048 MonoObjectHandle result
= NULL_HANDLE
;
1052 salen
= get_sockaddr_size (convert_family ((MonoAddressFamily
)af
));
1054 *werror
= WSAEAFNOSUPPORT
;
1058 sa
= g_alloca (salen
);
1059 memset (sa
, 0, salen
);
1061 sa
= g_malloc0 (salen
);
1064 /* Note: linux returns just 2 for AF_UNIX. Always. */
1065 ret
= (local
? mono_w32socket_getsockname
: mono_w32socket_getpeername
) (sock
, (struct sockaddr
*)sa
, &salen
);
1066 if (ret
== SOCKET_ERROR
) {
1067 *werror
= mono_w32socket_get_last_error ();
1071 LOGDEBUG (g_message("%s: %s to %s port %d", __func__
, local
? "bound" : "connected", inet_ntoa (((struct sockaddr_in
*)&sa
)->sin_addr
), ntohs (((struct sockaddr_in
*)&sa
)->sin_port
)));
1073 result
= create_object_handle_from_sockaddr ((struct sockaddr
*)sa
, salen
, werror
, error
);
1081 ves_icall_System_Net_Sockets_Socket_LocalEndPoint_icall (gsize sock
, gint32 af
, gint32
*werror
, MonoError
*error
)
1083 return mono_w32socket_getname (sock
, af
, TRUE
, werror
, error
);
1087 ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_icall (gsize sock
, gint32 af
, gint32
*werror
, MonoError
*error
)
1089 return mono_w32socket_getname (sock
, af
, FALSE
, werror
, error
);
1092 static struct sockaddr
*
1093 create_sockaddr_from_handle (MonoObjectHandle saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
)
1095 MonoDomain
*domain
= mono_domain_get ();
1101 if (!domain
->sockaddr_class
)
1102 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
1104 /* Locate the SocketAddress data buffer in the object */
1105 if (!domain
->sockaddr_data_field
) {
1106 domain
->sockaddr_data_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Buffer", NULL
);
1107 g_assert (domain
->sockaddr_data_field
);
1110 /* Locate the SocketAddress data buffer length in the object */
1111 if (!domain
->sockaddr_data_length_field
) {
1112 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Size", NULL
);
1113 g_assert (domain
->sockaddr_data_length_field
);
1116 MonoArrayHandle data
= MONO_HANDLE_NEW_GET_FIELD (saddr_obj
, MonoArray
, domain
->sockaddr_data_field
);
1118 /* The data buffer is laid out as follows:
1119 * byte 0 is the address family low byte
1120 * byte 1 is the address family high byte
1122 * bytes 2 and 3 are the port info
1123 * the rest is the address info
1125 * the rest is the file name
1127 len
= MONO_HANDLE_GET_FIELD_VAL (saddr_obj
, int, domain
->sockaddr_data_length_field
);
1128 g_assert (len
>= 2);
1131 guint8
*buf
= MONO_ARRAY_HANDLE_PIN (data
, guint8
, 0, &gchandle
);
1132 family
= convert_family ((MonoAddressFamily
)(buf
[0] + (buf
[1] << 8)));
1133 if (family
== AF_INET
) {
1134 struct sockaddr_in
*sa
;
1139 mono_error_set_generic_error (error
, "System", "SystemException", "");
1140 mono_gchandle_free_internal (gchandle
);
1144 sa
= g_new0 (struct sockaddr_in
, 1);
1145 port
= (buf
[2] << 8) + buf
[3];
1146 address
= (buf
[4] << 24) + (buf
[5] << 16) + (buf
[6] << 8) + buf
[7];
1148 sa
->sin_family
= family
;
1149 sa
->sin_addr
.s_addr
= htonl (address
);
1150 sa
->sin_port
= htons (port
);
1152 *sa_size
= sizeof (struct sockaddr_in
);
1153 mono_gchandle_free_internal (gchandle
);
1154 return (struct sockaddr
*)sa
;
1156 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1157 else if (family
== AF_INET6
) {
1158 struct sockaddr_in6
*sa
;
1164 mono_error_set_generic_error (error
, "System", "SystemException", "");
1165 mono_gchandle_free_internal (gchandle
);
1169 sa
= g_new0 (struct sockaddr_in6
, 1);
1170 port
= buf
[3] + (buf
[2] << 8);
1171 scopeid
= buf
[24] + (buf
[25] << 8) + (buf
[26] << 16) + (buf
[27] << 24);
1173 sa
->sin6_family
= family
;
1174 sa
->sin6_port
= htons (port
);
1175 sa
->sin6_scope_id
= scopeid
;
1177 for (i
= 0; i
< 16; i
++)
1178 sa
->sin6_addr
.s6_addr
[i
] = buf
[8 + i
];
1180 *sa_size
= sizeof (struct sockaddr_in6
);
1181 mono_gchandle_free_internal (gchandle
);
1182 return (struct sockaddr
*)sa
;
1185 #ifdef HAVE_SYS_UN_H
1186 else if (family
== AF_UNIX
) {
1187 struct sockaddr_un
*sock_un
;
1190 /* Need a byte for the '\0' terminator/prefix, and the first
1191 * two bytes hold the SocketAddress family
1193 if (len
- 2 >= sizeof (sock_un
->sun_path
)) {
1194 mono_error_set_argument_out_of_range (error
, "SocketAddress.Size", "MonoArgumentException:SocketAddress.Size");
1195 mono_gchandle_free_internal (gchandle
);
1199 sock_un
= g_new0 (struct sockaddr_un
, 1);
1201 sock_un
->sun_family
= family
;
1202 for (i
= 0; i
< len
- 2; i
++)
1203 sock_un
->sun_path
[i
] = buf
[i
+ 2];
1206 mono_gchandle_free_internal (gchandle
);
1207 return (struct sockaddr
*)sock_un
;
1211 *werror
= WSAEAFNOSUPPORT
;
1212 mono_gchandle_free_internal (gchandle
);
1218 ves_icall_System_Net_Sockets_Socket_Bind_icall (gsize sock
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoError
*error
)
1220 struct sockaddr
*sa
;
1227 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1230 return_if_nok (error
);
1232 LOGDEBUG (g_message("%s: binding to %s port %d", __func__
, inet_ntoa (((struct sockaddr_in
*)sa
)->sin_addr
), ntohs (((struct sockaddr_in
*)sa
)->sin_port
)));
1234 ret
= mono_w32socket_bind (sock
, sa
, sa_size
);
1236 if (ret
== SOCKET_ERROR
)
1237 *werror
= mono_w32socket_get_last_error ();
1249 ves_icall_System_Net_Sockets_Socket_Poll_icall (gsize sock
, gint mode
, gint timeout
, gint32
*werror
)
1251 MonoInternalThread
*thread
= mono_thread_internal_current ();
1259 pfds
= g_new0 (mono_pollfd
, 1);
1260 pfds
->fd
= GPOINTER_TO_INT (sock
);
1263 case SelectModeRead
:
1264 pfds
->events
= MONO_POLLIN
;
1266 case SelectModeWrite
:
1267 pfds
->events
= MONO_POLLOUT
;
1270 pfds
->events
= MONO_POLLERR
| MONO_POLLHUP
| MONO_POLLNVAL
;
1274 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1276 start
= time (NULL
);
1281 ret
= mono_poll (pfds
, 1, timeout
);
1285 if (timeout
> 0 && ret
< 0) {
1287 int sec
= time (NULL
) - start
;
1289 timeout
= rtimeout
- sec
* 1000;
1294 mono_set_errno (err
);
1297 if (ret
== -1 && errno
== EINTR
) {
1298 if (mono_thread_test_state (thread
, ThreadState_AbortRequested
)) {
1303 /* Suspend requested? */
1304 mono_thread_interruption_checkpoint_void ();
1306 mono_set_errno (EINTR
);
1308 } while (ret
== -1 && errno
== EINTR
);
1311 *werror
= mono_w32socket_convert_error (errno
);
1321 ves_icall_System_Net_Sockets_Socket_Connect_icall (gsize sock
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1323 struct sockaddr
*sa
;
1330 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1333 return_if_nok (error
);
1335 LOGDEBUG (g_message("%s: connecting to %s port %d", __func__
, inet_ntoa (((struct sockaddr_in
*)sa
)->sin_addr
), ntohs (((struct sockaddr_in
*)sa
)->sin_port
)));
1337 ret
= mono_w32socket_connect (sock
, sa
, sa_size
, blocking
);
1338 if (ret
== SOCKET_ERROR
)
1339 *werror
= mono_w32socket_get_last_error ();
1344 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
1347 ves_icall_System_Net_Sockets_Socket_Disconnect_icall (gsize sock
, MonoBoolean reuse
, gint32
*werror
)
1349 LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__
, sock
, reuse
));
1351 *werror
= mono_w32socket_disconnect (sock
, reuse
);
1354 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
1357 ves_icall_System_Net_Sockets_Socket_Duplicate_icall (gpointer handle
, gint32 targetProcessId
, gpointer
*duplicate_handle
, gint32
*werror
)
1360 if (!mono_w32socket_duplicate (handle
, targetProcessId
, duplicate_handle
)) {
1361 *werror
= mono_w32error_get_last ();
1369 ves_icall_System_Net_Sockets_Socket_Receive_icall (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
)
1376 recvflags
= convert_socketflags (flags
);
1377 if (recvflags
== -1) {
1378 *werror
= WSAEOPNOTSUPP
;
1382 ret
= mono_w32socket_recv (sock
, buffer
, count
, recvflags
, blocking
);
1383 if (ret
== SOCKET_ERROR
) {
1384 *werror
= mono_w32socket_get_last_error ();
1392 ves_icall_System_Net_Sockets_Socket_Receive_array_icall (gsize sock
, WSABUF
*buffers
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
)
1396 guint32 recvflags
= 0;
1400 recvflags
= convert_socketflags (flags
);
1401 if (recvflags
== -1) {
1402 *werror
= WSAEOPNOTSUPP
;
1406 ret
= mono_w32socket_recvbuffers (sock
, buffers
, count
, &recv
, &recvflags
, NULL
, NULL
, blocking
);
1407 if (ret
== SOCKET_ERROR
) {
1408 *werror
= mono_w32socket_get_last_error ();
1416 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_icall (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, MonoObjectHandleInOut sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1420 struct sockaddr
*sa
;
1426 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1432 recvflags
= convert_socketflags (flags
);
1433 if (recvflags
== -1) {
1434 *werror
= WSAEOPNOTSUPP
;
1438 ret
= mono_w32socket_recvfrom (sock
, buffer
, count
, recvflags
, sa
, &sa_size
, blocking
);
1439 if (ret
== SOCKET_ERROR
) {
1440 *werror
= mono_w32socket_get_last_error ();
1445 /* If we didn't get a socket size, then we're probably a
1446 * connected connection-oriented socket and the stack hasn't
1447 * returned the remote address. All we can do is return null.
1450 MONO_HANDLE_ASSIGN (sockaddr
, create_object_handle_from_sockaddr (sa
, sa_size
, werror
, error
));
1451 if (!is_ok (error
)) {
1456 MONO_HANDLE_ASSIGN (sockaddr
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1465 ves_icall_System_Net_Sockets_Socket_Send_icall (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
)
1472 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1474 sendflags
= convert_socketflags (flags
);
1475 if (sendflags
== -1) {
1476 *werror
= WSAEOPNOTSUPP
;
1480 ret
= mono_w32socket_send (sock
, buffer
, count
, sendflags
, blocking
);
1481 if (ret
== SOCKET_ERROR
) {
1482 *werror
= mono_w32socket_get_last_error ();
1490 ves_icall_System_Net_Sockets_Socket_Send_array_icall (gsize sock
, WSABUF
*buffers
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
)
1494 guint32 sendflags
= 0;
1498 sendflags
= convert_socketflags (flags
);
1499 if (sendflags
== -1) {
1500 *werror
= WSAEOPNOTSUPP
;
1504 ret
= mono_w32socket_sendbuffers (sock
, buffers
, count
, &sent
, sendflags
, NULL
, NULL
, blocking
);
1505 if (ret
== SOCKET_ERROR
) {
1506 *werror
= mono_w32socket_get_last_error ();
1514 ves_icall_System_Net_Sockets_Socket_SendTo_icall (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1518 struct sockaddr
*sa
;
1523 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1524 if (*werror
!= 0 || !is_ok (error
))
1527 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1529 sendflags
= convert_socketflags (flags
);
1530 if (sendflags
== -1) {
1531 *werror
= WSAEOPNOTSUPP
;
1536 ret
= mono_w32socket_sendto (sock
, buffer
, count
, sendflags
, sa
, sa_size
, blocking
);
1537 if (ret
== SOCKET_ERROR
) {
1538 *werror
= mono_w32socket_get_last_error ();
1548 Socket_to_SOCKET (MonoObjectHandle sockobj
)
1550 MonoClassField
*field
;
1552 field
= mono_class_get_field_from_name_full (mono_handle_class (sockobj
), "m_Handle", NULL
);
1553 MonoSafeHandleHandle safe_handle
= MONO_HANDLE_NEW_GET_FIELD(sockobj
, MonoSafeHandle
, field
);
1555 if (MONO_HANDLE_IS_NULL (safe_handle
))
1558 return (SOCKET
)(gsize
)MONO_HANDLE_GETVAL (safe_handle
, handle
);
1561 #define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
1564 collect_pollfds_from_array (MonoArrayHandle sockets
, int i
, int nfds
, mono_pollfd
*pfds
, int *idx
, int *mode
)
1566 HANDLE_FUNCTION_ENTER ();
1567 gboolean result
= TRUE
;
1568 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1569 MONO_HANDLE_ARRAY_GETREF (obj
, sockets
, i
);
1570 if (MONO_HANDLE_IS_NULL (obj
)) {
1580 pfds
[*idx
].fd
= Socket_to_SOCKET (obj
);
1581 pfds
[*idx
].events
= (*mode
== 0) ? MONO_POLLIN
: (*mode
== 1) ? MONO_POLLOUT
: POLL_ERRORS
;
1584 HANDLE_FUNCTION_RETURN_VAL (result
);
1588 set_socks_array_from_pollfds (MonoArrayHandle sockets
, int i
, mono_pollfd
*pfds
, int *ret
, int *mode
, MonoArrayHandle socks
, int *idx
)
1590 HANDLE_FUNCTION_ENTER ();
1593 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1594 MONO_HANDLE_ARRAY_GETREF (obj
, sockets
, i
);
1595 if (MONO_HANDLE_IS_NULL (obj
)) {
1601 pfd
= &pfds
[i
- *mode
];
1602 if (pfd
->revents
== 0)
1606 if (((*mode
== 0 && (pfd
->revents
& (MONO_POLLIN
| POLL_ERRORS
)) != 0)) ||
1607 ((*mode
== 1 && (pfd
->revents
& (MONO_POLLOUT
| POLL_ERRORS
)) != 0)) ||
1608 ((pfd
->revents
& POLL_ERRORS
) != 0)) {
1609 MONO_HANDLE_ARRAY_SETREF (socks
, *idx
, obj
);
1613 HANDLE_FUNCTION_RETURN ();
1617 ves_icall_System_Net_Sockets_Socket_Select_icall (MonoArrayHandleOut sockets
, gint32 timeout
, gint32
*werror
, MonoError
*error
)
1619 MonoInternalThread
*thread
= mono_thread_internal_current ();
1625 MonoClass
*sock_arr_class
;
1627 uintptr_t socks_size
;
1633 /* *sockets -> READ, null, WRITE, null, ERROR, null */
1634 count
= mono_array_handle_length (sockets
);
1635 nfds
= count
- 3; /* NULL separators */
1636 pfds
= g_new0 (mono_pollfd
, nfds
);
1638 for (i
= 0; i
< count
; i
++) {
1639 if (!collect_pollfds_from_array (sockets
, i
, nfds
, pfds
, &idx
, &mode
)) {
1640 /* The socket array was bogus */
1642 *werror
= WSAEFAULT
;
1647 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1649 start
= time (NULL
);
1653 ret
= mono_poll (pfds
, nfds
, timeout
);
1657 if (timeout
> 0 && ret
< 0) {
1659 int sec
= time (NULL
) - start
;
1661 timeout
= rtimeout
- sec
* 1000;
1664 mono_set_errno (err
);
1667 if (ret
== -1 && errno
== EINTR
) {
1668 if (mono_thread_test_state (thread
, ThreadState_AbortRequested
)) {
1670 MONO_HANDLE_ASSIGN (sockets
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1674 /* Suspend requested? */
1675 mono_thread_interruption_checkpoint_void ();
1677 mono_set_errno (EINTR
);
1679 } while (ret
== -1 && errno
== EINTR
);
1682 *werror
= mono_w32socket_convert_error (errno
);
1689 MONO_HANDLE_ASSIGN (sockets
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1693 sock_arr_class
= mono_handle_class (sockets
);
1694 socks_size
= ((uintptr_t)ret
) + 3; /* space for the NULL delimiters */
1695 MonoArrayHandle socks
= MONO_HANDLE_NEW (MonoArray
, mono_array_new_full_checked (mono_domain_get (), sock_arr_class
, &socks_size
, NULL
, error
));
1696 if (!is_ok (error
)) {
1702 for (i
= 0; i
< count
&& ret
> 0; i
++) {
1703 set_socks_array_from_pollfds (sockets
, i
, pfds
, &ret
, &mode
, socks
, &idx
);
1706 MONO_HANDLE_ASSIGN (sockets
, socks
);
1710 static MonoObjectHandle
1711 int_to_object_handle (MonoDomain
*domain
, int val
, MonoError
*error
)
1713 return MONO_HANDLE_NEW (MonoObject
, mono_value_box_checked (domain
, mono_get_int32_class (), &val
, error
));
1717 ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_icall (gsize sock
, gint32 level
, gint32 name
, MonoObjectHandleOut obj_val
, gint32
*werror
, MonoError
*error
)
1719 int system_level
= 0;
1720 int system_name
= 0;
1723 socklen_t valsize
= sizeof (val
);
1724 struct linger linger
;
1725 socklen_t lingersize
= sizeof (linger
);
1727 socklen_t time_ms_size
= sizeof (time_ms
);
1729 # if defined(__OpenBSD__)
1730 struct sockpeercred cred
;
1734 socklen_t credsize
= sizeof (cred
);
1736 MonoDomain
*domain
= mono_domain_get ();
1737 MonoClass
*obj_class
;
1738 MonoClassField
*field
;
1743 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1744 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
1745 system_level
= SOL_SOCKET
;
1746 system_name
= SO_REUSEADDR
;
1751 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
, &system_name
);
1755 *werror
= WSAENOPROTOOPT
;
1759 MONO_HANDLE_ASSIGN (obj_val
, int_to_object_handle (domain
, 0, error
));
1763 /* No need to deal with MulticastOption names here, because
1764 * you cant getsockopt AddMembership or DropMembership (the
1765 * int getsockopt will error, causing an exception)
1768 case SocketOptionName_Linger
:
1769 case SocketOptionName_DontLinger
:
1770 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &linger
, &lingersize
);
1773 case SocketOptionName_SendTimeout
:
1774 case SocketOptionName_ReceiveTimeout
:
1775 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &time_ms
, &time_ms_size
);
1779 case SocketOptionName_PeerCred
:
1780 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &cred
, &credsize
);
1785 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &val
, &valsize
);
1788 if (ret
== SOCKET_ERROR
) {
1789 *werror
= mono_w32socket_get_last_error ();
1794 case SocketOptionName_Linger
: {
1795 /* build a System.Net.Sockets.LingerOption */
1796 obj_class
= mono_class_load_from_name (get_socket_assembly (),
1797 "System.Net.Sockets",
1799 MonoObjectHandle obj
= mono_object_new_handle (domain
, obj_class
, error
);
1800 return_if_nok (error
);
1802 /* Locate and set the fields "bool enabled" and "int
1805 field
= mono_class_get_field_from_name_full (obj_class
, "enabled", NULL
);
1806 MONO_HANDLE_SET_FIELD_VAL (obj
, guint8
, field
, linger
.l_onoff
);
1808 field
= mono_class_get_field_from_name_full (obj_class
, "lingerTime", NULL
);
1809 MONO_HANDLE_SET_FIELD_VAL (obj
, guint32
, field
, linger
.l_linger
);
1811 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1814 case SocketOptionName_DontLinger
: {
1815 /* construct a bool int in val - true if linger is off */
1816 MonoObjectHandle obj
= int_to_object_handle (domain
, !linger
.l_onoff
, error
);
1817 return_if_nok (error
);
1819 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1822 case SocketOptionName_SendTimeout
:
1823 case SocketOptionName_ReceiveTimeout
: {
1824 MonoObjectHandle obj
= int_to_object_handle (domain
, time_ms
, error
);
1825 return_if_nok (error
);
1827 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1832 case SocketOptionName_PeerCred
: {
1834 * build a Mono.Posix.PeerCred+PeerCredData if
1837 static MonoImage
*mono_posix_image
= NULL
;
1839 if (mono_posix_image
== NULL
) {
1840 MonoAssemblyLoadContext
*alc
= mono_domain_default_alc (domain
);
1841 mono_posix_image
= mono_image_loaded_internal (alc
, "Mono.Posix", FALSE
);
1842 if (!mono_posix_image
) {
1843 MonoAssemblyOpenRequest req
;
1844 mono_assembly_request_prepare_open (&req
, MONO_ASMCTX_DEFAULT
, alc
);
1845 MonoAssembly
*sa
= mono_assembly_request_open ("Mono.Posix.dll", &req
, NULL
);
1847 *werror
= WSAENOPROTOOPT
;
1850 mono_posix_image
= mono_assembly_get_image_internal (sa
);
1855 obj_class
= mono_class_load_from_name (mono_posix_image
,
1858 MonoPeerCredDataHandle cred_data
= MONO_HANDLE_CAST (MonoPeerCredData
, mono_object_new_handle (domain
, obj_class
, error
));
1859 return_if_nok (error
);
1861 MONO_HANDLE_SETVAL (cred_data
, pid
, gint
, cred
.pid
);
1862 MONO_HANDLE_SETVAL (cred_data
, uid
, gint
, cred
.uid
);
1863 MONO_HANDLE_SETVAL (cred_data
, gid
, gint
, cred
.gid
);
1865 MONO_HANDLE_ASSIGN (obj_val
, cred_data
);
1871 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1872 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
)
1875 MonoObjectHandle obj
= int_to_object_handle (domain
, val
, error
);
1876 return_if_nok (error
);
1878 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1883 ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_icall (gsize sock
, gint32 level
, gint32 name
, MonoArrayHandle byte_val
, gint32
*werror
, MonoError
*error
)
1885 int system_level
= 0;
1886 int system_name
= 0;
1893 ret
= convert_sockopt_level_and_name((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
1896 *werror
= WSAENOPROTOOPT
;
1902 valsize
= mono_array_handle_length (byte_val
);
1905 guchar
*buf
= MONO_ARRAY_HANDLE_PIN (byte_val
, guchar
, 0, &gchandle
);
1907 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, buf
, &valsize
);
1909 mono_gchandle_free_internal (gchandle
);
1911 if (ret
== SOCKET_ERROR
)
1912 *werror
= mono_w32socket_get_last_error ();
1915 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
1916 static struct in_addr
1917 ipaddress_handle_to_struct_in_addr (MonoObjectHandle ipaddr
)
1919 struct in_addr inaddr
;
1920 MonoClassField
*field
;
1922 field
= mono_class_get_field_from_name_full (mono_handle_class (ipaddr
), "_addressOrScopeId", NULL
);
1925 /* No idea why .net uses a 64bit type to hold a 32bit value...
1927 * Internal value of IPAddess is in little-endian order
1929 inaddr
.s_addr
= GUINT_FROM_LE ((guint32
)MONO_HANDLE_GET_FIELD_VAL (ipaddr
, guint32
, field
));
1934 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1935 static struct in6_addr
1936 ipaddress_handle_to_struct_in6_addr (MonoObjectHandle ipaddr
)
1938 struct in6_addr in6addr
;
1939 MonoClassField
*field
;
1942 field
= mono_class_get_field_from_name_full (mono_handle_class (ipaddr
), "_numbers", NULL
);
1944 MonoArrayHandle data
= MONO_HANDLE_NEW_GET_FIELD (ipaddr
, MonoArray
, field
);
1946 for (i
= 0; i
< 8; i
++) {
1948 MONO_HANDLE_ARRAY_GETVAL (v
, data
, guint16
, i
);
1949 const guint16 s
= GUINT16_TO_BE (v
);
1951 /* Solaris/MacOS have only the 8 bit version. */
1953 in6addr
.s6_addr
[2 * i
+ 1] = (s
>> 8) & 0xff;
1954 in6addr
.s6_addr
[2 * i
] = s
& 0xff;
1956 in6addr
.s6_addr16
[i
] = s
;
1964 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1965 #if defined(__APPLE__) || defined(__FreeBSD__)
1967 get_local_interface_id (int family
)
1969 #if !(defined(HAVE_GETIFADDRS) || defined(HAVE_QP2GETIFADDRS)) || !defined(HAVE_IF_NAMETOINDEX)
1972 struct ifaddrs
*ifap
= NULL
, *ptr
;
1975 if (getifaddrs (&ifap
))
1978 for (ptr
= ifap
; ptr
; ptr
= ptr
->ifa_next
) {
1979 if (!ptr
->ifa_addr
|| !ptr
->ifa_name
)
1981 if (ptr
->ifa_addr
->sa_family
!= family
)
1983 if ((ptr
->ifa_flags
& IFF_LOOPBACK
) != 0)
1985 if ((ptr
->ifa_flags
& IFF_MULTICAST
) == 0)
1988 idx
= if_nametoindex (ptr
->ifa_name
);
1996 #endif /* defined(__APPLE__) || defined(__FreeBSD__) */
1997 #endif /* HAVE_STRUCT_SOCKADDR_IN6 */
2000 ves_icall_System_Net_Sockets_Socket_SetSocketOption_icall (gsize sock
, gint32 level
, gint32 name
, MonoObjectHandle obj_val
, MonoArrayHandle byte_val
, gint32 int_val
, gint32
*werror
, MonoError
*error
)
2002 struct linger linger
;
2003 int system_level
= 0;
2004 int system_name
= 0;
2012 sol_ipv6
= mono_networking_get_ipv6_protocol ();
2013 sol_ip
= mono_networking_get_ip_protocol ();
2015 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
2018 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2019 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
2020 system_name
= SO_REUSEADDR
;
2021 int_val
= int_val
? 0 : 1;
2027 *werror
= WSAENOPROTOOPT
;
2033 /* Only one of obj_val, byte_val or int_val has data */
2034 if (!MONO_HANDLE_IS_NULL (obj_val
)) {
2035 MonoClass
*obj_class
= mono_handle_class (obj_val
);
2036 MonoClassField
*field
;
2040 case SocketOptionName_Linger
:
2041 /* Dig out "bool enabled" and "int lingerTime"
2044 field
= mono_class_get_field_from_name_full (obj_class
, "enabled", NULL
);
2045 linger
.l_onoff
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint8
, field
);
2046 field
= mono_class_get_field_from_name_full (obj_class
, "lingerTime", NULL
);
2047 linger
.l_linger
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint32
, field
);
2049 valsize
= sizeof (linger
);
2050 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, valsize
);
2052 case SocketOptionName_AddMembership
:
2053 case SocketOptionName_DropMembership
:
2054 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2056 MonoObjectHandle address
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2057 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2058 if (system_level
== sol_ipv6
) {
2059 struct ipv6_mreq mreq6
;
2064 field
= mono_class_get_field_from_name_full (obj_class
, "m_Group", NULL
);
2066 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2068 if (!MONO_HANDLE_IS_NULL (address
))
2069 mreq6
.ipv6mr_multiaddr
= ipaddress_handle_to_struct_in6_addr (address
);
2071 field
= mono_class_get_field_from_name_full (obj_class
, "m_Interface", NULL
);
2072 mreq6
.ipv6mr_interface
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint64
, field
);
2074 #if defined(__APPLE__) || defined(__FreeBSD__)
2078 * Mac OS Lion doesn't allow ipv6mr_interface = 0.
2080 * Tests on Windows and Linux show that the multicast group is only
2081 * joined on one NIC when interface = 0, so we simply use the interface
2082 * id from the first non-loopback interface (this is also what
2083 * Dns.GetHostName (string.Empty) would return).
2085 if (!mreq6
.ipv6mr_interface
)
2086 mreq6
.ipv6mr_interface
= get_local_interface_id (AF_INET6
);
2089 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq6
, sizeof (mreq6
));
2091 break; // Don't check sol_ip
2094 if (system_level
== sol_ip
) {
2095 #ifdef HAVE_STRUCT_IP_MREQN
2096 struct ip_mreqn mreq
= {{0}};
2098 struct ip_mreq mreq
= {{0}};
2099 #endif /* HAVE_STRUCT_IP_MREQN */
2102 * pain! MulticastOption holds two IPAddress
2103 * members, so I have to dig the value out of
2106 field
= mono_class_get_field_from_name_full (obj_class
, "group", NULL
);
2107 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2109 /* address might not be defined and if so, set the address to ADDR_ANY.
2111 if (!MONO_HANDLE_IS_NULL (address
))
2112 mreq
.imr_multiaddr
= ipaddress_handle_to_struct_in_addr (address
);
2114 field
= mono_class_get_field_from_name_full (obj_class
, "localAddress", NULL
);
2115 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2117 #ifdef HAVE_STRUCT_IP_MREQN
2118 if (!MONO_HANDLE_IS_NULL (address
))
2119 mreq
.imr_address
= ipaddress_handle_to_struct_in_addr (address
);
2121 field
= mono_class_get_field_from_name_full (obj_class
, "ifIndex", NULL
);
2122 mreq
.imr_ifindex
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, gint32
, field
);
2124 if (!MONO_HANDLE_IS_NULL (address
))
2125 mreq
.imr_interface
= ipaddress_handle_to_struct_in_addr (address
);
2126 #endif /* HAVE_STRUCT_IP_MREQN */
2128 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq
, sizeof (mreq
));
2132 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
2134 /* Cause an exception to be thrown */
2135 *werror
= WSAEINVAL
;
2138 } else if (!MONO_HANDLE_IS_NULL (byte_val
)) {
2139 int valsize
= mono_array_handle_length (byte_val
);
2141 guchar
*buf
= MONO_ARRAY_HANDLE_PIN (byte_val
, guchar
, 0, &gchandle
);
2144 case SocketOptionName_DontLinger
:
2146 linger
.l_onoff
= (*buf
) ? 0 : 1;
2147 linger
.l_linger
= 0;
2148 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2150 *werror
= WSAEINVAL
;
2154 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, buf
, valsize
);
2157 mono_gchandle_free_internal (gchandle
);
2159 /* ReceiveTimeout/SendTimeout get here */
2161 case SocketOptionName_DontLinger
:
2162 linger
.l_onoff
= !int_val
;
2163 linger
.l_linger
= 0;
2164 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2166 case SocketOptionName_MulticastInterface
:
2168 #ifdef HAVE_STRUCT_IP_MREQN
2169 int_val
= GUINT32_FROM_BE (int_val
);
2170 if ((int_val
& 0xff000000) == 0) {
2171 /* int_val is interface index */
2172 struct ip_mreqn mreq
= {{0}};
2173 mreq
.imr_ifindex
= int_val
;
2174 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq
, sizeof (mreq
));
2177 int_val
= GUINT32_TO_BE (int_val
);
2178 #endif /* HAVE_STRUCT_IP_MREQN */
2179 #endif /* HOST_WIN32 */
2180 /* int_val is in_addr */
2181 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &int_val
, sizeof (int_val
));
2183 case SocketOptionName_DontFragment
:
2184 #ifdef HAVE_IP_MTU_DISCOVER
2185 /* Fiddle with the value slightly if we're
2189 int_val
= IP_PMTUDISC_DO
;
2194 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &int_val
, sizeof (int_val
));
2198 if (ret
== SOCKET_ERROR
) {
2199 *werror
= mono_w32socket_get_last_error ();
2201 #ifdef HAVE_IP_MTU_DISCOVER
2202 if (system_name
== IP_MTU_DISCOVER
) {
2203 switch (system_level
) {
2204 case IP_PMTUDISC_DONT
:
2205 case IP_PMTUDISC_WANT
:
2206 case IP_PMTUDISC_DO
:
2207 #ifdef IP_PMTUDISC_PROBE
2208 case IP_PMTUDISC_PROBE
:
2210 #ifdef IP_PMTUDISC_INTERFACE
2211 case IP_PMTUDISC_INTERFACE
:
2213 #ifdef IP_PMTUDISC_OMIT
2214 case IP_PMTUDISC_OMIT
:
2217 * This happens if HAVE_IP_MTU_DISCOVER is set but the OS
2218 * doesn't actually understand it. The only OS that this is
2219 * known to happen on currently is Windows Subsystem for Linux
2220 * (newer versions have been fixed to recognize it). Just
2221 * pretend everything is fine.
2235 ves_icall_System_Net_Sockets_Socket_Shutdown_icall (gsize sock
, gint32 how
, gint32
*werror
)
2241 /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
2242 ret
= mono_w32socket_shutdown (sock
, how
);
2243 if (ret
== SOCKET_ERROR
)
2244 *werror
= mono_w32socket_get_last_error ();
2248 ves_icall_System_Net_Sockets_Socket_IOControl_icall (gsize sock
, gint32 code
, MonoArrayHandle input
, MonoArrayHandle output
, gint32
*werror
, MonoError
*error
)
2251 DWORD output_bytes
= 0;
2253 glong output_bytes
= 0;
2255 gchar
*i_buffer
, *o_buffer
;
2257 uint32_t i_gchandle
= 0;
2258 uint32_t o_gchandle
= 0;
2264 if ((guint32
)code
== FIONBIO
)
2265 /* Invalid command. Must use Socket.Blocking */
2268 if (MONO_HANDLE_IS_NULL (input
)) {
2273 i_len
= mono_array_handle_length (input
);
2274 i_buffer
= MONO_ARRAY_HANDLE_PIN (input
, gchar
, 0, &i_gchandle
);
2277 if (MONO_HANDLE_IS_NULL (output
)) {
2282 o_len
= mono_array_handle_length (output
);
2283 o_buffer
= MONO_ARRAY_HANDLE_PIN (output
, gchar
, 0, &o_gchandle
);
2286 ret
= mono_w32socket_ioctl (sock
, code
, i_buffer
, i_len
, o_buffer
, o_len
, &output_bytes
);
2288 mono_gchandle_free_internal (i_gchandle
);
2289 mono_gchandle_free_internal (o_gchandle
);
2291 if (ret
== SOCKET_ERROR
) {
2292 *werror
= mono_w32socket_get_last_error ();
2296 return (gint
)output_bytes
;
2300 addrinfo_add_string (MonoDomain
*domain
, const char *s
, MonoArrayHandle arr
, int index
, MonoError
*error
)
2302 HANDLE_FUNCTION_ENTER ();
2304 MonoStringHandle str
= mono_string_new_handle (domain
, s
, error
);
2305 goto_if_nok (error
, leave
);
2306 MONO_HANDLE_ARRAY_SETREF (arr
, index
, str
);
2308 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2313 addrinfo_add_local_ips (MonoDomain
*domain
, MonoArrayHandleOut h_addr_list
, MonoError
*error
)
2315 HANDLE_FUNCTION_ENTER ();
2316 struct in_addr
*local_in
= NULL
;
2318 struct in6_addr
*local_in6
= NULL
;
2323 local_in
= (struct in_addr
*) mono_get_local_interfaces (AF_INET
, &nlocal_in
);
2324 local_in6
= (struct in6_addr
*) mono_get_local_interfaces (AF_INET6
, &nlocal_in6
);
2325 if (nlocal_in
|| nlocal_in6
) {
2326 char addr
[INET6_ADDRSTRLEN
];
2327 MONO_HANDLE_ASSIGN (h_addr_list
, mono_array_new_handle (domain
, mono_get_string_class (), nlocal_in
+ nlocal_in6
, error
));
2328 goto_if_nok (error
, leave
);
2333 for (i
= 0; i
< nlocal_in
; i
++) {
2335 mono_address_init (&maddr
, AF_INET
, &local_in
[i
]);
2336 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2337 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2343 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2347 for (i
= 0; i
< nlocal_in6
; i
++) {
2349 mono_address_init (&maddr
, AF_INET6
, &local_in6
[i
]);
2350 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2351 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2363 HANDLE_FUNCTION_RETURN_VAL (addr_index
);
2367 addrinfo_to_IPHostEntry_handles (MonoAddressInfo
*info
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gboolean add_local_ips
, MonoError
*error
)
2369 HANDLE_FUNCTION_ENTER ();
2370 MonoAddressEntry
*ai
= NULL
;
2371 MonoDomain
*domain
= mono_domain_get ();
2374 MONO_HANDLE_ASSIGN (h_aliases
, mono_array_new_handle (domain
, mono_get_string_class (), 0, error
));
2375 goto_if_nok (error
, leave
);
2376 if (add_local_ips
) {
2377 int addr_index
= addrinfo_add_local_ips (domain
, h_addr_list
, error
);
2378 goto_if_nok (error
, leave
);
2385 for (ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2386 if (ai
->family
!= AF_INET
&& ai
->family
!= AF_INET6
)
2393 MONO_HANDLE_ASSIGN (h_addr_list
, mono_array_new_handle (domain
, mono_get_string_class (), count
, error
));
2394 goto_if_nok (error
, leave
);
2396 gboolean name_assigned
;
2397 name_assigned
= FALSE
;
2398 for (ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2400 char buffer
[INET6_ADDRSTRLEN
]; /* Max. size for IPv6 */
2402 if ((ai
->family
!= PF_INET
) && (ai
->family
!= PF_INET6
))
2405 mono_address_init (&maddr
, ai
->family
, &ai
->address
);
2406 const char *addr
= NULL
;
2407 if (mono_networking_addr_to_str (&maddr
, buffer
, sizeof (buffer
)))
2411 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2414 if (!name_assigned
) {
2415 name_assigned
= TRUE
;
2416 const char *name
= ai
->canonical_name
!= NULL
? ai
->canonical_name
: buffer
;
2417 MONO_HANDLE_ASSIGN (h_name
, mono_string_new_handle (domain
, name
, error
));
2418 goto_if_nok (error
, leave
);
2426 mono_free_address_info (info
);
2428 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2432 ves_icall_System_Net_Dns_GetHostByName (MonoStringHandle host
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gint32 hint
, MonoError
*error
)
2434 gboolean add_local_ips
= FALSE
, add_info_ok
= TRUE
;
2435 gchar this_hostname
[256];
2436 MonoAddressInfo
*info
= NULL
;
2440 char *hostname
= mono_string_handle_to_utf8 (host
, error
);
2441 return_val_if_nok (error
, FALSE
);
2443 if (*hostname
== '\0') {
2444 add_local_ips
= TRUE
;
2445 MONO_HANDLE_ASSIGN (h_name
, host
);
2448 if (!add_local_ips
&& gethostname (this_hostname
, sizeof (this_hostname
)) != -1) {
2449 if (!strcmp (hostname
, this_hostname
)) {
2450 add_local_ips
= TRUE
;
2451 MONO_HANDLE_ASSIGN (h_name
, host
);
2456 // Win32 APIs already returns local interface addresses for empty hostname ("")
2457 // so we never want to add them manually.
2458 add_local_ips
= FALSE
;
2459 if (mono_get_address_info(hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2460 add_info_ok
= FALSE
;
2462 if (*hostname
&& mono_get_address_info (hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2463 add_info_ok
= FALSE
;
2469 MonoBoolean result
= addrinfo_to_IPHostEntry_handles (info
, h_name
, h_aliases
, h_addr_list
, add_local_ips
, error
);
2476 ves_icall_System_Net_Dns_GetHostByAddr (MonoStringHandle addr
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gint32 hint
, MonoError
*error
)
2479 struct sockaddr_in saddr
;
2480 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2481 struct sockaddr_in6 saddr6
;
2483 MonoAddressInfo
*info
= NULL
;
2485 gchar hostname
[NI_MAXHOST
] = { 0 };
2490 address
= mono_string_handle_to_utf8 (addr
, error
);
2491 return_val_if_nok (error
, FALSE
);
2493 if (inet_pton (AF_INET
, address
, &saddr
.sin_addr
) == 1) {
2495 saddr
.sin_family
= AF_INET
;
2497 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2498 else if (inet_pton (AF_INET6
, address
, &saddr6
.sin6_addr
) == 1) {
2500 saddr6
.sin6_family
= AF_INET6
;
2512 #if HAVE_SOCKADDR_IN_SIN_LEN
2513 saddr
.sin_len
= sizeof (saddr
);
2516 ret
= getnameinfo ((struct sockaddr
*)&saddr
, sizeof (saddr
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2520 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2522 #if HAVE_SOCKADDR_IN6_SIN_LEN
2523 saddr6
.sin6_len
= sizeof (saddr6
);
2526 ret
= getnameinfo ((struct sockaddr
*)&saddr6
, sizeof (saddr6
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2532 g_assert_not_reached ();
2538 if (mono_get_address_info (hostname
, 0, hint
| MONO_HINT_CANONICAL_NAME
| MONO_HINT_CONFIGURED_ONLY
, &info
) != 0)
2541 MonoBoolean result
= addrinfo_to_IPHostEntry_handles (info
, h_name
, h_aliases
, h_addr_list
, FALSE
, error
);
2546 ves_icall_System_Net_Dns_GetHostName (MonoStringHandleOut h_name
, MonoError
*error
)
2548 gchar hostname
[NI_MAXHOST
] = { 0 };
2553 ret
= gethostname (hostname
, sizeof (hostname
));
2558 MONO_HANDLE_ASSIGN (h_name
, mono_string_new_handle (mono_domain_get (), hostname
, error
));
2562 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
2565 ves_icall_System_Net_Sockets_Socket_SendFile_icall (gsize sock
, MonoStringHandle filename
, MonoArrayHandle pre_buffer
, MonoArrayHandle post_buffer
, gint flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
2569 TRANSMIT_FILE_BUFFERS buffers
;
2570 uint32_t pre_buffer_gchandle
= 0;
2571 uint32_t post_buffer_gchandle
= 0;
2576 if (MONO_HANDLE_IS_NULL (filename
))
2579 /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
2581 uint32_t filename_gchandle
;
2582 gunichar2
*filename_chars
= mono_string_handle_pin_chars (filename
, &filename_gchandle
);
2583 file
= mono_w32file_create (filename_chars
, GENERIC_READ
, FILE_SHARE_READ
, OPEN_EXISTING
, 0);
2584 mono_gchandle_free_internal (filename_gchandle
);
2585 if (file
== INVALID_HANDLE_VALUE
) {
2586 *werror
= mono_w32error_get_last ();
2590 memset (&buffers
, 0, sizeof (buffers
));
2591 if (!MONO_HANDLE_IS_NULL (pre_buffer
)) {
2592 buffers
.Head
= MONO_ARRAY_HANDLE_PIN (pre_buffer
, guchar
, 0, &pre_buffer_gchandle
);
2593 buffers
.HeadLength
= mono_array_handle_length (pre_buffer
);
2595 if (!MONO_HANDLE_IS_NULL (post_buffer
)) {
2596 buffers
.Tail
= MONO_ARRAY_HANDLE_PIN (post_buffer
, guchar
, 0, &post_buffer_gchandle
);
2597 buffers
.TailLength
= mono_array_handle_length (post_buffer
);
2600 ret
= mono_w32socket_transmit_file (sock
, file
, &buffers
, flags
, blocking
);
2602 if (pre_buffer_gchandle
)
2603 mono_gchandle_free_internal (pre_buffer_gchandle
);
2604 if (post_buffer_gchandle
)
2605 mono_gchandle_free_internal (post_buffer_gchandle
);
2608 *werror
= mono_w32socket_get_last_error ();
2610 mono_w32file_close (file
);
2618 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
2621 mono_network_init (void)
2623 mono_networking_init ();
2624 mono_w32socket_initialize ();
2628 mono_network_cleanup (void)
2630 mono_w32socket_cleanup ();
2631 mono_networking_shutdown ();
2635 ves_icall_cancel_blocking_socket_operation (MonoThreadObjectHandle thread
, MonoError
*error
)
2638 MonoInternalThreadHandle internal
= MONO_HANDLE_NEW_GET (MonoInternalThread
, thread
, internal_thread
);
2639 g_assert (!MONO_HANDLE_IS_NULL (internal
));
2641 guint64 tid
= mono_internal_thread_handle_ptr (internal
)->tid
;
2642 mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (tid
));
2648 mono_network_init (void)
2653 mono_network_cleanup (void)
2657 #endif // !defined(DISABLE_SOCKETS) && !defined(ENABLE_NETCORE)