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 #ifndef DISABLE_SOCKETS
21 #if defined(__APPLE__) || defined(__FreeBSD__)
22 #define __APPLE_USE_RFC_3542
31 #include <sys/socket.h>
32 #ifdef HAVE_SYS_IOCTL_H
33 #include <sys/ioctl.h>
35 #include <netinet/in.h>
36 #include <netinet/tcp.h>
40 #ifdef HAVE_NETINET_TCP_H
41 #include <arpa/inet.h>
48 #include <mono/utils/mono-errno.h>
50 #include <sys/types.h>
52 #include <mono/metadata/object.h>
53 #include <mono/metadata/exception.h>
54 #include <mono/metadata/assembly-internals.h>
55 #include <mono/metadata/appdomain.h>
56 #include <mono/metadata/w32file.h>
57 #include <mono/metadata/threads.h>
58 #include <mono/metadata/threads-types.h>
59 #include <mono/metadata/threadpool-io.h>
60 #include <mono/utils/mono-poll.h>
61 /* FIXME change this code to not mess so much with the internals */
62 #include <mono/metadata/class-internals.h>
63 #include <mono/metadata/domain-internals.h>
64 #include <mono/metadata/image-internals.h>
65 #include <mono/utils/mono-threads.h>
66 #include <mono/utils/mono-memory-model.h>
67 #include <mono/utils/networking.h>
68 #include <mono/metadata/w32handle.h>
69 #include <mono/metadata/w32socket.h>
70 #include <mono/metadata/w32socket-internals.h>
71 #include <mono/metadata/w32error.h>
74 #ifdef HAVE_SYS_TIME_H
77 #ifdef HAVE_SYS_IOCTL_H
78 #include <sys/ioctl.h>
87 #ifdef HAVE_SYS_FILIO_H
88 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
90 #ifdef HAVE_SYS_SOCKIO_H
91 #include <sys/sockio.h> /* defines SIOCATMARK */
97 #ifdef HAVE_GETIFADDRS
98 // <net/if.h> must be included before <ifaddrs.h>
102 #if defined(_MSC_VER) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
105 #include "icall-decl.h"
107 #define LOGDEBUG(...)
108 /* define LOGDEBUG(...) g_message(__VA_ARGS__) */
111 addrinfo_to_IPHostEntry_handles (MonoAddressInfo
*info
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gboolean add_local_ips
, MonoError
*error
);
113 static MonoObjectHandle
114 create_object_handle_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
);
116 static struct sockaddr
*
117 create_sockaddr_from_handle (MonoObjectHandle saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
);
122 mono_w32socket_socket (int domain
, int type
, int protocol
)
126 ret
= WSASocket (domain
, type
, protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
);
132 mono_w32socket_bind (SOCKET sock
, struct sockaddr
*addr
, socklen_t addrlen
)
136 ret
= bind (sock
, addr
, addrlen
);
142 mono_w32socket_getpeername (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
146 ret
= getpeername (sock
, name
, namelen
);
152 mono_w32socket_getsockname (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
156 ret
= getsockname (sock
, name
, namelen
);
162 mono_w32socket_getsockopt (SOCKET sock
, gint level
, gint optname
, gpointer optval
, socklen_t
*optlen
)
166 ret
= getsockopt (sock
, level
, optname
, (char*)optval
, optlen
);
172 mono_w32socket_setsockopt (SOCKET sock
, gint level
, gint optname
, gconstpointer optval
, socklen_t optlen
)
176 ret
= setsockopt (sock
, level
, optname
, (const char*)optval
, optlen
);
182 mono_w32socket_listen (SOCKET sock
, gint backlog
)
186 ret
= listen (sock
, backlog
);
192 mono_w32socket_shutdown (SOCKET sock
, gint how
)
196 ret
= shutdown (sock
, how
);
202 mono_w32socket_ioctl (SOCKET sock
, gint32 command
, gchar
*input
, gint inputlen
, gchar
*output
, gint outputlen
, DWORD
*written
)
206 ret
= WSAIoctl (sock
, command
, input
, inputlen
, output
, outputlen
, written
, NULL
, NULL
);
212 mono_w32socket_close (SOCKET sock
)
216 ret
= closesocket (sock
);
221 #endif /* HOST_WIN32 */
224 convert_family (MonoAddressFamily mono_family
)
226 switch (mono_family
) {
227 case AddressFamily_Unknown
:
228 case AddressFamily_ImpLink
:
229 case AddressFamily_Pup
:
230 case AddressFamily_Chaos
:
231 case AddressFamily_Iso
:
232 case AddressFamily_Ecma
:
233 case AddressFamily_DataKit
:
234 case AddressFamily_Ccitt
:
235 case AddressFamily_DataLink
:
236 case AddressFamily_Lat
:
237 case AddressFamily_HyperChannel
:
238 case AddressFamily_NetBios
:
239 case AddressFamily_VoiceView
:
240 case AddressFamily_FireFox
:
241 case AddressFamily_Banyan
:
242 case AddressFamily_Atm
:
243 case AddressFamily_Cluster
:
244 case AddressFamily_Ieee12844
:
245 case AddressFamily_NetworkDesigners
:
246 g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family
);
248 case AddressFamily_Unspecified
:
250 case AddressFamily_Unix
:
252 case AddressFamily_InterNetwork
:
254 case AddressFamily_AppleTalk
:
260 case AddressFamily_InterNetworkV6
:
261 #ifdef HAVE_STRUCT_SOCKADDR_IN6
266 case AddressFamily_DecNet
:
272 case AddressFamily_Ipx
:
278 case AddressFamily_Sna
:
284 case AddressFamily_Irda
:
291 g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family
);
296 static MonoAddressFamily
297 convert_to_mono_family (guint16 af_family
)
301 return AddressFamily_Unspecified
;
303 return AddressFamily_Unix
;
305 return AddressFamily_InterNetwork
;
308 return AddressFamily_Ipx
;
312 return AddressFamily_Sna
;
316 return AddressFamily_DecNet
;
320 return AddressFamily_AppleTalk
;
322 #ifdef HAVE_STRUCT_SOCKADDR_IN6
324 return AddressFamily_InterNetworkV6
;
328 return AddressFamily_Irda
;
331 g_warning ("unknown address family 0x%x", af_family
);
332 return AddressFamily_Unknown
;
337 convert_type (MonoSocketType mono_type
)
340 case SocketType_Stream
:
342 case SocketType_Dgram
:
352 case SocketType_Seqpacket
:
353 #ifdef SOCK_SEQPACKET
354 return SOCK_SEQPACKET
;
358 case SocketType_Unknown
:
359 g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type
);
362 g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type
);
368 convert_proto (MonoProtocolType mono_proto
)
370 switch (mono_proto
) {
371 case ProtocolType_IP
:
372 case ProtocolType_IPv6
:
373 case ProtocolType_Icmp
:
374 case ProtocolType_Igmp
:
375 case ProtocolType_Ggp
:
376 case ProtocolType_Tcp
:
377 case ProtocolType_Pup
:
378 case ProtocolType_Udp
:
379 case ProtocolType_Idp
:
380 /* These protocols are known (on my system at least) */
382 case ProtocolType_ND
:
383 case ProtocolType_Raw
:
384 case ProtocolType_Ipx
:
385 case ProtocolType_Spx
:
386 case ProtocolType_SpxII
:
387 case ProtocolType_Unknown
:
388 /* These protocols arent */
389 g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto
);
396 /* Convert MonoSocketFlags */
398 convert_socketflags (gint32 sflags
)
403 /* SocketFlags.None */
406 if (sflags
& ~(SocketFlags_OutOfBand
| SocketFlags_MaxIOVectorLength
| SocketFlags_Peek
|
407 SocketFlags_DontRoute
| SocketFlags_Partial
))
408 /* Contains invalid flag values */
412 if (sflags
& SocketFlags_OutOfBand
)
415 if (sflags
& SocketFlags_Peek
)
417 if (sflags
& SocketFlags_DontRoute
)
418 flags
|= MSG_DONTROUTE
;
420 /* Ignore Partial - see bug 349688. Don't return -1, because
421 * according to the comment in that bug ms runtime doesn't for
422 * UDP sockets (this means we will silently ignore it for TCP
426 if (sflags
& SocketFlags_Partial
)
430 /* Don't do anything for MaxIOVectorLength */
431 if (sflags
& SocketFlags_MaxIOVectorLength
)
439 * 0 on success (mapped mono_level and mono_name to system_level and system_name
441 * -2 on non-fatal error (ie, must ignore)
444 convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level
, MonoSocketOptionName mono_name
, int *system_level
, int *system_name
)
446 switch (mono_level
) {
447 case SocketOptionLevel_Socket
:
448 *system_level
= SOL_SOCKET
;
451 case SocketOptionName_DontLinger
:
452 /* This is SO_LINGER, because the setsockopt
453 * internal call maps DontLinger to SO_LINGER
456 *system_name
= SO_LINGER
;
459 case SocketOptionName_Debug
:
460 *system_name
= SO_DEBUG
;
464 case SocketOptionName_AcceptConnection
:
465 *system_name
= SO_ACCEPTCONN
;
468 case SocketOptionName_ReuseAddress
:
469 *system_name
= SO_REUSEADDR
;
471 case SocketOptionName_KeepAlive
:
472 *system_name
= SO_KEEPALIVE
;
475 case SocketOptionName_DontRoute
:
476 *system_name
= SO_DONTROUTE
;
479 case SocketOptionName_Broadcast
:
480 *system_name
= SO_BROADCAST
;
482 case SocketOptionName_Linger
:
483 *system_name
= SO_LINGER
;
486 case SocketOptionName_OutOfBandInline
:
487 *system_name
= SO_OOBINLINE
;
490 case SocketOptionName_SendBuffer
:
491 *system_name
= SO_SNDBUF
;
493 case SocketOptionName_ReceiveBuffer
:
494 *system_name
= SO_RCVBUF
;
496 case SocketOptionName_SendLowWater
:
497 *system_name
= SO_SNDLOWAT
;
499 case SocketOptionName_ReceiveLowWater
:
500 *system_name
= SO_RCVLOWAT
;
502 case SocketOptionName_SendTimeout
:
503 *system_name
= SO_SNDTIMEO
;
505 case SocketOptionName_ReceiveTimeout
:
506 *system_name
= SO_RCVTIMEO
;
508 case SocketOptionName_Error
:
509 *system_name
= SO_ERROR
;
511 case SocketOptionName_Type
:
512 *system_name
= SO_TYPE
;
515 case SocketOptionName_PeerCred
:
516 *system_name
= SO_PEERCRED
;
519 case SocketOptionName_ExclusiveAddressUse
:
520 #ifdef SO_EXCLUSIVEADDRUSE
521 *system_name
= SO_EXCLUSIVEADDRUSE
;
524 case SocketOptionName_UseLoopback
:
525 #ifdef SO_USELOOPBACK
526 *system_name
= SO_USELOOPBACK
;
529 case SocketOptionName_MaxConnections
:
531 *system_name
= SO_MAXCONN
;
533 #elif defined(SOMAXCONN)
534 *system_name
= SOMAXCONN
;
538 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name
);
543 case SocketOptionLevel_IP
:
544 *system_level
= mono_networking_get_ip_protocol ();
548 case SocketOptionName_IPOptions
:
549 *system_name
= IP_OPTIONS
;
553 case SocketOptionName_HeaderIncluded
:
554 *system_name
= IP_HDRINCL
;
558 case SocketOptionName_TypeOfService
:
559 *system_name
= IP_TOS
;
563 case SocketOptionName_IpTimeToLive
:
564 *system_name
= IP_TTL
;
567 case SocketOptionName_MulticastInterface
:
568 *system_name
= IP_MULTICAST_IF
;
570 case SocketOptionName_MulticastTimeToLive
:
571 *system_name
= IP_MULTICAST_TTL
;
573 case SocketOptionName_MulticastLoopback
:
574 *system_name
= IP_MULTICAST_LOOP
;
576 case SocketOptionName_AddMembership
:
577 *system_name
= IP_ADD_MEMBERSHIP
;
579 case SocketOptionName_DropMembership
:
580 *system_name
= IP_DROP_MEMBERSHIP
;
582 #ifdef HAVE_IP_PKTINFO
583 case SocketOptionName_PacketInformation
:
584 *system_name
= IP_PKTINFO
;
586 #endif /* HAVE_IP_PKTINFO */
588 case SocketOptionName_DontFragment
:
589 #ifdef HAVE_IP_DONTFRAGMENT
590 *system_name
= IP_DONTFRAGMENT
;
592 #elif defined HAVE_IP_MTU_DISCOVER
593 /* Not quite the same */
594 *system_name
= IP_MTU_DISCOVER
;
597 /* If the flag is not available on this system, we can ignore this error */
599 #endif /* HAVE_IP_DONTFRAGMENT */
600 case SocketOptionName_AddSourceMembership
:
601 case SocketOptionName_DropSourceMembership
:
602 case SocketOptionName_BlockSource
:
603 case SocketOptionName_UnblockSource
:
604 /* Can't figure out how to map these, so fall
608 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name
);
613 case SocketOptionLevel_IPv6
:
614 *system_level
= mono_networking_get_ipv6_protocol ();
617 case SocketOptionName_IpTimeToLive
:
618 case SocketOptionName_HopLimit
:
619 *system_name
= IPV6_UNICAST_HOPS
;
621 case SocketOptionName_MulticastInterface
:
622 *system_name
= IPV6_MULTICAST_IF
;
624 case SocketOptionName_MulticastTimeToLive
:
625 *system_name
= IPV6_MULTICAST_HOPS
;
627 case SocketOptionName_MulticastLoopback
:
628 *system_name
= IPV6_MULTICAST_LOOP
;
630 case SocketOptionName_AddMembership
:
631 *system_name
= IPV6_JOIN_GROUP
;
633 case SocketOptionName_DropMembership
:
634 *system_name
= IPV6_LEAVE_GROUP
;
636 case SocketOptionName_IPv6Only
:
638 *system_name
= IPV6_V6ONLY
;
643 case SocketOptionName_PacketInformation
:
644 #ifdef HAVE_IPV6_PKTINFO
645 *system_name
= IPV6_PKTINFO
;
648 case SocketOptionName_HeaderIncluded
:
649 case SocketOptionName_IPOptions
:
650 case SocketOptionName_TypeOfService
:
651 case SocketOptionName_DontFragment
:
652 case SocketOptionName_AddSourceMembership
:
653 case SocketOptionName_DropSourceMembership
:
654 case SocketOptionName_BlockSource
:
655 case SocketOptionName_UnblockSource
:
656 /* Can't figure out how to map these, so fall
660 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name
);
663 break; /* SocketOptionLevel_IPv6 */
665 case SocketOptionLevel_Tcp
:
666 *system_level
= mono_networking_get_tcp_protocol ();
669 case SocketOptionName_NoDelay
:
670 *system_name
= TCP_NODELAY
;
673 /* The documentation is talking complete
674 * bollocks here: rfc-1222 is titled
675 * 'Advancing the NSFNET Routing Architecture'
676 * and doesn't mention either of the words
677 * "expedite" or "urgent".
679 case SocketOptionName_BsdUrgent
:
680 case SocketOptionName_Expedited
:
683 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name
);
688 case SocketOptionLevel_Udp
:
689 g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level
);
692 case SocketOptionName_NoChecksum
:
693 case SocketOptionName_ChecksumCoverage
:
695 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name
);
702 g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level
);
710 get_socket_assembly (void)
712 MonoDomain
*domain
= mono_domain_get ();
714 if (domain
->socket_assembly
== NULL
) {
715 MonoImage
*socket_assembly
;
717 socket_assembly
= mono_image_loaded_internal ("System", FALSE
);
718 if (!socket_assembly
) {
719 MonoAssemblyOpenRequest req
;
720 mono_assembly_request_prepare (&req
.request
, sizeof (req
), MONO_ASMCTX_DEFAULT
);
721 MonoAssembly
*sa
= mono_assembly_request_open ("System.dll", &req
, NULL
);
724 g_assert_not_reached ();
726 socket_assembly
= mono_assembly_get_image_internal (sa
);
729 mono_atomic_store_release (&domain
->socket_assembly
, socket_assembly
);
732 return domain
->socket_assembly
;
736 ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObjectHandle this_obj
, gint32 family
, gint32 type
, gint32 proto
, gint32
*werror
, MonoError
*error
)
746 sock_family
= convert_family ((MonoAddressFamily
)family
);
747 if (sock_family
== -1) {
748 *werror
= WSAEAFNOSUPPORT
;
752 sock_proto
= convert_proto ((MonoProtocolType
)proto
);
753 if (sock_proto
== -1) {
754 *werror
= WSAEPROTONOSUPPORT
;
758 sock_type
= convert_type ((MonoSocketType
)type
);
759 if (sock_type
== -1) {
760 *werror
= WSAESOCKTNOSUPPORT
;
764 sock
= mono_w32socket_socket (sock_family
, sock_type
, sock_proto
);
766 if (sock
== INVALID_SOCKET
) {
767 *werror
= mono_w32socket_get_last_error ();
771 return GUINT_TO_POINTER (sock
);
774 /* FIXME: the SOCKET parameter (here and in other functions in this
775 * file) is really an IntPtr which needs to be converted to a guint32.
778 ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock
, gint32
*werror
, MonoError
*error
)
780 LOGDEBUG (g_message ("%s: closing 0x%x", __func__
, sock
));
785 /* Clear any pending work item from this socket if the underlying
786 * polling system does not notify when the socket is closed */
787 mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock
));
789 mono_w32socket_close ((SOCKET
) sock
);
793 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void)
795 LOGDEBUG (g_message("%s: returning %d", __func__
, mono_w32socket_get_last_error ()));
797 return mono_w32socket_get_last_error ();
801 ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock
, gint32
*werror
, MonoError
*error
)
809 /* FIXME: this might require amount to be unsigned long. */
810 ret
= mono_w32socket_get_available (sock
, &amount
);
811 if (ret
== SOCKET_ERROR
) {
812 *werror
= mono_w32socket_get_last_error ();
820 ves_icall_System_Net_Sockets_Socket_Blocking_internal (gsize sock
, MonoBoolean block
, gint32
*werror
, MonoError
*error
)
827 ret
= mono_w32socket_set_blocking (sock
, block
);
828 if (ret
== SOCKET_ERROR
)
829 *werror
= mono_w32socket_get_last_error ();
833 ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
840 newsock
= mono_w32socket_accept (sock
, NULL
, 0, blocking
);
841 if (newsock
== INVALID_SOCKET
) {
842 *werror
= mono_w32socket_get_last_error ();
846 return GUINT_TO_POINTER (newsock
);
850 ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock
, guint32 backlog
, gint32
*werror
, MonoError
*error
)
857 ret
= mono_w32socket_listen (sock
, backlog
);
858 if (ret
== SOCKET_ERROR
)
859 *werror
= mono_w32socket_get_last_error ();
862 #ifdef HAVE_STRUCT_SOCKADDR_IN6
863 // Check whether it's ::ffff::0:0.
865 is_ipv4_mapped_any (const struct in6_addr
*addr
)
869 for (i
= 0; i
< 10; i
++) {
870 if (addr
->s6_addr
[i
])
873 if ((addr
->s6_addr
[10] != 0xff) || (addr
->s6_addr
[11] != 0xff))
875 for (i
= 12; i
< 16; i
++) {
876 if (addr
->s6_addr
[i
])
883 static MonoObjectHandle
884 create_object_handle_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
)
886 MonoDomain
*domain
= mono_domain_get ();
887 MonoAddressFamily family
;
891 /* Build a System.Net.SocketAddress object instance */
892 if (!domain
->sockaddr_class
)
893 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
894 MonoObjectHandle sockaddr_obj
= mono_object_new_handle (domain
, domain
->sockaddr_class
, error
);
895 return_val_if_nok (error
, MONO_HANDLE_NEW (MonoObject
, NULL
));
897 /* Locate the SocketAddress data buffer in the object */
898 if (!domain
->sockaddr_data_field
) {
899 domain
->sockaddr_data_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Buffer", NULL
);
900 g_assert (domain
->sockaddr_data_field
);
903 /* Locate the SocketAddress data buffer length in the object */
904 if (!domain
->sockaddr_data_length_field
) {
905 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Size", NULL
);
906 g_assert (domain
->sockaddr_data_length_field
);
909 /* May be the +2 here is too conservative, as sa_len returns
910 * the length of the entire sockaddr_in/in6, including
911 * sizeof (unsigned short) of the family */
912 /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
913 MonoArrayHandle data
= mono_array_new_handle (domain
, mono_get_byte_class (), sa_size
+ 2, error
);
914 return_val_if_nok (error
, MONO_HANDLE_NEW (MonoObject
, NULL
));
916 /* The data buffer is laid out as follows:
917 * bytes 0 and 1 are the address family
918 * bytes 2 and 3 are the port info
919 * the rest is the address info
922 family
= convert_to_mono_family (saddr
->sa_family
);
923 if (family
== AddressFamily_Unknown
) {
924 *werror
= WSAEAFNOSUPPORT
;
925 return MONO_HANDLE_NEW (MonoObject
, NULL
);
928 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 0, family
& 0x0FF);
929 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 1, (family
>> 8) & 0x0FF);
931 if (saddr
->sa_family
== AF_INET
) {
932 struct sockaddr_in
*sa_in
= (struct sockaddr_in
*)saddr
;
933 guint16 port
= ntohs (sa_in
->sin_port
);
934 guint32 address
= ntohl (sa_in
->sin_addr
.s_addr
);
937 if (sa_size
< buffer_size
) {
938 mono_error_set_generic_error (error
, "System", "SystemException", "");
939 return MONO_HANDLE_NEW (MonoObject
, NULL
);
942 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 2, (port
>>8) & 0xff);
943 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 3, (port
) & 0xff);
944 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 4, (address
>>24) & 0xff);
945 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 5, (address
>>16) & 0xff);
946 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 6, (address
>>8) & 0xff);
947 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 7, (address
) & 0xff);
949 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 */
950 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 */
954 #ifdef HAVE_STRUCT_SOCKADDR_IN6
955 else if (saddr
->sa_family
== AF_INET6
) {
956 struct sockaddr_in6
*sa_in
= (struct sockaddr_in6
*)saddr
;
958 int buffer_size
= 28;
960 guint16 port
= ntohs (sa_in
->sin6_port
);
962 if (sa_size
< buffer_size
) {
963 mono_error_set_generic_error (error
, "System", "SystemException", "");
964 return MONO_HANDLE_NEW (MonoObject
, NULL
);
967 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 2, (port
>>8) & 0xff);
968 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 3, (port
) & 0xff);
970 if (is_ipv4_mapped_any (&sa_in
->sin6_addr
)) {
971 // Map ::ffff:0:0 to :: (bug #5502)
972 for (i
= 0; i
< 16; i
++)
973 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 8 + i
, 0);
975 for (i
= 0; i
< 16; i
++) {
976 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 8 + i
,
977 sa_in
->sin6_addr
.s6_addr
[i
]);
981 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 24, sa_in
->sin6_scope_id
& 0xff);
982 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 25,
983 (sa_in
->sin6_scope_id
>> 8) & 0xff);
984 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 26,
985 (sa_in
->sin6_scope_id
>> 16) & 0xff);
986 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 27,
987 (sa_in
->sin6_scope_id
>> 24) & 0xff);
989 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 */
990 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 */
996 else if (saddr
->sa_family
== AF_UNIX
) {
998 int buffer_size
= sa_size
+ 2;
1000 for (i
= 0; i
< sa_size
; i
++)
1001 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, i
+ 2, saddr
->sa_data
[i
]);
1003 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 */
1004 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 */
1006 return sockaddr_obj
;
1010 *werror
= WSAEAFNOSUPPORT
;
1011 return MONO_HANDLE_NEW (MonoObject
, NULL
);
1016 get_sockaddr_size (int family
)
1021 if (family
== AF_INET
) {
1022 size
= sizeof (struct sockaddr_in
);
1024 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1025 else if (family
== AF_INET6
) {
1026 size
= sizeof (struct sockaddr_in6
);
1029 #ifdef HAVE_SYS_UN_H
1030 else if (family
== AF_UNIX
) {
1031 size
= sizeof (struct sockaddr_un
);
1037 static MonoObjectHandle
1038 mono_w32socket_getname (gsize sock
, gint32 af
, gboolean local
, gint32
*werror
, MonoError
*error
)
1041 socklen_t salen
= 0;
1043 MonoObjectHandle result
= NULL_HANDLE
;
1047 salen
= get_sockaddr_size (convert_family ((MonoAddressFamily
)af
));
1049 *werror
= WSAEAFNOSUPPORT
;
1053 sa
= g_alloca (salen
);
1054 memset (sa
, 0, salen
);
1056 sa
= g_malloc0 (salen
);
1059 /* Note: linux returns just 2 for AF_UNIX. Always. */
1060 ret
= (local
? mono_w32socket_getsockname
: mono_w32socket_getpeername
) (sock
, (struct sockaddr
*)sa
, &salen
);
1061 if (ret
== SOCKET_ERROR
) {
1062 *werror
= mono_w32socket_get_last_error ();
1066 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
)));
1068 result
= create_object_handle_from_sockaddr ((struct sockaddr
*)sa
, salen
, werror
, error
);
1076 ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock
, gint32 af
, gint32
*werror
, MonoError
*error
)
1078 return mono_w32socket_getname (sock
, af
, TRUE
, werror
, error
);
1082 ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock
, gint32 af
, gint32
*werror
, MonoError
*error
)
1084 return mono_w32socket_getname (sock
, af
, FALSE
, werror
, error
);
1087 static struct sockaddr
*
1088 create_sockaddr_from_handle (MonoObjectHandle saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
)
1090 MonoDomain
*domain
= mono_domain_get ();
1096 if (!domain
->sockaddr_class
)
1097 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
1099 /* Locate the SocketAddress data buffer in the object */
1100 if (!domain
->sockaddr_data_field
) {
1101 domain
->sockaddr_data_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Buffer", NULL
);
1102 g_assert (domain
->sockaddr_data_field
);
1105 /* Locate the SocketAddress data buffer length in the object */
1106 if (!domain
->sockaddr_data_length_field
) {
1107 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Size", NULL
);
1108 g_assert (domain
->sockaddr_data_length_field
);
1111 MonoArrayHandle data
= MONO_HANDLE_NEW_GET_FIELD (saddr_obj
, MonoArray
, domain
->sockaddr_data_field
);
1113 /* The data buffer is laid out as follows:
1114 * byte 0 is the address family low byte
1115 * byte 1 is the address family high byte
1117 * bytes 2 and 3 are the port info
1118 * the rest is the address info
1120 * the rest is the file name
1122 len
= MONO_HANDLE_GET_FIELD_VAL (saddr_obj
, int, domain
->sockaddr_data_length_field
);
1123 g_assert (len
>= 2);
1126 guint8
*buf
= MONO_ARRAY_HANDLE_PIN (data
, guint8
, 0, &gchandle
);
1127 family
= convert_family ((MonoAddressFamily
)(buf
[0] + (buf
[1] << 8)));
1128 if (family
== AF_INET
) {
1129 struct sockaddr_in
*sa
;
1134 mono_error_set_generic_error (error
, "System", "SystemException", "");
1135 mono_gchandle_free_internal (gchandle
);
1139 sa
= g_new0 (struct sockaddr_in
, 1);
1140 port
= (buf
[2] << 8) + buf
[3];
1141 address
= (buf
[4] << 24) + (buf
[5] << 16) + (buf
[6] << 8) + buf
[7];
1143 sa
->sin_family
= family
;
1144 sa
->sin_addr
.s_addr
= htonl (address
);
1145 sa
->sin_port
= htons (port
);
1147 *sa_size
= sizeof (struct sockaddr_in
);
1148 mono_gchandle_free_internal (gchandle
);
1149 return (struct sockaddr
*)sa
;
1151 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1152 else if (family
== AF_INET6
) {
1153 struct sockaddr_in6
*sa
;
1159 mono_error_set_generic_error (error
, "System", "SystemException", "");
1160 mono_gchandle_free_internal (gchandle
);
1164 sa
= g_new0 (struct sockaddr_in6
, 1);
1165 port
= buf
[3] + (buf
[2] << 8);
1166 scopeid
= buf
[24] + (buf
[25] << 8) + (buf
[26] << 16) + (buf
[27] << 24);
1168 sa
->sin6_family
= family
;
1169 sa
->sin6_port
= htons (port
);
1170 sa
->sin6_scope_id
= scopeid
;
1172 for (i
= 0; i
< 16; i
++)
1173 sa
->sin6_addr
.s6_addr
[i
] = buf
[8 + i
];
1175 *sa_size
= sizeof (struct sockaddr_in6
);
1176 mono_gchandle_free_internal (gchandle
);
1177 return (struct sockaddr
*)sa
;
1180 #ifdef HAVE_SYS_UN_H
1181 else if (family
== AF_UNIX
) {
1182 struct sockaddr_un
*sock_un
;
1185 /* Need a byte for the '\0' terminator/prefix, and the first
1186 * two bytes hold the SocketAddress family
1188 if (len
- 2 >= sizeof (sock_un
->sun_path
)) {
1189 mono_error_set_argument_out_of_range (error
, "SocketAddress.Size");
1190 mono_gchandle_free_internal (gchandle
);
1194 sock_un
= g_new0 (struct sockaddr_un
, 1);
1196 sock_un
->sun_family
= family
;
1197 for (i
= 0; i
< len
- 2; i
++)
1198 sock_un
->sun_path
[i
] = buf
[i
+ 2];
1201 mono_gchandle_free_internal (gchandle
);
1202 return (struct sockaddr
*)sock_un
;
1206 *werror
= WSAEAFNOSUPPORT
;
1207 mono_gchandle_free_internal (gchandle
);
1213 ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoError
*error
)
1215 struct sockaddr
*sa
;
1222 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1225 return_if_nok (error
);
1227 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
)));
1229 ret
= mono_w32socket_bind (sock
, sa
, sa_size
);
1231 if (ret
== SOCKET_ERROR
)
1232 *werror
= mono_w32socket_get_last_error ();
1244 ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock
, gint mode
,
1245 gint timeout
, gint32
*werror
, MonoError
*error
)
1247 MonoInternalThread
*thread
= mono_thread_internal_current ();
1256 pfds
= g_new0 (mono_pollfd
, 1);
1257 pfds
->fd
= GPOINTER_TO_INT (sock
);
1260 case SelectModeRead
:
1261 pfds
->events
= MONO_POLLIN
;
1263 case SelectModeWrite
:
1264 pfds
->events
= MONO_POLLOUT
;
1267 pfds
->events
= MONO_POLLERR
| MONO_POLLHUP
| MONO_POLLNVAL
;
1271 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1273 start
= time (NULL
);
1278 ret
= mono_poll (pfds
, 1, timeout
);
1282 if (timeout
> 0 && ret
< 0) {
1284 int sec
= time (NULL
) - start
;
1286 timeout
= rtimeout
- sec
* 1000;
1291 mono_set_errno (err
);
1294 if (ret
== -1 && errno
== EINTR
) {
1295 if (mono_thread_test_state (thread
, ThreadState_AbortRequested
)) {
1300 /* Suspend requested? */
1301 mono_thread_interruption_checkpoint_void ();
1303 mono_set_errno (EINTR
);
1305 } while (ret
== -1 && errno
== EINTR
);
1308 *werror
= mono_w32socket_convert_error (errno
);
1318 ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1320 struct sockaddr
*sa
;
1327 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1330 return_if_nok (error
);
1332 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
)));
1334 ret
= mono_w32socket_connect (sock
, sa
, sa_size
, blocking
);
1335 if (ret
== SOCKET_ERROR
)
1336 *werror
= mono_w32socket_get_last_error ();
1341 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
1344 ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock
, MonoBoolean reuse
, gint32
*werror
, MonoError
*error
)
1348 LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__
, sock
, reuse
));
1350 *werror
= mono_w32socket_disconnect (sock
, reuse
);
1352 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
1355 ves_icall_System_Net_Sockets_Socket_Duplicate_internal (gpointer handle
, gint32 targetProcessId
, gpointer
*duplicate_handle
, gint32
*werror
, MonoError
*error
)
1360 if (!mono_w32socket_duplicate (handle
, targetProcessId
, duplicate_handle
)) {
1361 *werror
= mono_w32error_get_last ();
1369 ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1377 recvflags
= convert_socketflags (flags
);
1378 if (recvflags
== -1) {
1379 *werror
= WSAEOPNOTSUPP
;
1383 ret
= mono_w32socket_recv (sock
, buffer
, count
, recvflags
, blocking
);
1384 if (ret
== SOCKET_ERROR
) {
1385 *werror
= mono_w32socket_get_last_error ();
1393 ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock
, WSABUF
*buffers
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1397 guint32 recvflags
= 0;
1402 recvflags
= convert_socketflags (flags
);
1403 if (recvflags
== -1) {
1404 *werror
= WSAEOPNOTSUPP
;
1408 ret
= mono_w32socket_recvbuffers (sock
, buffers
, count
, &recv
, &recvflags
, NULL
, NULL
, blocking
);
1409 if (ret
== SOCKET_ERROR
) {
1410 *werror
= mono_w32socket_get_last_error ();
1418 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, MonoObjectHandleInOut sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1422 struct sockaddr
*sa
;
1428 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1434 recvflags
= convert_socketflags (flags
);
1435 if (recvflags
== -1) {
1436 *werror
= WSAEOPNOTSUPP
;
1440 ret
= mono_w32socket_recvfrom (sock
, buffer
, count
, recvflags
, sa
, &sa_size
, blocking
);
1441 if (ret
== SOCKET_ERROR
) {
1442 *werror
= mono_w32socket_get_last_error ();
1447 /* If we didn't get a socket size, then we're probably a
1448 * connected connection-oriented socket and the stack hasn't
1449 * returned the remote address. All we can do is return null.
1452 MONO_HANDLE_ASSIGN (sockaddr
, create_object_handle_from_sockaddr (sa
, sa_size
, werror
, error
));
1453 if (!is_ok (error
)) {
1458 MONO_HANDLE_ASSIGN (sockaddr
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1467 ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1475 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1477 sendflags
= convert_socketflags (flags
);
1478 if (sendflags
== -1) {
1479 *werror
= WSAEOPNOTSUPP
;
1483 ret
= mono_w32socket_send (sock
, buffer
, count
, sendflags
, blocking
);
1484 if (ret
== SOCKET_ERROR
) {
1485 *werror
= mono_w32socket_get_last_error ();
1493 ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock
, WSABUF
*buffers
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1497 guint32 sendflags
= 0;
1502 sendflags
= convert_socketflags (flags
);
1503 if (sendflags
== -1) {
1504 *werror
= WSAEOPNOTSUPP
;
1508 ret
= mono_w32socket_sendbuffers (sock
, buffers
, count
, &sent
, sendflags
, NULL
, NULL
, blocking
);
1509 if (ret
== SOCKET_ERROR
) {
1510 *werror
= mono_w32socket_get_last_error ();
1518 ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1522 struct sockaddr
*sa
;
1527 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1528 if (*werror
!= 0 || !is_ok (error
))
1531 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1533 sendflags
= convert_socketflags (flags
);
1534 if (sendflags
== -1) {
1535 *werror
= WSAEOPNOTSUPP
;
1540 ret
= mono_w32socket_sendto (sock
, buffer
, count
, sendflags
, sa
, sa_size
, blocking
);
1541 if (ret
== SOCKET_ERROR
) {
1542 *werror
= mono_w32socket_get_last_error ();
1552 Socket_to_SOCKET (MonoObjectHandle sockobj
)
1554 MonoClassField
*field
;
1556 field
= mono_class_get_field_from_name_full (mono_handle_class (sockobj
), "m_Handle", NULL
);
1557 MonoSafeHandleHandle safe_handle
= MONO_HANDLE_NEW_GET_FIELD(sockobj
, MonoSafeHandle
, field
);
1559 if (MONO_HANDLE_IS_NULL (safe_handle
))
1562 return (SOCKET
)(gsize
)MONO_HANDLE_GETVAL (safe_handle
, handle
);
1565 #define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
1568 collect_pollfds_from_array (MonoArrayHandle sockets
, int i
, int nfds
, mono_pollfd
*pfds
, int *idx
, int *mode
)
1570 HANDLE_FUNCTION_ENTER ();
1571 gboolean result
= TRUE
;
1572 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1573 MONO_HANDLE_ARRAY_GETREF (obj
, sockets
, i
);
1574 if (MONO_HANDLE_IS_NULL (obj
)) {
1584 pfds
[*idx
].fd
= Socket_to_SOCKET (obj
);
1585 pfds
[*idx
].events
= (*mode
== 0) ? MONO_POLLIN
: (*mode
== 1) ? MONO_POLLOUT
: POLL_ERRORS
;
1588 HANDLE_FUNCTION_RETURN_VAL (result
);
1592 set_socks_array_from_pollfds (MonoArrayHandle sockets
, int i
, mono_pollfd
*pfds
, int *ret
, int *mode
, MonoArrayHandle socks
, int *idx
)
1594 HANDLE_FUNCTION_ENTER ();
1597 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1598 MONO_HANDLE_ARRAY_GETREF (obj
, sockets
, i
);
1599 if (MONO_HANDLE_IS_NULL (obj
)) {
1605 pfd
= &pfds
[i
- *mode
];
1606 if (pfd
->revents
== 0)
1610 if (((*mode
== 0 && (pfd
->revents
& (MONO_POLLIN
| POLL_ERRORS
)) != 0)) ||
1611 ((*mode
== 1 && (pfd
->revents
& (MONO_POLLOUT
| POLL_ERRORS
)) != 0)) ||
1612 ((pfd
->revents
& POLL_ERRORS
) != 0)) {
1613 MONO_HANDLE_ARRAY_SETREF (socks
, *idx
, obj
);
1617 HANDLE_FUNCTION_RETURN ();
1621 ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArrayHandleOut sockets
, gint32 timeout
, gint32
*werror
, MonoError
*error
)
1623 MonoInternalThread
*thread
= mono_thread_internal_current ();
1629 MonoClass
*sock_arr_class
;
1631 uintptr_t socks_size
;
1637 /* *sockets -> READ, null, WRITE, null, ERROR, null */
1638 count
= mono_array_handle_length (sockets
);
1639 nfds
= count
- 3; /* NULL separators */
1640 pfds
= g_new0 (mono_pollfd
, nfds
);
1642 for (i
= 0; i
< count
; i
++) {
1643 if (!collect_pollfds_from_array (sockets
, i
, nfds
, pfds
, &idx
, &mode
)) {
1644 /* The socket array was bogus */
1646 *werror
= WSAEFAULT
;
1651 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1653 start
= time (NULL
);
1657 ret
= mono_poll (pfds
, nfds
, timeout
);
1661 if (timeout
> 0 && ret
< 0) {
1663 int sec
= time (NULL
) - start
;
1665 timeout
= rtimeout
- sec
* 1000;
1668 mono_set_errno (err
);
1671 if (ret
== -1 && errno
== EINTR
) {
1672 if (mono_thread_test_state (thread
, ThreadState_AbortRequested
)) {
1674 MONO_HANDLE_ASSIGN (sockets
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1678 /* Suspend requested? */
1679 mono_thread_interruption_checkpoint_void ();
1681 mono_set_errno (EINTR
);
1683 } while (ret
== -1 && errno
== EINTR
);
1686 *werror
= mono_w32socket_convert_error (errno
);
1693 MONO_HANDLE_ASSIGN (sockets
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1697 sock_arr_class
= mono_handle_class (sockets
);
1698 socks_size
= ((uintptr_t)ret
) + 3; /* space for the NULL delimiters */
1699 MonoArrayHandle socks
= MONO_HANDLE_NEW (MonoArray
, mono_array_new_full_checked (mono_domain_get (), sock_arr_class
, &socks_size
, NULL
, error
));
1700 if (!is_ok (error
)) {
1706 for (i
= 0; i
< count
&& ret
> 0; i
++) {
1707 set_socks_array_from_pollfds (sockets
, i
, pfds
, &ret
, &mode
, socks
, &idx
);
1710 MONO_HANDLE_ASSIGN (sockets
, socks
);
1714 static MonoObjectHandle
1715 int_to_object_handle (MonoDomain
*domain
, int val
, MonoError
*error
)
1717 return MONO_HANDLE_NEW (MonoObject
, mono_value_box_checked (domain
, mono_get_int32_class (), &val
, error
));
1721 ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock
, gint32 level
, gint32 name
, MonoObjectHandleOut obj_val
, gint32
*werror
, MonoError
*error
)
1723 int system_level
= 0;
1724 int system_name
= 0;
1727 socklen_t valsize
= sizeof (val
);
1728 struct linger linger
;
1729 socklen_t lingersize
= sizeof (linger
);
1731 socklen_t time_ms_size
= sizeof (time_ms
);
1733 # if defined(__OpenBSD__)
1734 struct sockpeercred cred
;
1738 socklen_t credsize
= sizeof (cred
);
1740 MonoDomain
*domain
= mono_domain_get ();
1741 MonoClass
*obj_class
;
1742 MonoClassField
*field
;
1747 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1748 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
1749 system_level
= SOL_SOCKET
;
1750 system_name
= SO_REUSEADDR
;
1755 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
, &system_name
);
1759 *werror
= WSAENOPROTOOPT
;
1763 MONO_HANDLE_ASSIGN (obj_val
, int_to_object_handle (domain
, 0, error
));
1767 /* No need to deal with MulticastOption names here, because
1768 * you cant getsockopt AddMembership or DropMembership (the
1769 * int getsockopt will error, causing an exception)
1772 case SocketOptionName_Linger
:
1773 case SocketOptionName_DontLinger
:
1774 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &linger
, &lingersize
);
1777 case SocketOptionName_SendTimeout
:
1778 case SocketOptionName_ReceiveTimeout
:
1779 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &time_ms
, &time_ms_size
);
1783 case SocketOptionName_PeerCred
:
1784 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &cred
, &credsize
);
1789 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &val
, &valsize
);
1792 if (ret
== SOCKET_ERROR
) {
1793 *werror
= mono_w32socket_get_last_error ();
1798 case SocketOptionName_Linger
: {
1799 /* build a System.Net.Sockets.LingerOption */
1800 obj_class
= mono_class_load_from_name (get_socket_assembly (),
1801 "System.Net.Sockets",
1803 MonoObjectHandle obj
= mono_object_new_handle (domain
, obj_class
, error
);
1804 return_if_nok (error
);
1806 /* Locate and set the fields "bool enabled" and "int
1809 field
= mono_class_get_field_from_name_full (obj_class
, "enabled", NULL
);
1810 MONO_HANDLE_SET_FIELD_VAL (obj
, guint8
, field
, linger
.l_onoff
);
1812 field
= mono_class_get_field_from_name_full (obj_class
, "lingerTime", NULL
);
1813 MONO_HANDLE_SET_FIELD_VAL (obj
, guint32
, field
, linger
.l_linger
);
1815 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1818 case SocketOptionName_DontLinger
: {
1819 /* construct a bool int in val - true if linger is off */
1820 MonoObjectHandle obj
= int_to_object_handle (domain
, !linger
.l_onoff
, error
);
1821 return_if_nok (error
);
1823 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1826 case SocketOptionName_SendTimeout
:
1827 case SocketOptionName_ReceiveTimeout
: {
1828 MonoObjectHandle obj
= int_to_object_handle (domain
, time_ms
, error
);
1829 return_if_nok (error
);
1831 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1836 case SocketOptionName_PeerCred
: {
1838 * build a Mono.Posix.PeerCred+PeerCredData if
1841 static MonoImage
*mono_posix_image
= NULL
;
1843 if (mono_posix_image
== NULL
) {
1844 mono_posix_image
= mono_image_loaded_internal ("Mono.Posix", FALSE
);
1845 if (!mono_posix_image
) {
1846 MonoAssemblyOpenRequest req
;
1847 mono_assembly_request_prepare (&req
.request
, sizeof (req
), MONO_ASMCTX_DEFAULT
);
1848 MonoAssembly
*sa
= mono_assembly_request_open ("Mono.Posix.dll", &req
, NULL
);
1850 *werror
= WSAENOPROTOOPT
;
1853 mono_posix_image
= mono_assembly_get_image_internal (sa
);
1858 obj_class
= mono_class_load_from_name (mono_posix_image
,
1861 MonoPeerCredDataHandle cred_data
= MONO_HANDLE_CAST (MonoPeerCredData
, mono_object_new_handle (domain
, obj_class
, error
));
1862 return_if_nok (error
);
1864 MONO_HANDLE_SETVAL (cred_data
, pid
, gint
, cred
.pid
);
1865 MONO_HANDLE_SETVAL (cred_data
, uid
, gint
, cred
.uid
);
1866 MONO_HANDLE_SETVAL (cred_data
, gid
, gint
, cred
.gid
);
1868 MONO_HANDLE_ASSIGN (obj_val
, cred_data
);
1874 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1875 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
)
1878 MonoObjectHandle obj
= int_to_object_handle (domain
, val
, error
);
1879 return_if_nok (error
);
1881 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1887 ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock
, gint32 level
, gint32 name
, MonoArrayHandle byte_val
, gint32
*werror
, MonoError
*error
)
1889 int system_level
= 0;
1890 int system_name
= 0;
1897 ret
= convert_sockopt_level_and_name((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
1900 *werror
= WSAENOPROTOOPT
;
1906 valsize
= mono_array_handle_length (byte_val
);
1909 guchar
*buf
= MONO_ARRAY_HANDLE_PIN (byte_val
, guchar
, 0, &gchandle
);
1911 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, buf
, &valsize
);
1913 mono_gchandle_free_internal (gchandle
);
1915 if (ret
== SOCKET_ERROR
)
1916 *werror
= mono_w32socket_get_last_error ();
1919 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
1920 static struct in_addr
1921 ipaddress_handle_to_struct_in_addr (MonoObjectHandle ipaddr
)
1923 struct in_addr inaddr
;
1924 MonoClassField
*field
;
1926 field
= mono_class_get_field_from_name_full (mono_handle_class (ipaddr
), "m_Address", NULL
);
1929 /* No idea why .net uses a 64bit type to hold a 32bit value...
1931 * Internal value of IPAddess is in little-endian order
1933 inaddr
.s_addr
= GUINT_FROM_LE ((guint32
)MONO_HANDLE_GET_FIELD_VAL (ipaddr
, guint64
, field
));
1938 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1939 static struct in6_addr
1940 ipaddress_handle_to_struct_in6_addr (MonoObjectHandle ipaddr
)
1942 struct in6_addr in6addr
;
1943 MonoClassField
*field
;
1946 field
= mono_class_get_field_from_name_full (mono_handle_class (ipaddr
), "m_Numbers", NULL
);
1948 MonoArrayHandle data
= MONO_HANDLE_NEW_GET_FIELD (ipaddr
, MonoArray
, field
);
1950 for (i
= 0; i
< 8; i
++) {
1952 MONO_HANDLE_ARRAY_GETVAL (v
, data
, guint16
, i
);
1953 const guint16 s
= GUINT16_TO_BE (v
);
1955 /* Solaris/MacOS have only the 8 bit version. */
1957 in6addr
.s6_addr
[2 * i
+ 1] = (s
>> 8) & 0xff;
1958 in6addr
.s6_addr
[2 * i
] = s
& 0xff;
1960 in6addr
.s6_addr16
[i
] = s
;
1968 #if defined(__APPLE__) || defined(__FreeBSD__)
1971 get_local_interface_id (int family
)
1973 #if !defined(HAVE_GETIFADDRS) || !defined(HAVE_IF_NAMETOINDEX)
1976 struct ifaddrs
*ifap
= NULL
, *ptr
;
1979 if (getifaddrs (&ifap
))
1982 for (ptr
= ifap
; ptr
; ptr
= ptr
->ifa_next
) {
1983 if (!ptr
->ifa_addr
|| !ptr
->ifa_name
)
1985 if (ptr
->ifa_addr
->sa_family
!= family
)
1987 if ((ptr
->ifa_flags
& IFF_LOOPBACK
) != 0)
1989 if ((ptr
->ifa_flags
& IFF_MULTICAST
) == 0)
1992 idx
= if_nametoindex (ptr
->ifa_name
);
2001 #endif /* defined(__APPLE__) || defined(__FreeBSD__) */
2004 ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (gsize sock
, gint32 level
, gint32 name
, MonoObjectHandle obj_val
, MonoArrayHandle byte_val
, gint32 int_val
, gint32
*werror
, MonoError
*error
)
2006 struct linger linger
;
2007 int system_level
= 0;
2008 int system_name
= 0;
2016 sol_ipv6
= mono_networking_get_ipv6_protocol ();
2017 sol_ip
= mono_networking_get_ip_protocol ();
2019 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
2022 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2023 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
2024 system_name
= SO_REUSEADDR
;
2025 int_val
= int_val
? 0 : 1;
2031 *werror
= WSAENOPROTOOPT
;
2037 /* Only one of obj_val, byte_val or int_val has data */
2038 if (!MONO_HANDLE_IS_NULL (obj_val
)) {
2039 MonoClass
*obj_class
= mono_handle_class (obj_val
);
2040 MonoClassField
*field
;
2044 case SocketOptionName_Linger
:
2045 /* Dig out "bool enabled" and "int lingerTime"
2048 field
= mono_class_get_field_from_name_full (obj_class
, "enabled", NULL
);
2049 linger
.l_onoff
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint8
, field
);
2050 field
= mono_class_get_field_from_name_full (obj_class
, "lingerTime", NULL
);
2051 linger
.l_linger
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint32
, field
);
2053 valsize
= sizeof (linger
);
2054 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, valsize
);
2056 case SocketOptionName_AddMembership
:
2057 case SocketOptionName_DropMembership
:
2058 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2060 MonoObjectHandle address
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2061 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2062 if (system_level
== sol_ipv6
) {
2063 struct ipv6_mreq mreq6
;
2068 field
= mono_class_get_field_from_name_full (obj_class
, "m_Group", NULL
);
2070 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2072 if (!MONO_HANDLE_IS_NULL (address
))
2073 mreq6
.ipv6mr_multiaddr
= ipaddress_handle_to_struct_in6_addr (address
);
2075 field
= mono_class_get_field_from_name_full (obj_class
, "m_Interface", NULL
);
2076 mreq6
.ipv6mr_interface
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint64
, field
);
2078 #if defined(__APPLE__) || defined(__FreeBSD__)
2082 * Mac OS Lion doesn't allow ipv6mr_interface = 0.
2084 * Tests on Windows and Linux show that the multicast group is only
2085 * joined on one NIC when interface = 0, so we simply use the interface
2086 * id from the first non-loopback interface (this is also what
2087 * Dns.GetHostName (string.Empty) would return).
2089 if (!mreq6
.ipv6mr_interface
)
2090 mreq6
.ipv6mr_interface
= get_local_interface_id (AF_INET6
);
2093 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq6
, sizeof (mreq6
));
2095 break; // Don't check sol_ip
2098 if (system_level
== sol_ip
) {
2099 #ifdef HAVE_STRUCT_IP_MREQN
2100 struct ip_mreqn mreq
= {{0}};
2102 struct ip_mreq mreq
= {{0}};
2103 #endif /* HAVE_STRUCT_IP_MREQN */
2106 * pain! MulticastOption holds two IPAddress
2107 * members, so I have to dig the value out of
2110 field
= mono_class_get_field_from_name_full (obj_class
, "group", NULL
);
2111 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2113 /* address might not be defined and if so, set the address to ADDR_ANY.
2115 if (!MONO_HANDLE_IS_NULL (address
))
2116 mreq
.imr_multiaddr
= ipaddress_handle_to_struct_in_addr (address
);
2118 field
= mono_class_get_field_from_name_full (obj_class
, "localAddress", NULL
);
2119 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2121 #ifdef HAVE_STRUCT_IP_MREQN
2122 if (!MONO_HANDLE_IS_NULL (address
))
2123 mreq
.imr_address
= ipaddress_handle_to_struct_in_addr (address
);
2125 field
= mono_class_get_field_from_name_full (obj_class
, "ifIndex", NULL
);
2126 mreq
.imr_ifindex
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, gint32
, field
);
2128 if (!MONO_HANDLE_IS_NULL (address
))
2129 mreq
.imr_interface
= ipaddress_handle_to_struct_in_addr (address
);
2130 #endif /* HAVE_STRUCT_IP_MREQN */
2132 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq
, sizeof (mreq
));
2136 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
2138 /* Cause an exception to be thrown */
2139 *werror
= WSAEINVAL
;
2142 } else if (!MONO_HANDLE_IS_NULL (byte_val
)) {
2143 int valsize
= mono_array_handle_length (byte_val
);
2145 guchar
*buf
= MONO_ARRAY_HANDLE_PIN (byte_val
, guchar
, 0, &gchandle
);
2148 case SocketOptionName_DontLinger
:
2150 linger
.l_onoff
= (*buf
) ? 0 : 1;
2151 linger
.l_linger
= 0;
2152 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2154 *werror
= WSAEINVAL
;
2158 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, buf
, valsize
);
2161 mono_gchandle_free_internal (gchandle
);
2163 /* ReceiveTimeout/SendTimeout get here */
2165 case SocketOptionName_DontLinger
:
2166 linger
.l_onoff
= !int_val
;
2167 linger
.l_linger
= 0;
2168 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2170 case SocketOptionName_MulticastInterface
:
2172 #ifdef HAVE_STRUCT_IP_MREQN
2173 int_val
= GUINT32_FROM_BE (int_val
);
2174 if ((int_val
& 0xff000000) == 0) {
2175 /* int_val is interface index */
2176 struct ip_mreqn mreq
= {{0}};
2177 mreq
.imr_ifindex
= int_val
;
2178 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq
, sizeof (mreq
));
2181 int_val
= GUINT32_TO_BE (int_val
);
2182 #endif /* HAVE_STRUCT_IP_MREQN */
2183 #endif /* HOST_WIN32 */
2184 /* int_val is in_addr */
2185 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &int_val
, sizeof (int_val
));
2187 case SocketOptionName_DontFragment
:
2188 #ifdef HAVE_IP_MTU_DISCOVER
2189 /* Fiddle with the value slightly if we're
2193 int_val
= IP_PMTUDISC_DO
;
2198 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &int_val
, sizeof (int_val
));
2202 if (ret
== SOCKET_ERROR
) {
2203 *werror
= mono_w32socket_get_last_error ();
2205 #ifdef HAVE_IP_MTU_DISCOVER
2206 if (system_name
== IP_MTU_DISCOVER
) {
2207 switch (system_level
) {
2208 case IP_PMTUDISC_DONT
:
2209 case IP_PMTUDISC_WANT
:
2210 case IP_PMTUDISC_DO
:
2211 #ifdef IP_PMTUDISC_PROBE
2212 case IP_PMTUDISC_PROBE
:
2214 #ifdef IP_PMTUDISC_INTERFACE
2215 case IP_PMTUDISC_INTERFACE
:
2217 #ifdef IP_PMTUDISC_OMIT
2218 case IP_PMTUDISC_OMIT
:
2221 * This happens if HAVE_IP_MTU_DISCOVER is set but the OS
2222 * doesn't actually understand it. The only OS that this is
2223 * known to happen on currently is Windows Subsystem for Linux
2224 * (newer versions have been fixed to recognize it). Just
2225 * pretend everything is fine.
2239 ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock
, gint32 how
, gint32
*werror
, MonoError
*error
)
2246 /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
2247 ret
= mono_w32socket_shutdown (sock
, how
);
2248 if (ret
== SOCKET_ERROR
)
2249 *werror
= mono_w32socket_get_last_error ();
2253 ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock
, gint32 code
, MonoArrayHandle input
, MonoArrayHandle output
, gint32
*werror
, MonoError
*error
)
2256 DWORD output_bytes
= 0;
2258 glong output_bytes
= 0;
2260 gchar
*i_buffer
, *o_buffer
;
2262 uint32_t i_gchandle
= 0;
2263 uint32_t o_gchandle
= 0;
2269 if ((guint32
)code
== FIONBIO
)
2270 /* Invalid command. Must use Socket.Blocking */
2273 if (MONO_HANDLE_IS_NULL (input
)) {
2278 i_len
= mono_array_handle_length (input
);
2279 i_buffer
= MONO_ARRAY_HANDLE_PIN (input
, gchar
, 0, &i_gchandle
);
2282 if (MONO_HANDLE_IS_NULL (output
)) {
2287 o_len
= mono_array_handle_length (output
);
2288 o_buffer
= MONO_ARRAY_HANDLE_PIN (output
, gchar
, 0, &o_gchandle
);
2291 ret
= mono_w32socket_ioctl (sock
, code
, i_buffer
, i_len
, o_buffer
, o_len
, &output_bytes
);
2293 mono_gchandle_free_internal (i_gchandle
);
2294 mono_gchandle_free_internal (o_gchandle
);
2296 if (ret
== SOCKET_ERROR
) {
2297 *werror
= mono_w32socket_get_last_error ();
2301 return (gint
)output_bytes
;
2305 addrinfo_add_string (MonoDomain
*domain
, const char *s
, MonoArrayHandle arr
, int index
, MonoError
*error
)
2307 HANDLE_FUNCTION_ENTER ();
2309 MonoStringHandle str
= mono_string_new_handle (domain
, s
, error
);
2310 goto_if_nok (error
, leave
);
2311 MONO_HANDLE_ARRAY_SETREF (arr
, index
, str
);
2313 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2318 addrinfo_add_local_ips (MonoDomain
*domain
, MonoArrayHandleOut h_addr_list
, MonoError
*error
)
2320 HANDLE_FUNCTION_ENTER ();
2321 struct in_addr
*local_in
= NULL
;
2323 struct in6_addr
*local_in6
= NULL
;
2328 local_in
= (struct in_addr
*) mono_get_local_interfaces (AF_INET
, &nlocal_in
);
2329 local_in6
= (struct in6_addr
*) mono_get_local_interfaces (AF_INET6
, &nlocal_in6
);
2330 if (nlocal_in
|| nlocal_in6
) {
2331 char addr
[INET6_ADDRSTRLEN
];
2332 MONO_HANDLE_ASSIGN (h_addr_list
, mono_array_new_handle (domain
, mono_get_string_class (), nlocal_in
+ nlocal_in6
, error
));
2333 goto_if_nok (error
, leave
);
2338 for (i
= 0; i
< nlocal_in
; i
++) {
2340 mono_address_init (&maddr
, AF_INET
, &local_in
[i
]);
2341 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2342 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2348 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2352 for (i
= 0; i
< nlocal_in6
; i
++) {
2354 mono_address_init (&maddr
, AF_INET6
, &local_in6
[i
]);
2355 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2356 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2368 HANDLE_FUNCTION_RETURN_VAL (addr_index
);
2372 addrinfo_to_IPHostEntry_handles (MonoAddressInfo
*info
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gboolean add_local_ips
, MonoError
*error
)
2374 HANDLE_FUNCTION_ENTER ();
2375 MonoAddressEntry
*ai
= NULL
;
2376 MonoDomain
*domain
= mono_domain_get ();
2379 MONO_HANDLE_ASSIGN (h_aliases
, mono_array_new_handle (domain
, mono_get_string_class (), 0, error
));
2380 goto_if_nok (error
, leave
);
2381 if (add_local_ips
) {
2382 int addr_index
= addrinfo_add_local_ips (domain
, h_addr_list
, error
);
2383 goto_if_nok (error
, leave
);
2390 for (ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2391 if (ai
->family
!= AF_INET
&& ai
->family
!= AF_INET6
)
2398 MONO_HANDLE_ASSIGN (h_addr_list
, mono_array_new_handle (domain
, mono_get_string_class (), count
, error
));
2399 goto_if_nok (error
, leave
);
2401 gboolean name_assigned
;
2402 name_assigned
= FALSE
;
2403 for (ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2405 char buffer
[INET6_ADDRSTRLEN
]; /* Max. size for IPv6 */
2407 if ((ai
->family
!= PF_INET
) && (ai
->family
!= PF_INET6
))
2410 mono_address_init (&maddr
, ai
->family
, &ai
->address
);
2411 const char *addr
= NULL
;
2412 if (mono_networking_addr_to_str (&maddr
, buffer
, sizeof (buffer
)))
2416 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2419 if (!name_assigned
) {
2420 name_assigned
= TRUE
;
2421 const char *name
= ai
->canonical_name
!= NULL
? ai
->canonical_name
: buffer
;
2422 MONO_HANDLE_ASSIGN (h_name
, mono_string_new_handle (domain
, name
, error
));
2423 goto_if_nok (error
, leave
);
2431 mono_free_address_info (info
);
2433 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2437 ves_icall_System_Net_Dns_GetHostByName_internal (MonoStringHandle host
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gint32 hint
, MonoError
*error
)
2439 gboolean add_local_ips
= FALSE
, add_info_ok
= TRUE
;
2440 gchar this_hostname
[256];
2441 MonoAddressInfo
*info
= NULL
;
2445 char *hostname
= mono_string_handle_to_utf8 (host
, error
);
2446 return_val_if_nok (error
, FALSE
);
2448 if (*hostname
== '\0') {
2449 add_local_ips
= TRUE
;
2450 MONO_HANDLE_ASSIGN (h_name
, host
);
2453 if (!add_local_ips
&& gethostname (this_hostname
, sizeof (this_hostname
)) != -1) {
2454 if (!strcmp (hostname
, this_hostname
)) {
2455 add_local_ips
= TRUE
;
2456 MONO_HANDLE_ASSIGN (h_name
, host
);
2461 // Win32 APIs already returns local interface addresses for empty hostname ("")
2462 // so we never want to add them manually.
2463 add_local_ips
= FALSE
;
2464 if (mono_get_address_info(hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2465 add_info_ok
= FALSE
;
2467 if (*hostname
&& mono_get_address_info (hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2468 add_info_ok
= FALSE
;
2474 MonoBoolean result
= addrinfo_to_IPHostEntry_handles (info
, h_name
, h_aliases
, h_addr_list
, add_local_ips
, error
);
2481 ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gint32 hint
, MonoError
*error
)
2484 struct sockaddr_in saddr
;
2485 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2486 struct sockaddr_in6 saddr6
;
2488 MonoAddressInfo
*info
= NULL
;
2490 gchar hostname
[NI_MAXHOST
] = { 0 };
2495 address
= mono_string_handle_to_utf8 (addr
, error
);
2496 return_val_if_nok (error
, FALSE
);
2498 if (inet_pton (AF_INET
, address
, &saddr
.sin_addr
) == 1) {
2500 saddr
.sin_family
= AF_INET
;
2502 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2503 else if (inet_pton (AF_INET6
, address
, &saddr6
.sin6_addr
) == 1) {
2505 saddr6
.sin6_family
= AF_INET6
;
2517 #if HAVE_SOCKADDR_IN_SIN_LEN
2518 saddr
.sin_len
= sizeof (saddr
);
2521 ret
= getnameinfo ((struct sockaddr
*)&saddr
, sizeof (saddr
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2525 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2527 #if HAVE_SOCKADDR_IN6_SIN_LEN
2528 saddr6
.sin6_len
= sizeof (saddr6
);
2531 ret
= getnameinfo ((struct sockaddr
*)&saddr6
, sizeof (saddr6
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2537 g_assert_not_reached ();
2543 if (mono_get_address_info (hostname
, 0, hint
| MONO_HINT_CANONICAL_NAME
| MONO_HINT_CONFIGURED_ONLY
, &info
) != 0)
2546 MonoBoolean result
= addrinfo_to_IPHostEntry_handles (info
, h_name
, h_aliases
, h_addr_list
, FALSE
, error
);
2551 ves_icall_System_Net_Dns_GetHostName_internal (MonoStringHandleOut h_name
, MonoError
*error
)
2553 gchar hostname
[NI_MAXHOST
] = { 0 };
2558 ret
= gethostname (hostname
, sizeof (hostname
));
2563 MONO_HANDLE_ASSIGN (h_name
, mono_string_new_handle (mono_domain_get (), hostname
, error
));
2567 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
2569 ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock
, MonoStringHandle filename
, MonoArrayHandle pre_buffer
, MonoArrayHandle post_buffer
, gint flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
2573 TRANSMIT_FILE_BUFFERS buffers
;
2574 uint32_t pre_buffer_gchandle
= 0;
2575 uint32_t post_buffer_gchandle
= 0;
2580 if (MONO_HANDLE_IS_NULL (filename
))
2583 /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
2585 uint32_t filename_gchandle
;
2586 gunichar2
*filename_chars
= mono_string_handle_pin_chars (filename
, &filename_gchandle
);
2587 file
= mono_w32file_create (filename_chars
, GENERIC_READ
, FILE_SHARE_READ
, OPEN_EXISTING
, 0);
2588 mono_gchandle_free_internal (filename_gchandle
);
2589 if (file
== INVALID_HANDLE_VALUE
) {
2590 *werror
= mono_w32error_get_last ();
2594 memset (&buffers
, 0, sizeof (buffers
));
2595 if (!MONO_HANDLE_IS_NULL (pre_buffer
)) {
2596 buffers
.Head
= MONO_ARRAY_HANDLE_PIN (pre_buffer
, guchar
, 0, &pre_buffer_gchandle
);
2597 buffers
.HeadLength
= mono_array_handle_length (pre_buffer
);
2599 if (!MONO_HANDLE_IS_NULL (post_buffer
)) {
2600 buffers
.Tail
= MONO_ARRAY_HANDLE_PIN (post_buffer
, guchar
, 0, &post_buffer_gchandle
);
2601 buffers
.TailLength
= mono_array_handle_length (post_buffer
);
2604 ret
= mono_w32socket_transmit_file (sock
, file
, &buffers
, flags
, blocking
);
2606 if (pre_buffer_gchandle
)
2607 mono_gchandle_free_internal (pre_buffer_gchandle
);
2608 if (post_buffer_gchandle
)
2609 mono_gchandle_free_internal (post_buffer_gchandle
);
2612 *werror
= mono_w32socket_get_last_error ();
2614 mono_w32file_close (file
);
2621 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
2624 mono_network_init (void)
2626 mono_networking_init ();
2627 mono_w32socket_initialize ();
2631 mono_network_cleanup (void)
2633 mono_w32socket_cleanup ();
2634 mono_networking_shutdown ();
2638 ves_icall_cancel_blocking_socket_operation (MonoThreadObjectHandle thread
, MonoError
*error
)
2641 MonoInternalThreadHandle internal
= MONO_HANDLE_NEW_GET (MonoInternalThread
, thread
, internal_thread
);
2642 g_assert (!MONO_HANDLE_IS_NULL (internal
));
2644 guint64 tid
= mono_internal_thread_handle_ptr (internal
)->tid
;
2645 mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (tid
));
2648 #endif /* #ifndef DISABLE_SOCKETS */