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>
100 #elif defined(HAVE_QP2GETIFADDRS)
101 /* Bizarrely, IBM i implements this, but AIX doesn't, so on i, it has a different name... */
102 #include <as400_types.h>
103 #include <as400_protos.h>
104 /* Defines to just reuse ifaddrs code */
105 #define ifaddrs ifaddrs_pase
106 #define freeifaddrs Qp2freeifaddrs
107 #define getifaddrs Qp2getifaddrs
110 #if defined(_MSC_VER) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
113 #include "icall-decl.h"
115 #define LOGDEBUG(...)
116 /* define LOGDEBUG(...) g_message(__VA_ARGS__) */
119 addrinfo_to_IPHostEntry_handles (MonoAddressInfo
*info
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gboolean add_local_ips
, MonoError
*error
);
121 static MonoObjectHandle
122 create_object_handle_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
);
124 static struct sockaddr
*
125 create_sockaddr_from_handle (MonoObjectHandle saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
);
130 mono_w32socket_socket (int domain
, int type
, int protocol
)
134 ret
= WSASocket (domain
, type
, protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
);
140 mono_w32socket_bind (SOCKET sock
, struct sockaddr
*addr
, socklen_t addrlen
)
144 ret
= bind (sock
, addr
, addrlen
);
150 mono_w32socket_getpeername (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
154 ret
= getpeername (sock
, name
, namelen
);
160 mono_w32socket_getsockname (SOCKET sock
, struct sockaddr
*name
, socklen_t
*namelen
)
164 ret
= getsockname (sock
, name
, namelen
);
170 mono_w32socket_getsockopt (SOCKET sock
, gint level
, gint optname
, gpointer optval
, socklen_t
*optlen
)
174 ret
= getsockopt (sock
, level
, optname
, (char*)optval
, optlen
);
180 mono_w32socket_setsockopt (SOCKET sock
, gint level
, gint optname
, gconstpointer optval
, socklen_t optlen
)
184 ret
= setsockopt (sock
, level
, optname
, (const char*)optval
, optlen
);
190 mono_w32socket_listen (SOCKET sock
, gint backlog
)
194 ret
= listen (sock
, backlog
);
200 mono_w32socket_shutdown (SOCKET sock
, gint how
)
204 ret
= shutdown (sock
, how
);
210 mono_w32socket_ioctl (SOCKET sock
, gint32 command
, gchar
*input
, gint inputlen
, gchar
*output
, gint outputlen
, DWORD
*written
)
214 ret
= WSAIoctl (sock
, command
, input
, inputlen
, output
, outputlen
, written
, NULL
, NULL
);
220 mono_w32socket_close (SOCKET sock
)
224 ret
= closesocket (sock
);
229 #endif /* HOST_WIN32 */
232 convert_family (MonoAddressFamily mono_family
)
234 switch (mono_family
) {
235 case AddressFamily_Unknown
:
236 case AddressFamily_ImpLink
:
237 case AddressFamily_Pup
:
238 case AddressFamily_Chaos
:
239 case AddressFamily_Iso
:
240 case AddressFamily_Ecma
:
241 case AddressFamily_DataKit
:
242 case AddressFamily_Ccitt
:
243 case AddressFamily_DataLink
:
244 case AddressFamily_Lat
:
245 case AddressFamily_HyperChannel
:
246 case AddressFamily_NetBios
:
247 case AddressFamily_VoiceView
:
248 case AddressFamily_FireFox
:
249 case AddressFamily_Banyan
:
250 case AddressFamily_Atm
:
251 case AddressFamily_Cluster
:
252 case AddressFamily_Ieee12844
:
253 case AddressFamily_NetworkDesigners
:
254 g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family
);
256 case AddressFamily_Unspecified
:
258 case AddressFamily_Unix
:
260 case AddressFamily_InterNetwork
:
262 case AddressFamily_AppleTalk
:
268 case AddressFamily_InterNetworkV6
:
269 #ifdef HAVE_STRUCT_SOCKADDR_IN6
274 case AddressFamily_DecNet
:
280 case AddressFamily_Ipx
:
286 case AddressFamily_Sna
:
292 case AddressFamily_Irda
:
299 g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family
);
304 static MonoAddressFamily
305 convert_to_mono_family (guint16 af_family
)
309 return AddressFamily_Unspecified
;
311 return AddressFamily_Unix
;
313 return AddressFamily_InterNetwork
;
316 return AddressFamily_Ipx
;
320 return AddressFamily_Sna
;
324 return AddressFamily_DecNet
;
328 return AddressFamily_AppleTalk
;
330 #ifdef HAVE_STRUCT_SOCKADDR_IN6
332 return AddressFamily_InterNetworkV6
;
336 return AddressFamily_Irda
;
339 g_warning ("unknown address family 0x%x", af_family
);
340 return AddressFamily_Unknown
;
345 convert_type (MonoSocketType mono_type
)
348 case SocketType_Stream
:
350 case SocketType_Dgram
:
360 case SocketType_Seqpacket
:
361 #ifdef SOCK_SEQPACKET
362 return SOCK_SEQPACKET
;
366 case SocketType_Unknown
:
367 g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type
);
370 g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type
);
376 convert_proto (MonoProtocolType mono_proto
)
378 switch (mono_proto
) {
379 case ProtocolType_IP
:
380 case ProtocolType_IPv6
:
381 case ProtocolType_Icmp
:
382 case ProtocolType_Igmp
:
383 case ProtocolType_Ggp
:
384 case ProtocolType_Tcp
:
385 case ProtocolType_Pup
:
386 case ProtocolType_Udp
:
387 case ProtocolType_Idp
:
388 /* These protocols are known (on my system at least) */
390 case ProtocolType_ND
:
391 case ProtocolType_Raw
:
392 case ProtocolType_Ipx
:
393 case ProtocolType_Spx
:
394 case ProtocolType_SpxII
:
395 case ProtocolType_Unknown
:
396 /* These protocols arent */
397 g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto
);
404 /* Convert MonoSocketFlags */
406 convert_socketflags (gint32 sflags
)
411 /* SocketFlags.None */
414 if (sflags
& ~(SocketFlags_OutOfBand
| SocketFlags_MaxIOVectorLength
| SocketFlags_Peek
|
415 SocketFlags_DontRoute
| SocketFlags_Partial
))
416 /* Contains invalid flag values */
420 if (sflags
& SocketFlags_OutOfBand
)
423 if (sflags
& SocketFlags_Peek
)
425 if (sflags
& SocketFlags_DontRoute
)
426 flags
|= MSG_DONTROUTE
;
428 /* Ignore Partial - see bug 349688. Don't return -1, because
429 * according to the comment in that bug ms runtime doesn't for
430 * UDP sockets (this means we will silently ignore it for TCP
434 if (sflags
& SocketFlags_Partial
)
438 /* Don't do anything for MaxIOVectorLength */
439 if (sflags
& SocketFlags_MaxIOVectorLength
)
447 * 0 on success (mapped mono_level and mono_name to system_level and system_name
449 * -2 on non-fatal error (ie, must ignore)
452 convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level
, MonoSocketOptionName mono_name
, int *system_level
, int *system_name
)
454 switch (mono_level
) {
455 case SocketOptionLevel_Socket
:
456 *system_level
= SOL_SOCKET
;
459 case SocketOptionName_DontLinger
:
460 /* This is SO_LINGER, because the setsockopt
461 * internal call maps DontLinger to SO_LINGER
464 *system_name
= SO_LINGER
;
467 case SocketOptionName_Debug
:
468 *system_name
= SO_DEBUG
;
472 case SocketOptionName_AcceptConnection
:
473 *system_name
= SO_ACCEPTCONN
;
476 case SocketOptionName_ReuseAddress
:
477 *system_name
= SO_REUSEADDR
;
479 case SocketOptionName_KeepAlive
:
480 *system_name
= SO_KEEPALIVE
;
483 case SocketOptionName_DontRoute
:
484 *system_name
= SO_DONTROUTE
;
487 case SocketOptionName_Broadcast
:
488 *system_name
= SO_BROADCAST
;
490 case SocketOptionName_Linger
:
491 *system_name
= SO_LINGER
;
494 case SocketOptionName_OutOfBandInline
:
495 *system_name
= SO_OOBINLINE
;
498 case SocketOptionName_SendBuffer
:
499 *system_name
= SO_SNDBUF
;
501 case SocketOptionName_ReceiveBuffer
:
502 *system_name
= SO_RCVBUF
;
504 case SocketOptionName_SendLowWater
:
505 *system_name
= SO_SNDLOWAT
;
507 case SocketOptionName_ReceiveLowWater
:
508 *system_name
= SO_RCVLOWAT
;
510 case SocketOptionName_SendTimeout
:
511 *system_name
= SO_SNDTIMEO
;
513 case SocketOptionName_ReceiveTimeout
:
514 *system_name
= SO_RCVTIMEO
;
516 case SocketOptionName_Error
:
517 *system_name
= SO_ERROR
;
519 case SocketOptionName_Type
:
520 *system_name
= SO_TYPE
;
523 case SocketOptionName_PeerCred
:
524 *system_name
= SO_PEERCRED
;
527 case SocketOptionName_ExclusiveAddressUse
:
528 #ifdef SO_EXCLUSIVEADDRUSE
529 *system_name
= SO_EXCLUSIVEADDRUSE
;
532 case SocketOptionName_UseLoopback
:
533 #ifdef SO_USELOOPBACK
534 *system_name
= SO_USELOOPBACK
;
537 case SocketOptionName_MaxConnections
:
539 *system_name
= SO_MAXCONN
;
541 #elif defined(SOMAXCONN)
542 *system_name
= SOMAXCONN
;
546 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name
);
551 case SocketOptionLevel_IP
:
552 *system_level
= mono_networking_get_ip_protocol ();
556 case SocketOptionName_IPOptions
:
557 *system_name
= IP_OPTIONS
;
561 case SocketOptionName_HeaderIncluded
:
562 *system_name
= IP_HDRINCL
;
566 case SocketOptionName_TypeOfService
:
567 *system_name
= IP_TOS
;
571 case SocketOptionName_IpTimeToLive
:
572 *system_name
= IP_TTL
;
575 case SocketOptionName_MulticastInterface
:
576 *system_name
= IP_MULTICAST_IF
;
578 case SocketOptionName_MulticastTimeToLive
:
579 *system_name
= IP_MULTICAST_TTL
;
581 case SocketOptionName_MulticastLoopback
:
582 *system_name
= IP_MULTICAST_LOOP
;
584 case SocketOptionName_AddMembership
:
585 *system_name
= IP_ADD_MEMBERSHIP
;
587 case SocketOptionName_DropMembership
:
588 *system_name
= IP_DROP_MEMBERSHIP
;
590 #ifdef HAVE_IP_PKTINFO
591 case SocketOptionName_PacketInformation
:
592 *system_name
= IP_PKTINFO
;
594 #endif /* HAVE_IP_PKTINFO */
596 case SocketOptionName_DontFragment
:
597 #ifdef HAVE_IP_DONTFRAGMENT
598 *system_name
= IP_DONTFRAGMENT
;
600 #elif defined HAVE_IP_MTU_DISCOVER
601 /* Not quite the same */
602 *system_name
= IP_MTU_DISCOVER
;
605 /* If the flag is not available on this system, we can ignore this error */
607 #endif /* HAVE_IP_DONTFRAGMENT */
608 case SocketOptionName_AddSourceMembership
:
609 case SocketOptionName_DropSourceMembership
:
610 case SocketOptionName_BlockSource
:
611 case SocketOptionName_UnblockSource
:
612 /* Can't figure out how to map these, so fall
616 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name
);
621 case SocketOptionLevel_IPv6
:
622 *system_level
= mono_networking_get_ipv6_protocol ();
625 case SocketOptionName_IpTimeToLive
:
626 case SocketOptionName_HopLimit
:
627 *system_name
= IPV6_UNICAST_HOPS
;
629 case SocketOptionName_MulticastInterface
:
630 *system_name
= IPV6_MULTICAST_IF
;
632 case SocketOptionName_MulticastTimeToLive
:
633 *system_name
= IPV6_MULTICAST_HOPS
;
635 case SocketOptionName_MulticastLoopback
:
636 *system_name
= IPV6_MULTICAST_LOOP
;
638 case SocketOptionName_AddMembership
:
639 *system_name
= IPV6_JOIN_GROUP
;
641 case SocketOptionName_DropMembership
:
642 *system_name
= IPV6_LEAVE_GROUP
;
644 case SocketOptionName_IPv6Only
:
646 *system_name
= IPV6_V6ONLY
;
651 case SocketOptionName_PacketInformation
:
652 #ifdef HAVE_IPV6_PKTINFO
653 *system_name
= IPV6_PKTINFO
;
656 case SocketOptionName_HeaderIncluded
:
657 case SocketOptionName_IPOptions
:
658 case SocketOptionName_TypeOfService
:
659 case SocketOptionName_DontFragment
:
660 case SocketOptionName_AddSourceMembership
:
661 case SocketOptionName_DropSourceMembership
:
662 case SocketOptionName_BlockSource
:
663 case SocketOptionName_UnblockSource
:
664 /* Can't figure out how to map these, so fall
668 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name
);
671 break; /* SocketOptionLevel_IPv6 */
673 case SocketOptionLevel_Tcp
:
674 *system_level
= mono_networking_get_tcp_protocol ();
677 case SocketOptionName_NoDelay
:
678 *system_name
= TCP_NODELAY
;
681 /* The documentation is talking complete
682 * bollocks here: rfc-1222 is titled
683 * 'Advancing the NSFNET Routing Architecture'
684 * and doesn't mention either of the words
685 * "expedite" or "urgent".
687 case SocketOptionName_BsdUrgent
:
688 case SocketOptionName_Expedited
:
691 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name
);
696 case SocketOptionLevel_Udp
:
697 g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level
);
700 case SocketOptionName_NoChecksum
:
701 case SocketOptionName_ChecksumCoverage
:
703 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name
);
710 g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level
);
718 get_socket_assembly (void)
720 MonoDomain
*domain
= mono_domain_get ();
722 if (domain
->socket_assembly
== NULL
) {
723 MonoImage
*socket_assembly
;
725 socket_assembly
= mono_image_loaded_internal ("System", FALSE
);
726 if (!socket_assembly
) {
727 MonoAssemblyOpenRequest req
;
728 mono_assembly_request_prepare (&req
.request
, sizeof (req
), MONO_ASMCTX_DEFAULT
);
729 MonoAssembly
*sa
= mono_assembly_request_open ("System.dll", &req
, NULL
);
732 g_assert_not_reached ();
734 socket_assembly
= mono_assembly_get_image_internal (sa
);
737 mono_atomic_store_release (&domain
->socket_assembly
, socket_assembly
);
740 return domain
->socket_assembly
;
744 ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObjectHandle this_obj
, gint32 family
, gint32 type
, gint32 proto
, gint32
*werror
, MonoError
*error
)
754 sock_family
= convert_family ((MonoAddressFamily
)family
);
755 if (sock_family
== -1) {
756 *werror
= WSAEAFNOSUPPORT
;
760 sock_proto
= convert_proto ((MonoProtocolType
)proto
);
761 if (sock_proto
== -1) {
762 *werror
= WSAEPROTONOSUPPORT
;
766 sock_type
= convert_type ((MonoSocketType
)type
);
767 if (sock_type
== -1) {
768 *werror
= WSAESOCKTNOSUPPORT
;
772 sock
= mono_w32socket_socket (sock_family
, sock_type
, sock_proto
);
774 if (sock
== INVALID_SOCKET
) {
775 *werror
= mono_w32socket_get_last_error ();
779 return GUINT_TO_POINTER (sock
);
782 /* FIXME: the SOCKET parameter (here and in other functions in this
783 * file) is really an IntPtr which needs to be converted to a guint32.
786 ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock
, gint32
*werror
, MonoError
*error
)
788 LOGDEBUG (g_message ("%s: closing 0x%x", __func__
, sock
));
793 /* Clear any pending work item from this socket if the underlying
794 * polling system does not notify when the socket is closed */
795 mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock
));
797 mono_w32socket_close ((SOCKET
) sock
);
801 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void)
803 LOGDEBUG (g_message("%s: returning %d", __func__
, mono_w32socket_get_last_error ()));
805 return mono_w32socket_get_last_error ();
809 ves_icall_System_Net_Sockets_Socket_Available_internal (gsize sock
, gint32
*werror
, MonoError
*error
)
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_internal (gsize sock
, MonoBoolean block
, gint32
*werror
, MonoError
*error
)
835 ret
= mono_w32socket_set_blocking (sock
, block
);
836 if (ret
== SOCKET_ERROR
)
837 *werror
= mono_w32socket_get_last_error ();
841 ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
848 newsock
= mono_w32socket_accept (sock
, NULL
, 0, blocking
);
849 if (newsock
== INVALID_SOCKET
) {
850 *werror
= mono_w32socket_get_last_error ();
854 return GUINT_TO_POINTER (newsock
);
858 ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock
, guint32 backlog
, gint32
*werror
, MonoError
*error
)
865 ret
= mono_w32socket_listen (sock
, backlog
);
866 if (ret
== SOCKET_ERROR
)
867 *werror
= mono_w32socket_get_last_error ();
870 #ifdef HAVE_STRUCT_SOCKADDR_IN6
871 // Check whether it's ::ffff::0:0.
873 is_ipv4_mapped_any (const struct in6_addr
*addr
)
877 for (i
= 0; i
< 10; i
++) {
878 if (addr
->s6_addr
[i
])
881 if ((addr
->s6_addr
[10] != 0xff) || (addr
->s6_addr
[11] != 0xff))
883 for (i
= 12; i
< 16; i
++) {
884 if (addr
->s6_addr
[i
])
891 static MonoObjectHandle
892 create_object_handle_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
)
894 MonoDomain
*domain
= mono_domain_get ();
895 MonoAddressFamily family
;
899 /* Build a System.Net.SocketAddress object instance */
900 if (!domain
->sockaddr_class
)
901 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
902 MonoObjectHandle sockaddr_obj
= mono_object_new_handle (domain
, domain
->sockaddr_class
, error
);
903 return_val_if_nok (error
, MONO_HANDLE_NEW (MonoObject
, NULL
));
905 /* Locate the SocketAddress data buffer in the object */
906 if (!domain
->sockaddr_data_field
) {
907 domain
->sockaddr_data_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Buffer", NULL
);
908 g_assert (domain
->sockaddr_data_field
);
911 /* Locate the SocketAddress data buffer length in the object */
912 if (!domain
->sockaddr_data_length_field
) {
913 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Size", NULL
);
914 g_assert (domain
->sockaddr_data_length_field
);
917 /* May be the +2 here is too conservative, as sa_len returns
918 * the length of the entire sockaddr_in/in6, including
919 * sizeof (unsigned short) of the family */
920 /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
921 MonoArrayHandle data
= mono_array_new_handle (domain
, mono_get_byte_class (), sa_size
+ 2, error
);
922 return_val_if_nok (error
, MONO_HANDLE_NEW (MonoObject
, NULL
));
924 /* The data buffer is laid out as follows:
925 * bytes 0 and 1 are the address family
926 * bytes 2 and 3 are the port info
927 * the rest is the address info
930 family
= convert_to_mono_family (saddr
->sa_family
);
931 if (family
== AddressFamily_Unknown
) {
932 *werror
= WSAEAFNOSUPPORT
;
933 return MONO_HANDLE_NEW (MonoObject
, NULL
);
936 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 0, family
& 0x0FF);
937 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 1, (family
>> 8) & 0x0FF);
939 if (saddr
->sa_family
== AF_INET
) {
940 struct sockaddr_in
*sa_in
= (struct sockaddr_in
*)saddr
;
941 guint16 port
= ntohs (sa_in
->sin_port
);
942 guint32 address
= ntohl (sa_in
->sin_addr
.s_addr
);
945 if (sa_size
< buffer_size
) {
946 mono_error_set_generic_error (error
, "System", "SystemException", "");
947 return MONO_HANDLE_NEW (MonoObject
, NULL
);
950 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 2, (port
>>8) & 0xff);
951 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 3, (port
) & 0xff);
952 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 4, (address
>>24) & 0xff);
953 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 5, (address
>>16) & 0xff);
954 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 6, (address
>>8) & 0xff);
955 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 7, (address
) & 0xff);
957 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 */
958 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 */
962 #ifdef HAVE_STRUCT_SOCKADDR_IN6
963 else if (saddr
->sa_family
== AF_INET6
) {
964 struct sockaddr_in6
*sa_in
= (struct sockaddr_in6
*)saddr
;
966 int buffer_size
= 28;
968 guint16 port
= ntohs (sa_in
->sin6_port
);
970 if (sa_size
< buffer_size
) {
971 mono_error_set_generic_error (error
, "System", "SystemException", "");
972 return MONO_HANDLE_NEW (MonoObject
, NULL
);
975 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 2, (port
>>8) & 0xff);
976 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 3, (port
) & 0xff);
978 if (is_ipv4_mapped_any (&sa_in
->sin6_addr
)) {
979 // Map ::ffff:0:0 to :: (bug #5502)
980 for (i
= 0; i
< 16; i
++)
981 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 8 + i
, 0);
983 for (i
= 0; i
< 16; i
++) {
984 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 8 + i
,
985 sa_in
->sin6_addr
.s6_addr
[i
]);
989 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 24, sa_in
->sin6_scope_id
& 0xff);
990 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 25,
991 (sa_in
->sin6_scope_id
>> 8) & 0xff);
992 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 26,
993 (sa_in
->sin6_scope_id
>> 16) & 0xff);
994 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, 27,
995 (sa_in
->sin6_scope_id
>> 24) & 0xff);
997 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 */
998 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 return sockaddr_obj
;
1003 #ifdef HAVE_SYS_UN_H
1004 else if (saddr
->sa_family
== AF_UNIX
) {
1006 int buffer_size
= sa_size
+ 2;
1008 for (i
= 0; i
< sa_size
; i
++)
1009 MONO_HANDLE_ARRAY_SETVAL (data
, guint8
, i
+ 2, saddr
->sa_data
[i
]);
1011 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 */
1012 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 */
1014 return sockaddr_obj
;
1018 *werror
= WSAEAFNOSUPPORT
;
1019 return MONO_HANDLE_NEW (MonoObject
, NULL
);
1024 get_sockaddr_size (int family
)
1029 if (family
== AF_INET
) {
1030 size
= sizeof (struct sockaddr_in
);
1032 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1033 else if (family
== AF_INET6
) {
1034 size
= sizeof (struct sockaddr_in6
);
1037 #ifdef HAVE_SYS_UN_H
1038 else if (family
== AF_UNIX
) {
1039 size
= sizeof (struct sockaddr_un
);
1045 static MonoObjectHandle
1046 mono_w32socket_getname (gsize sock
, gint32 af
, gboolean local
, gint32
*werror
, MonoError
*error
)
1049 socklen_t salen
= 0;
1051 MonoObjectHandle result
= NULL_HANDLE
;
1055 salen
= get_sockaddr_size (convert_family ((MonoAddressFamily
)af
));
1057 *werror
= WSAEAFNOSUPPORT
;
1061 sa
= g_alloca (salen
);
1062 memset (sa
, 0, salen
);
1064 sa
= g_malloc0 (salen
);
1067 /* Note: linux returns just 2 for AF_UNIX. Always. */
1068 ret
= (local
? mono_w32socket_getsockname
: mono_w32socket_getpeername
) (sock
, (struct sockaddr
*)sa
, &salen
);
1069 if (ret
== SOCKET_ERROR
) {
1070 *werror
= mono_w32socket_get_last_error ();
1074 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
)));
1076 result
= create_object_handle_from_sockaddr ((struct sockaddr
*)sa
, salen
, werror
, error
);
1084 ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock
, gint32 af
, gint32
*werror
, MonoError
*error
)
1086 return mono_w32socket_getname (sock
, af
, TRUE
, werror
, error
);
1090 ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock
, gint32 af
, gint32
*werror
, MonoError
*error
)
1092 return mono_w32socket_getname (sock
, af
, FALSE
, werror
, error
);
1095 static struct sockaddr
*
1096 create_sockaddr_from_handle (MonoObjectHandle saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
)
1098 MonoDomain
*domain
= mono_domain_get ();
1104 if (!domain
->sockaddr_class
)
1105 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
1107 /* Locate the SocketAddress data buffer in the object */
1108 if (!domain
->sockaddr_data_field
) {
1109 domain
->sockaddr_data_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Buffer", NULL
);
1110 g_assert (domain
->sockaddr_data_field
);
1113 /* Locate the SocketAddress data buffer length in the object */
1114 if (!domain
->sockaddr_data_length_field
) {
1115 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name_full (domain
->sockaddr_class
, "m_Size", NULL
);
1116 g_assert (domain
->sockaddr_data_length_field
);
1119 MonoArrayHandle data
= MONO_HANDLE_NEW_GET_FIELD (saddr_obj
, MonoArray
, domain
->sockaddr_data_field
);
1121 /* The data buffer is laid out as follows:
1122 * byte 0 is the address family low byte
1123 * byte 1 is the address family high byte
1125 * bytes 2 and 3 are the port info
1126 * the rest is the address info
1128 * the rest is the file name
1130 len
= MONO_HANDLE_GET_FIELD_VAL (saddr_obj
, int, domain
->sockaddr_data_length_field
);
1131 g_assert (len
>= 2);
1134 guint8
*buf
= MONO_ARRAY_HANDLE_PIN (data
, guint8
, 0, &gchandle
);
1135 family
= convert_family ((MonoAddressFamily
)(buf
[0] + (buf
[1] << 8)));
1136 if (family
== AF_INET
) {
1137 struct sockaddr_in
*sa
;
1142 mono_error_set_generic_error (error
, "System", "SystemException", "");
1143 mono_gchandle_free_internal (gchandle
);
1147 sa
= g_new0 (struct sockaddr_in
, 1);
1148 port
= (buf
[2] << 8) + buf
[3];
1149 address
= (buf
[4] << 24) + (buf
[5] << 16) + (buf
[6] << 8) + buf
[7];
1151 sa
->sin_family
= family
;
1152 sa
->sin_addr
.s_addr
= htonl (address
);
1153 sa
->sin_port
= htons (port
);
1155 *sa_size
= sizeof (struct sockaddr_in
);
1156 mono_gchandle_free_internal (gchandle
);
1157 return (struct sockaddr
*)sa
;
1159 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1160 else if (family
== AF_INET6
) {
1161 struct sockaddr_in6
*sa
;
1167 mono_error_set_generic_error (error
, "System", "SystemException", "");
1168 mono_gchandle_free_internal (gchandle
);
1172 sa
= g_new0 (struct sockaddr_in6
, 1);
1173 port
= buf
[3] + (buf
[2] << 8);
1174 scopeid
= buf
[24] + (buf
[25] << 8) + (buf
[26] << 16) + (buf
[27] << 24);
1176 sa
->sin6_family
= family
;
1177 sa
->sin6_port
= htons (port
);
1178 sa
->sin6_scope_id
= scopeid
;
1180 for (i
= 0; i
< 16; i
++)
1181 sa
->sin6_addr
.s6_addr
[i
] = buf
[8 + i
];
1183 *sa_size
= sizeof (struct sockaddr_in6
);
1184 mono_gchandle_free_internal (gchandle
);
1185 return (struct sockaddr
*)sa
;
1188 #ifdef HAVE_SYS_UN_H
1189 else if (family
== AF_UNIX
) {
1190 struct sockaddr_un
*sock_un
;
1193 /* Need a byte for the '\0' terminator/prefix, and the first
1194 * two bytes hold the SocketAddress family
1196 if (len
- 2 >= sizeof (sock_un
->sun_path
)) {
1197 mono_error_set_argument_out_of_range (error
, "SocketAddress.Size", "MonoArgumentException:SocketAddress.Size");
1198 mono_gchandle_free_internal (gchandle
);
1202 sock_un
= g_new0 (struct sockaddr_un
, 1);
1204 sock_un
->sun_family
= family
;
1205 for (i
= 0; i
< len
- 2; i
++)
1206 sock_un
->sun_path
[i
] = buf
[i
+ 2];
1209 mono_gchandle_free_internal (gchandle
);
1210 return (struct sockaddr
*)sock_un
;
1214 *werror
= WSAEAFNOSUPPORT
;
1215 mono_gchandle_free_internal (gchandle
);
1221 ves_icall_System_Net_Sockets_Socket_Bind_internal (gsize sock
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoError
*error
)
1223 struct sockaddr
*sa
;
1230 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1233 return_if_nok (error
);
1235 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
)));
1237 ret
= mono_w32socket_bind (sock
, sa
, sa_size
);
1239 if (ret
== SOCKET_ERROR
)
1240 *werror
= mono_w32socket_get_last_error ();
1252 ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock
, gint mode
,
1253 gint timeout
, gint32
*werror
, MonoError
*error
)
1255 MonoInternalThread
*thread
= mono_thread_internal_current ();
1264 pfds
= g_new0 (mono_pollfd
, 1);
1265 pfds
->fd
= GPOINTER_TO_INT (sock
);
1268 case SelectModeRead
:
1269 pfds
->events
= MONO_POLLIN
;
1271 case SelectModeWrite
:
1272 pfds
->events
= MONO_POLLOUT
;
1275 pfds
->events
= MONO_POLLERR
| MONO_POLLHUP
| MONO_POLLNVAL
;
1279 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1281 start
= time (NULL
);
1286 ret
= mono_poll (pfds
, 1, timeout
);
1290 if (timeout
> 0 && ret
< 0) {
1292 int sec
= time (NULL
) - start
;
1294 timeout
= rtimeout
- sec
* 1000;
1299 mono_set_errno (err
);
1302 if (ret
== -1 && errno
== EINTR
) {
1303 if (mono_thread_test_state (thread
, ThreadState_AbortRequested
)) {
1308 /* Suspend requested? */
1309 mono_thread_interruption_checkpoint_void ();
1311 mono_set_errno (EINTR
);
1313 } while (ret
== -1 && errno
== EINTR
);
1316 *werror
= mono_w32socket_convert_error (errno
);
1326 ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1328 struct sockaddr
*sa
;
1335 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1338 return_if_nok (error
);
1340 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
)));
1342 ret
= mono_w32socket_connect (sock
, sa
, sa_size
, blocking
);
1343 if (ret
== SOCKET_ERROR
)
1344 *werror
= mono_w32socket_get_last_error ();
1349 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
1352 ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock
, MonoBoolean reuse
, gint32
*werror
, MonoError
*error
)
1356 LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__
, sock
, reuse
));
1358 *werror
= mono_w32socket_disconnect (sock
, reuse
);
1360 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
1363 ves_icall_System_Net_Sockets_Socket_Duplicate_internal (gpointer handle
, gint32 targetProcessId
, gpointer
*duplicate_handle
, gint32
*werror
, MonoError
*error
)
1368 if (!mono_w32socket_duplicate (handle
, targetProcessId
, duplicate_handle
)) {
1369 *werror
= mono_w32error_get_last ();
1377 ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1385 recvflags
= convert_socketflags (flags
);
1386 if (recvflags
== -1) {
1387 *werror
= WSAEOPNOTSUPP
;
1391 ret
= mono_w32socket_recv (sock
, buffer
, count
, recvflags
, blocking
);
1392 if (ret
== SOCKET_ERROR
) {
1393 *werror
= mono_w32socket_get_last_error ();
1401 ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock
, WSABUF
*buffers
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1405 guint32 recvflags
= 0;
1410 recvflags
= convert_socketflags (flags
);
1411 if (recvflags
== -1) {
1412 *werror
= WSAEOPNOTSUPP
;
1416 ret
= mono_w32socket_recvbuffers (sock
, buffers
, count
, &recv
, &recvflags
, NULL
, NULL
, blocking
);
1417 if (ret
== SOCKET_ERROR
) {
1418 *werror
= mono_w32socket_get_last_error ();
1426 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, MonoObjectHandleInOut sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1430 struct sockaddr
*sa
;
1436 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1442 recvflags
= convert_socketflags (flags
);
1443 if (recvflags
== -1) {
1444 *werror
= WSAEOPNOTSUPP
;
1448 ret
= mono_w32socket_recvfrom (sock
, buffer
, count
, recvflags
, sa
, &sa_size
, blocking
);
1449 if (ret
== SOCKET_ERROR
) {
1450 *werror
= mono_w32socket_get_last_error ();
1455 /* If we didn't get a socket size, then we're probably a
1456 * connected connection-oriented socket and the stack hasn't
1457 * returned the remote address. All we can do is return null.
1460 MONO_HANDLE_ASSIGN (sockaddr
, create_object_handle_from_sockaddr (sa
, sa_size
, werror
, error
));
1461 if (!is_ok (error
)) {
1466 MONO_HANDLE_ASSIGN (sockaddr
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1475 ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1483 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1485 sendflags
= convert_socketflags (flags
);
1486 if (sendflags
== -1) {
1487 *werror
= WSAEOPNOTSUPP
;
1491 ret
= mono_w32socket_send (sock
, buffer
, count
, sendflags
, blocking
);
1492 if (ret
== SOCKET_ERROR
) {
1493 *werror
= mono_w32socket_get_last_error ();
1501 ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock
, WSABUF
*buffers
, gint32 count
, gint32 flags
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1505 guint32 sendflags
= 0;
1510 sendflags
= convert_socketflags (flags
);
1511 if (sendflags
== -1) {
1512 *werror
= WSAEOPNOTSUPP
;
1516 ret
= mono_w32socket_sendbuffers (sock
, buffers
, count
, &sent
, sendflags
, NULL
, NULL
, blocking
);
1517 if (ret
== SOCKET_ERROR
) {
1518 *werror
= mono_w32socket_get_last_error ();
1526 ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock
, gchar
*buffer
, gint32 count
, gint32 flags
, MonoObjectHandle sockaddr
, gint32
*werror
, MonoBoolean blocking
, MonoError
*error
)
1530 struct sockaddr
*sa
;
1535 sa
= create_sockaddr_from_handle (sockaddr
, &sa_size
, werror
, error
);
1536 if (*werror
!= 0 || !is_ok (error
))
1539 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1541 sendflags
= convert_socketflags (flags
);
1542 if (sendflags
== -1) {
1543 *werror
= WSAEOPNOTSUPP
;
1548 ret
= mono_w32socket_sendto (sock
, buffer
, count
, sendflags
, sa
, sa_size
, blocking
);
1549 if (ret
== SOCKET_ERROR
) {
1550 *werror
= mono_w32socket_get_last_error ();
1560 Socket_to_SOCKET (MonoObjectHandle sockobj
)
1562 MonoClassField
*field
;
1564 field
= mono_class_get_field_from_name_full (mono_handle_class (sockobj
), "m_Handle", NULL
);
1565 MonoSafeHandleHandle safe_handle
= MONO_HANDLE_NEW_GET_FIELD(sockobj
, MonoSafeHandle
, field
);
1567 if (MONO_HANDLE_IS_NULL (safe_handle
))
1570 return (SOCKET
)(gsize
)MONO_HANDLE_GETVAL (safe_handle
, handle
);
1573 #define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
1576 collect_pollfds_from_array (MonoArrayHandle sockets
, int i
, int nfds
, mono_pollfd
*pfds
, int *idx
, int *mode
)
1578 HANDLE_FUNCTION_ENTER ();
1579 gboolean result
= TRUE
;
1580 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1581 MONO_HANDLE_ARRAY_GETREF (obj
, sockets
, i
);
1582 if (MONO_HANDLE_IS_NULL (obj
)) {
1592 pfds
[*idx
].fd
= Socket_to_SOCKET (obj
);
1593 pfds
[*idx
].events
= (*mode
== 0) ? MONO_POLLIN
: (*mode
== 1) ? MONO_POLLOUT
: POLL_ERRORS
;
1596 HANDLE_FUNCTION_RETURN_VAL (result
);
1600 set_socks_array_from_pollfds (MonoArrayHandle sockets
, int i
, mono_pollfd
*pfds
, int *ret
, int *mode
, MonoArrayHandle socks
, int *idx
)
1602 HANDLE_FUNCTION_ENTER ();
1605 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1606 MONO_HANDLE_ARRAY_GETREF (obj
, sockets
, i
);
1607 if (MONO_HANDLE_IS_NULL (obj
)) {
1613 pfd
= &pfds
[i
- *mode
];
1614 if (pfd
->revents
== 0)
1618 if (((*mode
== 0 && (pfd
->revents
& (MONO_POLLIN
| POLL_ERRORS
)) != 0)) ||
1619 ((*mode
== 1 && (pfd
->revents
& (MONO_POLLOUT
| POLL_ERRORS
)) != 0)) ||
1620 ((pfd
->revents
& POLL_ERRORS
) != 0)) {
1621 MONO_HANDLE_ARRAY_SETREF (socks
, *idx
, obj
);
1625 HANDLE_FUNCTION_RETURN ();
1629 ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArrayHandleOut sockets
, gint32 timeout
, gint32
*werror
, MonoError
*error
)
1631 MonoInternalThread
*thread
= mono_thread_internal_current ();
1637 MonoClass
*sock_arr_class
;
1639 uintptr_t socks_size
;
1645 /* *sockets -> READ, null, WRITE, null, ERROR, null */
1646 count
= mono_array_handle_length (sockets
);
1647 nfds
= count
- 3; /* NULL separators */
1648 pfds
= g_new0 (mono_pollfd
, nfds
);
1650 for (i
= 0; i
< count
; i
++) {
1651 if (!collect_pollfds_from_array (sockets
, i
, nfds
, pfds
, &idx
, &mode
)) {
1652 /* The socket array was bogus */
1654 *werror
= WSAEFAULT
;
1659 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1661 start
= time (NULL
);
1665 ret
= mono_poll (pfds
, nfds
, timeout
);
1669 if (timeout
> 0 && ret
< 0) {
1671 int sec
= time (NULL
) - start
;
1673 timeout
= rtimeout
- sec
* 1000;
1676 mono_set_errno (err
);
1679 if (ret
== -1 && errno
== EINTR
) {
1680 if (mono_thread_test_state (thread
, ThreadState_AbortRequested
)) {
1682 MONO_HANDLE_ASSIGN (sockets
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1686 /* Suspend requested? */
1687 mono_thread_interruption_checkpoint_void ();
1689 mono_set_errno (EINTR
);
1691 } while (ret
== -1 && errno
== EINTR
);
1694 *werror
= mono_w32socket_convert_error (errno
);
1701 MONO_HANDLE_ASSIGN (sockets
, MONO_HANDLE_NEW (MonoObject
, NULL
));
1705 sock_arr_class
= mono_handle_class (sockets
);
1706 socks_size
= ((uintptr_t)ret
) + 3; /* space for the NULL delimiters */
1707 MonoArrayHandle socks
= MONO_HANDLE_NEW (MonoArray
, mono_array_new_full_checked (mono_domain_get (), sock_arr_class
, &socks_size
, NULL
, error
));
1708 if (!is_ok (error
)) {
1714 for (i
= 0; i
< count
&& ret
> 0; i
++) {
1715 set_socks_array_from_pollfds (sockets
, i
, pfds
, &ret
, &mode
, socks
, &idx
);
1718 MONO_HANDLE_ASSIGN (sockets
, socks
);
1722 static MonoObjectHandle
1723 int_to_object_handle (MonoDomain
*domain
, int val
, MonoError
*error
)
1725 return MONO_HANDLE_NEW (MonoObject
, mono_value_box_checked (domain
, mono_get_int32_class (), &val
, error
));
1729 ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock
, gint32 level
, gint32 name
, MonoObjectHandleOut obj_val
, gint32
*werror
, MonoError
*error
)
1731 int system_level
= 0;
1732 int system_name
= 0;
1735 socklen_t valsize
= sizeof (val
);
1736 struct linger linger
;
1737 socklen_t lingersize
= sizeof (linger
);
1739 socklen_t time_ms_size
= sizeof (time_ms
);
1741 # if defined(__OpenBSD__)
1742 struct sockpeercred cred
;
1746 socklen_t credsize
= sizeof (cred
);
1748 MonoDomain
*domain
= mono_domain_get ();
1749 MonoClass
*obj_class
;
1750 MonoClassField
*field
;
1755 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1756 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
1757 system_level
= SOL_SOCKET
;
1758 system_name
= SO_REUSEADDR
;
1763 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
, &system_name
);
1767 *werror
= WSAENOPROTOOPT
;
1771 MONO_HANDLE_ASSIGN (obj_val
, int_to_object_handle (domain
, 0, error
));
1775 /* No need to deal with MulticastOption names here, because
1776 * you cant getsockopt AddMembership or DropMembership (the
1777 * int getsockopt will error, causing an exception)
1780 case SocketOptionName_Linger
:
1781 case SocketOptionName_DontLinger
:
1782 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &linger
, &lingersize
);
1785 case SocketOptionName_SendTimeout
:
1786 case SocketOptionName_ReceiveTimeout
:
1787 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &time_ms
, &time_ms_size
);
1791 case SocketOptionName_PeerCred
:
1792 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &cred
, &credsize
);
1797 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, &val
, &valsize
);
1800 if (ret
== SOCKET_ERROR
) {
1801 *werror
= mono_w32socket_get_last_error ();
1806 case SocketOptionName_Linger
: {
1807 /* build a System.Net.Sockets.LingerOption */
1808 obj_class
= mono_class_load_from_name (get_socket_assembly (),
1809 "System.Net.Sockets",
1811 MonoObjectHandle obj
= mono_object_new_handle (domain
, obj_class
, error
);
1812 return_if_nok (error
);
1814 /* Locate and set the fields "bool enabled" and "int
1817 field
= mono_class_get_field_from_name_full (obj_class
, "enabled", NULL
);
1818 MONO_HANDLE_SET_FIELD_VAL (obj
, guint8
, field
, linger
.l_onoff
);
1820 field
= mono_class_get_field_from_name_full (obj_class
, "lingerTime", NULL
);
1821 MONO_HANDLE_SET_FIELD_VAL (obj
, guint32
, field
, linger
.l_linger
);
1823 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1826 case SocketOptionName_DontLinger
: {
1827 /* construct a bool int in val - true if linger is off */
1828 MonoObjectHandle obj
= int_to_object_handle (domain
, !linger
.l_onoff
, error
);
1829 return_if_nok (error
);
1831 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1834 case SocketOptionName_SendTimeout
:
1835 case SocketOptionName_ReceiveTimeout
: {
1836 MonoObjectHandle obj
= int_to_object_handle (domain
, time_ms
, error
);
1837 return_if_nok (error
);
1839 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1844 case SocketOptionName_PeerCred
: {
1846 * build a Mono.Posix.PeerCred+PeerCredData if
1849 static MonoImage
*mono_posix_image
= NULL
;
1851 if (mono_posix_image
== NULL
) {
1852 mono_posix_image
= mono_image_loaded_internal ("Mono.Posix", FALSE
);
1853 if (!mono_posix_image
) {
1854 MonoAssemblyOpenRequest req
;
1855 mono_assembly_request_prepare (&req
.request
, sizeof (req
), MONO_ASMCTX_DEFAULT
);
1856 MonoAssembly
*sa
= mono_assembly_request_open ("Mono.Posix.dll", &req
, NULL
);
1858 *werror
= WSAENOPROTOOPT
;
1861 mono_posix_image
= mono_assembly_get_image_internal (sa
);
1866 obj_class
= mono_class_load_from_name (mono_posix_image
,
1869 MonoPeerCredDataHandle cred_data
= MONO_HANDLE_CAST (MonoPeerCredData
, mono_object_new_handle (domain
, obj_class
, error
));
1870 return_if_nok (error
);
1872 MONO_HANDLE_SETVAL (cred_data
, pid
, gint
, cred
.pid
);
1873 MONO_HANDLE_SETVAL (cred_data
, uid
, gint
, cred
.uid
);
1874 MONO_HANDLE_SETVAL (cred_data
, gid
, gint
, cred
.gid
);
1876 MONO_HANDLE_ASSIGN (obj_val
, cred_data
);
1882 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1883 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
)
1886 MonoObjectHandle obj
= int_to_object_handle (domain
, val
, error
);
1887 return_if_nok (error
);
1889 MONO_HANDLE_ASSIGN (obj_val
, obj
);
1895 ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock
, gint32 level
, gint32 name
, MonoArrayHandle byte_val
, gint32
*werror
, MonoError
*error
)
1897 int system_level
= 0;
1898 int system_name
= 0;
1905 ret
= convert_sockopt_level_and_name((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
1908 *werror
= WSAENOPROTOOPT
;
1914 valsize
= mono_array_handle_length (byte_val
);
1917 guchar
*buf
= MONO_ARRAY_HANDLE_PIN (byte_val
, guchar
, 0, &gchandle
);
1919 ret
= mono_w32socket_getsockopt (sock
, system_level
, system_name
, buf
, &valsize
);
1921 mono_gchandle_free_internal (gchandle
);
1923 if (ret
== SOCKET_ERROR
)
1924 *werror
= mono_w32socket_get_last_error ();
1927 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
1928 static struct in_addr
1929 ipaddress_handle_to_struct_in_addr (MonoObjectHandle ipaddr
)
1931 struct in_addr inaddr
;
1932 MonoClassField
*field
;
1934 field
= mono_class_get_field_from_name_full (mono_handle_class (ipaddr
), "_addressOrScopeId", NULL
);
1937 /* No idea why .net uses a 64bit type to hold a 32bit value...
1939 * Internal value of IPAddess is in little-endian order
1941 inaddr
.s_addr
= GUINT_FROM_LE ((guint32
)MONO_HANDLE_GET_FIELD_VAL (ipaddr
, guint32
, field
));
1946 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1947 static struct in6_addr
1948 ipaddress_handle_to_struct_in6_addr (MonoObjectHandle ipaddr
)
1950 struct in6_addr in6addr
;
1951 MonoClassField
*field
;
1954 field
= mono_class_get_field_from_name_full (mono_handle_class (ipaddr
), "_numbers", NULL
);
1956 MonoArrayHandle data
= MONO_HANDLE_NEW_GET_FIELD (ipaddr
, MonoArray
, field
);
1958 for (i
= 0; i
< 8; i
++) {
1960 MONO_HANDLE_ARRAY_GETVAL (v
, data
, guint16
, i
);
1961 const guint16 s
= GUINT16_TO_BE (v
);
1963 /* Solaris/MacOS have only the 8 bit version. */
1965 in6addr
.s6_addr
[2 * i
+ 1] = (s
>> 8) & 0xff;
1966 in6addr
.s6_addr
[2 * i
] = s
& 0xff;
1968 in6addr
.s6_addr16
[i
] = s
;
1976 #if defined(__APPLE__) || defined(__FreeBSD__)
1979 get_local_interface_id (int family
)
1981 #if !(defined(HAVE_GETIFADDRS) || defined(HAVE_QP2GETIFADDRS)) || !defined(HAVE_IF_NAMETOINDEX)
1984 struct ifaddrs
*ifap
= NULL
, *ptr
;
1987 if (getifaddrs (&ifap
))
1990 for (ptr
= ifap
; ptr
; ptr
= ptr
->ifa_next
) {
1991 if (!ptr
->ifa_addr
|| !ptr
->ifa_name
)
1993 if (ptr
->ifa_addr
->sa_family
!= family
)
1995 if ((ptr
->ifa_flags
& IFF_LOOPBACK
) != 0)
1997 if ((ptr
->ifa_flags
& IFF_MULTICAST
) == 0)
2000 idx
= if_nametoindex (ptr
->ifa_name
);
2009 #endif /* defined(__APPLE__) || defined(__FreeBSD__) */
2012 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
)
2014 struct linger linger
;
2015 int system_level
= 0;
2016 int system_name
= 0;
2024 sol_ipv6
= mono_networking_get_ipv6_protocol ();
2025 sol_ip
= mono_networking_get_ip_protocol ();
2027 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
2030 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2031 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
2032 system_name
= SO_REUSEADDR
;
2033 int_val
= int_val
? 0 : 1;
2039 *werror
= WSAENOPROTOOPT
;
2045 /* Only one of obj_val, byte_val or int_val has data */
2046 if (!MONO_HANDLE_IS_NULL (obj_val
)) {
2047 MonoClass
*obj_class
= mono_handle_class (obj_val
);
2048 MonoClassField
*field
;
2052 case SocketOptionName_Linger
:
2053 /* Dig out "bool enabled" and "int lingerTime"
2056 field
= mono_class_get_field_from_name_full (obj_class
, "enabled", NULL
);
2057 linger
.l_onoff
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint8
, field
);
2058 field
= mono_class_get_field_from_name_full (obj_class
, "lingerTime", NULL
);
2059 linger
.l_linger
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint32
, field
);
2061 valsize
= sizeof (linger
);
2062 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, valsize
);
2064 case SocketOptionName_AddMembership
:
2065 case SocketOptionName_DropMembership
:
2066 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2068 MonoObjectHandle address
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2069 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2070 if (system_level
== sol_ipv6
) {
2071 struct ipv6_mreq mreq6
;
2076 field
= mono_class_get_field_from_name_full (obj_class
, "m_Group", NULL
);
2078 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2080 if (!MONO_HANDLE_IS_NULL (address
))
2081 mreq6
.ipv6mr_multiaddr
= ipaddress_handle_to_struct_in6_addr (address
);
2083 field
= mono_class_get_field_from_name_full (obj_class
, "m_Interface", NULL
);
2084 mreq6
.ipv6mr_interface
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, guint64
, field
);
2086 #if defined(__APPLE__) || defined(__FreeBSD__)
2090 * Mac OS Lion doesn't allow ipv6mr_interface = 0.
2092 * Tests on Windows and Linux show that the multicast group is only
2093 * joined on one NIC when interface = 0, so we simply use the interface
2094 * id from the first non-loopback interface (this is also what
2095 * Dns.GetHostName (string.Empty) would return).
2097 if (!mreq6
.ipv6mr_interface
)
2098 mreq6
.ipv6mr_interface
= get_local_interface_id (AF_INET6
);
2101 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq6
, sizeof (mreq6
));
2103 break; // Don't check sol_ip
2106 if (system_level
== sol_ip
) {
2107 #ifdef HAVE_STRUCT_IP_MREQN
2108 struct ip_mreqn mreq
= {{0}};
2110 struct ip_mreq mreq
= {{0}};
2111 #endif /* HAVE_STRUCT_IP_MREQN */
2114 * pain! MulticastOption holds two IPAddress
2115 * members, so I have to dig the value out of
2118 field
= mono_class_get_field_from_name_full (obj_class
, "group", NULL
);
2119 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2121 /* address might not be defined and if so, set the address to ADDR_ANY.
2123 if (!MONO_HANDLE_IS_NULL (address
))
2124 mreq
.imr_multiaddr
= ipaddress_handle_to_struct_in_addr (address
);
2126 field
= mono_class_get_field_from_name_full (obj_class
, "localAddress", NULL
);
2127 MONO_HANDLE_ASSIGN (address
, MONO_HANDLE_NEW_GET_FIELD (obj_val
, MonoObject
, field
));
2129 #ifdef HAVE_STRUCT_IP_MREQN
2130 if (!MONO_HANDLE_IS_NULL (address
))
2131 mreq
.imr_address
= ipaddress_handle_to_struct_in_addr (address
);
2133 field
= mono_class_get_field_from_name_full (obj_class
, "ifIndex", NULL
);
2134 mreq
.imr_ifindex
= MONO_HANDLE_GET_FIELD_VAL (obj_val
, gint32
, field
);
2136 if (!MONO_HANDLE_IS_NULL (address
))
2137 mreq
.imr_interface
= ipaddress_handle_to_struct_in_addr (address
);
2138 #endif /* HAVE_STRUCT_IP_MREQN */
2140 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq
, sizeof (mreq
));
2144 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
2146 /* Cause an exception to be thrown */
2147 *werror
= WSAEINVAL
;
2150 } else if (!MONO_HANDLE_IS_NULL (byte_val
)) {
2151 int valsize
= mono_array_handle_length (byte_val
);
2153 guchar
*buf
= MONO_ARRAY_HANDLE_PIN (byte_val
, guchar
, 0, &gchandle
);
2156 case SocketOptionName_DontLinger
:
2158 linger
.l_onoff
= (*buf
) ? 0 : 1;
2159 linger
.l_linger
= 0;
2160 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2162 *werror
= WSAEINVAL
;
2166 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, buf
, valsize
);
2169 mono_gchandle_free_internal (gchandle
);
2171 /* ReceiveTimeout/SendTimeout get here */
2173 case SocketOptionName_DontLinger
:
2174 linger
.l_onoff
= !int_val
;
2175 linger
.l_linger
= 0;
2176 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2178 case SocketOptionName_MulticastInterface
:
2180 #ifdef HAVE_STRUCT_IP_MREQN
2181 int_val
= GUINT32_FROM_BE (int_val
);
2182 if ((int_val
& 0xff000000) == 0) {
2183 /* int_val is interface index */
2184 struct ip_mreqn mreq
= {{0}};
2185 mreq
.imr_ifindex
= int_val
;
2186 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &mreq
, sizeof (mreq
));
2189 int_val
= GUINT32_TO_BE (int_val
);
2190 #endif /* HAVE_STRUCT_IP_MREQN */
2191 #endif /* HOST_WIN32 */
2192 /* int_val is in_addr */
2193 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &int_val
, sizeof (int_val
));
2195 case SocketOptionName_DontFragment
:
2196 #ifdef HAVE_IP_MTU_DISCOVER
2197 /* Fiddle with the value slightly if we're
2201 int_val
= IP_PMTUDISC_DO
;
2206 ret
= mono_w32socket_setsockopt (sock
, system_level
, system_name
, &int_val
, sizeof (int_val
));
2210 if (ret
== SOCKET_ERROR
) {
2211 *werror
= mono_w32socket_get_last_error ();
2213 #ifdef HAVE_IP_MTU_DISCOVER
2214 if (system_name
== IP_MTU_DISCOVER
) {
2215 switch (system_level
) {
2216 case IP_PMTUDISC_DONT
:
2217 case IP_PMTUDISC_WANT
:
2218 case IP_PMTUDISC_DO
:
2219 #ifdef IP_PMTUDISC_PROBE
2220 case IP_PMTUDISC_PROBE
:
2222 #ifdef IP_PMTUDISC_INTERFACE
2223 case IP_PMTUDISC_INTERFACE
:
2225 #ifdef IP_PMTUDISC_OMIT
2226 case IP_PMTUDISC_OMIT
:
2229 * This happens if HAVE_IP_MTU_DISCOVER is set but the OS
2230 * doesn't actually understand it. The only OS that this is
2231 * known to happen on currently is Windows Subsystem for Linux
2232 * (newer versions have been fixed to recognize it). Just
2233 * pretend everything is fine.
2247 ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock
, gint32 how
, gint32
*werror
, MonoError
*error
)
2254 /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
2255 ret
= mono_w32socket_shutdown (sock
, how
);
2256 if (ret
== SOCKET_ERROR
)
2257 *werror
= mono_w32socket_get_last_error ();
2261 ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock
, gint32 code
, MonoArrayHandle input
, MonoArrayHandle output
, gint32
*werror
, MonoError
*error
)
2264 DWORD output_bytes
= 0;
2266 glong output_bytes
= 0;
2268 gchar
*i_buffer
, *o_buffer
;
2270 uint32_t i_gchandle
= 0;
2271 uint32_t o_gchandle
= 0;
2277 if ((guint32
)code
== FIONBIO
)
2278 /* Invalid command. Must use Socket.Blocking */
2281 if (MONO_HANDLE_IS_NULL (input
)) {
2286 i_len
= mono_array_handle_length (input
);
2287 i_buffer
= MONO_ARRAY_HANDLE_PIN (input
, gchar
, 0, &i_gchandle
);
2290 if (MONO_HANDLE_IS_NULL (output
)) {
2295 o_len
= mono_array_handle_length (output
);
2296 o_buffer
= MONO_ARRAY_HANDLE_PIN (output
, gchar
, 0, &o_gchandle
);
2299 ret
= mono_w32socket_ioctl (sock
, code
, i_buffer
, i_len
, o_buffer
, o_len
, &output_bytes
);
2301 mono_gchandle_free_internal (i_gchandle
);
2302 mono_gchandle_free_internal (o_gchandle
);
2304 if (ret
== SOCKET_ERROR
) {
2305 *werror
= mono_w32socket_get_last_error ();
2309 return (gint
)output_bytes
;
2313 addrinfo_add_string (MonoDomain
*domain
, const char *s
, MonoArrayHandle arr
, int index
, MonoError
*error
)
2315 HANDLE_FUNCTION_ENTER ();
2317 MonoStringHandle str
= mono_string_new_handle (domain
, s
, error
);
2318 goto_if_nok (error
, leave
);
2319 MONO_HANDLE_ARRAY_SETREF (arr
, index
, str
);
2321 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2326 addrinfo_add_local_ips (MonoDomain
*domain
, MonoArrayHandleOut h_addr_list
, MonoError
*error
)
2328 HANDLE_FUNCTION_ENTER ();
2329 struct in_addr
*local_in
= NULL
;
2331 struct in6_addr
*local_in6
= NULL
;
2336 local_in
= (struct in_addr
*) mono_get_local_interfaces (AF_INET
, &nlocal_in
);
2337 local_in6
= (struct in6_addr
*) mono_get_local_interfaces (AF_INET6
, &nlocal_in6
);
2338 if (nlocal_in
|| nlocal_in6
) {
2339 char addr
[INET6_ADDRSTRLEN
];
2340 MONO_HANDLE_ASSIGN (h_addr_list
, mono_array_new_handle (domain
, mono_get_string_class (), nlocal_in
+ nlocal_in6
, error
));
2341 goto_if_nok (error
, leave
);
2346 for (i
= 0; i
< nlocal_in
; i
++) {
2348 mono_address_init (&maddr
, AF_INET
, &local_in
[i
]);
2349 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2350 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2356 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2360 for (i
= 0; i
< nlocal_in6
; i
++) {
2362 mono_address_init (&maddr
, AF_INET6
, &local_in6
[i
]);
2363 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2364 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2376 HANDLE_FUNCTION_RETURN_VAL (addr_index
);
2380 addrinfo_to_IPHostEntry_handles (MonoAddressInfo
*info
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gboolean add_local_ips
, MonoError
*error
)
2382 HANDLE_FUNCTION_ENTER ();
2383 MonoAddressEntry
*ai
= NULL
;
2384 MonoDomain
*domain
= mono_domain_get ();
2387 MONO_HANDLE_ASSIGN (h_aliases
, mono_array_new_handle (domain
, mono_get_string_class (), 0, error
));
2388 goto_if_nok (error
, leave
);
2389 if (add_local_ips
) {
2390 int addr_index
= addrinfo_add_local_ips (domain
, h_addr_list
, error
);
2391 goto_if_nok (error
, leave
);
2398 for (ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2399 if (ai
->family
!= AF_INET
&& ai
->family
!= AF_INET6
)
2406 MONO_HANDLE_ASSIGN (h_addr_list
, mono_array_new_handle (domain
, mono_get_string_class (), count
, error
));
2407 goto_if_nok (error
, leave
);
2409 gboolean name_assigned
;
2410 name_assigned
= FALSE
;
2411 for (ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2413 char buffer
[INET6_ADDRSTRLEN
]; /* Max. size for IPv6 */
2415 if ((ai
->family
!= PF_INET
) && (ai
->family
!= PF_INET6
))
2418 mono_address_init (&maddr
, ai
->family
, &ai
->address
);
2419 const char *addr
= NULL
;
2420 if (mono_networking_addr_to_str (&maddr
, buffer
, sizeof (buffer
)))
2424 if (!addrinfo_add_string (domain
, addr
, h_addr_list
, addr_index
, error
))
2427 if (!name_assigned
) {
2428 name_assigned
= TRUE
;
2429 const char *name
= ai
->canonical_name
!= NULL
? ai
->canonical_name
: buffer
;
2430 MONO_HANDLE_ASSIGN (h_name
, mono_string_new_handle (domain
, name
, error
));
2431 goto_if_nok (error
, leave
);
2439 mono_free_address_info (info
);
2441 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
2445 ves_icall_System_Net_Dns_GetHostByName_internal (MonoStringHandle host
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gint32 hint
, MonoError
*error
)
2447 gboolean add_local_ips
= FALSE
, add_info_ok
= TRUE
;
2448 gchar this_hostname
[256];
2449 MonoAddressInfo
*info
= NULL
;
2453 char *hostname
= mono_string_handle_to_utf8 (host
, error
);
2454 return_val_if_nok (error
, FALSE
);
2456 if (*hostname
== '\0') {
2457 add_local_ips
= TRUE
;
2458 MONO_HANDLE_ASSIGN (h_name
, host
);
2461 if (!add_local_ips
&& gethostname (this_hostname
, sizeof (this_hostname
)) != -1) {
2462 if (!strcmp (hostname
, this_hostname
)) {
2463 add_local_ips
= TRUE
;
2464 MONO_HANDLE_ASSIGN (h_name
, host
);
2469 // Win32 APIs already returns local interface addresses for empty hostname ("")
2470 // so we never want to add them manually.
2471 add_local_ips
= FALSE
;
2472 if (mono_get_address_info(hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2473 add_info_ok
= FALSE
;
2475 if (*hostname
&& mono_get_address_info (hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2476 add_info_ok
= FALSE
;
2482 MonoBoolean result
= addrinfo_to_IPHostEntry_handles (info
, h_name
, h_aliases
, h_addr_list
, add_local_ips
, error
);
2489 ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr
, MonoStringHandleOut h_name
, MonoArrayHandleOut h_aliases
, MonoArrayHandleOut h_addr_list
, gint32 hint
, MonoError
*error
)
2492 struct sockaddr_in saddr
;
2493 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2494 struct sockaddr_in6 saddr6
;
2496 MonoAddressInfo
*info
= NULL
;
2498 gchar hostname
[NI_MAXHOST
] = { 0 };
2503 address
= mono_string_handle_to_utf8 (addr
, error
);
2504 return_val_if_nok (error
, FALSE
);
2506 if (inet_pton (AF_INET
, address
, &saddr
.sin_addr
) == 1) {
2508 saddr
.sin_family
= AF_INET
;
2510 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2511 else if (inet_pton (AF_INET6
, address
, &saddr6
.sin6_addr
) == 1) {
2513 saddr6
.sin6_family
= AF_INET6
;
2525 #if HAVE_SOCKADDR_IN_SIN_LEN
2526 saddr
.sin_len
= sizeof (saddr
);
2529 ret
= getnameinfo ((struct sockaddr
*)&saddr
, sizeof (saddr
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2533 #ifdef HAVE_STRUCT_SOCKADDR_IN6
2535 #if HAVE_SOCKADDR_IN6_SIN_LEN
2536 saddr6
.sin6_len
= sizeof (saddr6
);
2539 ret
= getnameinfo ((struct sockaddr
*)&saddr6
, sizeof (saddr6
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2545 g_assert_not_reached ();
2551 if (mono_get_address_info (hostname
, 0, hint
| MONO_HINT_CANONICAL_NAME
| MONO_HINT_CONFIGURED_ONLY
, &info
) != 0)
2554 MonoBoolean result
= addrinfo_to_IPHostEntry_handles (info
, h_name
, h_aliases
, h_addr_list
, FALSE
, error
);
2559 ves_icall_System_Net_Dns_GetHostName_internal (MonoStringHandleOut h_name
, MonoError
*error
)
2561 gchar hostname
[NI_MAXHOST
] = { 0 };
2566 ret
= gethostname (hostname
, sizeof (hostname
));
2571 MONO_HANDLE_ASSIGN (h_name
, mono_string_new_handle (mono_domain_get (), hostname
, error
));
2575 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
2577 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
)
2581 TRANSMIT_FILE_BUFFERS buffers
;
2582 uint32_t pre_buffer_gchandle
= 0;
2583 uint32_t post_buffer_gchandle
= 0;
2588 if (MONO_HANDLE_IS_NULL (filename
))
2591 /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
2593 uint32_t filename_gchandle
;
2594 gunichar2
*filename_chars
= mono_string_handle_pin_chars (filename
, &filename_gchandle
);
2595 file
= mono_w32file_create (filename_chars
, GENERIC_READ
, FILE_SHARE_READ
, OPEN_EXISTING
, 0);
2596 mono_gchandle_free_internal (filename_gchandle
);
2597 if (file
== INVALID_HANDLE_VALUE
) {
2598 *werror
= mono_w32error_get_last ();
2602 memset (&buffers
, 0, sizeof (buffers
));
2603 if (!MONO_HANDLE_IS_NULL (pre_buffer
)) {
2604 buffers
.Head
= MONO_ARRAY_HANDLE_PIN (pre_buffer
, guchar
, 0, &pre_buffer_gchandle
);
2605 buffers
.HeadLength
= mono_array_handle_length (pre_buffer
);
2607 if (!MONO_HANDLE_IS_NULL (post_buffer
)) {
2608 buffers
.Tail
= MONO_ARRAY_HANDLE_PIN (post_buffer
, guchar
, 0, &post_buffer_gchandle
);
2609 buffers
.TailLength
= mono_array_handle_length (post_buffer
);
2612 ret
= mono_w32socket_transmit_file (sock
, file
, &buffers
, flags
, blocking
);
2614 if (pre_buffer_gchandle
)
2615 mono_gchandle_free_internal (pre_buffer_gchandle
);
2616 if (post_buffer_gchandle
)
2617 mono_gchandle_free_internal (post_buffer_gchandle
);
2620 *werror
= mono_w32socket_get_last_error ();
2622 mono_w32file_close (file
);
2629 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
2632 mono_network_init (void)
2634 mono_networking_init ();
2635 mono_w32socket_initialize ();
2639 mono_network_cleanup (void)
2641 mono_w32socket_cleanup ();
2642 mono_networking_shutdown ();
2646 ves_icall_cancel_blocking_socket_operation (MonoThreadObjectHandle thread
, MonoError
*error
)
2649 MonoInternalThreadHandle internal
= MONO_HANDLE_NEW_GET (MonoInternalThread
, thread
, internal_thread
);
2650 g_assert (!MONO_HANDLE_IS_NULL (internal
));
2652 guint64 tid
= mono_internal_thread_handle_ptr (internal
)->tid
;
2653 mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (tid
));
2656 #endif /* #ifndef DISABLE_SOCKETS */