2 * socket-io.c: Socket IO internal calls
5 * Dick Porter (dick@ximian.com)
6 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * This file has been re-licensed under the MIT License:
12 * http://opensource.org/licenses/MIT
13 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
18 #ifndef DISABLE_SOCKETS
20 #if defined(__APPLE__) || defined(__FreeBSD__)
21 #define __APPLE_USE_RFC_3542
30 #include <sys/socket.h>
31 #ifdef HAVE_SYS_IOCTL_H
32 #include <sys/ioctl.h>
34 #include <netinet/in.h>
35 #include <netinet/tcp.h>
39 #include <arpa/inet.h>
46 #include <sys/types.h>
48 #include <mono/metadata/object.h>
49 #include <mono/io-layer/io-layer.h>
50 #include <mono/metadata/socket-io.h>
51 #include <mono/metadata/exception.h>
52 #include <mono/metadata/assembly.h>
53 #include <mono/metadata/appdomain.h>
54 #include <mono/metadata/file-io.h>
55 #include <mono/metadata/threads.h>
56 #include <mono/metadata/threads-types.h>
57 #include <mono/metadata/threadpool-ms-io.h>
58 #include <mono/utils/mono-poll.h>
59 /* FIXME change this code to not mess so much with the internals */
60 #include <mono/metadata/class-internals.h>
61 #include <mono/metadata/domain-internals.h>
62 #include <mono/utils/mono-threads.h>
63 #include <mono/utils/mono-memory-model.h>
64 #include <mono/utils/networking.h>
65 #include <mono/utils/w32handle.h>
68 #ifdef HAVE_SYS_TIME_H
71 #ifdef HAVE_SYS_IOCTL_H
72 #include <sys/ioctl.h>
81 #ifdef HAVE_SYS_FILIO_H
82 #include <sys/filio.h> /* defines FIONBIO and FIONREAD */
84 #ifdef HAVE_SYS_SOCKIO_H
85 #include <sys/sockio.h> /* defines SIOCATMARK */
91 #ifdef HAVE_GETIFADDRS
92 // <net/if.h> must be included before <ifaddrs.h>
96 #include "mono/io-layer/socket-wrappers.h"
99 /* define LOGDEBUG(...) g_message(__VA_ARGS__) */
102 abort_syscall (gpointer data
)
104 mono_thread_info_abort_socket_syscall_for_close ((MonoNativeThreadId
) (gsize
) data
);
108 convert_family (MonoAddressFamily mono_family
)
110 switch (mono_family
) {
111 case AddressFamily_Unknown
:
112 case AddressFamily_ImpLink
:
113 case AddressFamily_Pup
:
114 case AddressFamily_Chaos
:
115 case AddressFamily_Iso
:
116 case AddressFamily_Ecma
:
117 case AddressFamily_DataKit
:
118 case AddressFamily_Ccitt
:
119 case AddressFamily_DataLink
:
120 case AddressFamily_Lat
:
121 case AddressFamily_HyperChannel
:
122 case AddressFamily_NetBios
:
123 case AddressFamily_VoiceView
:
124 case AddressFamily_FireFox
:
125 case AddressFamily_Banyan
:
126 case AddressFamily_Atm
:
127 case AddressFamily_Cluster
:
128 case AddressFamily_Ieee12844
:
129 case AddressFamily_NetworkDesigners
:
130 g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family
);
132 case AddressFamily_Unspecified
:
134 case AddressFamily_Unix
:
136 case AddressFamily_InterNetwork
:
138 case AddressFamily_AppleTalk
:
140 case AddressFamily_InterNetworkV6
:
142 case AddressFamily_DecNet
:
148 case AddressFamily_Ipx
:
154 case AddressFamily_Sna
:
160 case AddressFamily_Irda
:
167 g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family
);
172 static MonoAddressFamily
173 convert_to_mono_family (guint16 af_family
)
177 return AddressFamily_Unspecified
;
179 return AddressFamily_Unix
;
181 return AddressFamily_InterNetwork
;
184 return AddressFamily_Ipx
;
188 return AddressFamily_Sna
;
192 return AddressFamily_DecNet
;
195 return AddressFamily_AppleTalk
;
197 return AddressFamily_InterNetworkV6
;
200 return AddressFamily_Irda
;
203 g_warning ("unknown address family 0x%x", af_family
);
204 return AddressFamily_Unknown
;
209 convert_type (MonoSocketType mono_type
)
212 case SocketType_Stream
:
214 case SocketType_Dgram
:
224 case SocketType_Seqpacket
:
225 return SOCK_SEQPACKET
;
226 case SocketType_Unknown
:
227 g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type
);
230 g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type
);
236 convert_proto (MonoProtocolType mono_proto
)
238 switch (mono_proto
) {
239 case ProtocolType_IP
:
240 case ProtocolType_IPv6
:
241 case ProtocolType_Icmp
:
242 case ProtocolType_Igmp
:
243 case ProtocolType_Ggp
:
244 case ProtocolType_Tcp
:
245 case ProtocolType_Pup
:
246 case ProtocolType_Udp
:
247 case ProtocolType_Idp
:
248 /* These protocols are known (on my system at least) */
250 case ProtocolType_ND
:
251 case ProtocolType_Raw
:
252 case ProtocolType_Ipx
:
253 case ProtocolType_Spx
:
254 case ProtocolType_SpxII
:
255 case ProtocolType_Unknown
:
256 /* These protocols arent */
257 g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto
);
264 /* Convert MonoSocketFlags */
266 convert_socketflags (gint32 sflags
)
271 /* SocketFlags.None */
274 if (sflags
& ~(SocketFlags_OutOfBand
| SocketFlags_MaxIOVectorLength
| SocketFlags_Peek
|
275 SocketFlags_DontRoute
| SocketFlags_Partial
))
276 /* Contains invalid flag values */
279 if (sflags
& SocketFlags_OutOfBand
)
281 if (sflags
& SocketFlags_Peek
)
283 if (sflags
& SocketFlags_DontRoute
)
284 flags
|= MSG_DONTROUTE
;
286 /* Ignore Partial - see bug 349688. Don't return -1, because
287 * according to the comment in that bug ms runtime doesn't for
288 * UDP sockets (this means we will silently ignore it for TCP
292 if (sflags
& SocketFlags_Partial
)
296 /* Don't do anything for MaxIOVectorLength */
297 if (sflags
& SocketFlags_MaxIOVectorLength
)
305 * 0 on success (mapped mono_level and mono_name to system_level and system_name
307 * -2 on non-fatal error (ie, must ignore)
310 convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level
, MonoSocketOptionName mono_name
, int *system_level
, int *system_name
)
312 switch (mono_level
) {
313 case SocketOptionLevel_Socket
:
314 *system_level
= SOL_SOCKET
;
317 case SocketOptionName_DontLinger
:
318 /* This is SO_LINGER, because the setsockopt
319 * internal call maps DontLinger to SO_LINGER
322 *system_name
= SO_LINGER
;
324 case SocketOptionName_Debug
:
325 *system_name
= SO_DEBUG
;
328 case SocketOptionName_AcceptConnection
:
329 *system_name
= SO_ACCEPTCONN
;
332 case SocketOptionName_ReuseAddress
:
333 *system_name
= SO_REUSEADDR
;
335 case SocketOptionName_KeepAlive
:
336 *system_name
= SO_KEEPALIVE
;
338 case SocketOptionName_DontRoute
:
339 *system_name
= SO_DONTROUTE
;
341 case SocketOptionName_Broadcast
:
342 *system_name
= SO_BROADCAST
;
344 case SocketOptionName_Linger
:
345 *system_name
= SO_LINGER
;
347 case SocketOptionName_OutOfBandInline
:
348 *system_name
= SO_OOBINLINE
;
350 case SocketOptionName_SendBuffer
:
351 *system_name
= SO_SNDBUF
;
353 case SocketOptionName_ReceiveBuffer
:
354 *system_name
= SO_RCVBUF
;
356 case SocketOptionName_SendLowWater
:
357 *system_name
= SO_SNDLOWAT
;
359 case SocketOptionName_ReceiveLowWater
:
360 *system_name
= SO_RCVLOWAT
;
362 case SocketOptionName_SendTimeout
:
363 *system_name
= SO_SNDTIMEO
;
365 case SocketOptionName_ReceiveTimeout
:
366 *system_name
= SO_RCVTIMEO
;
368 case SocketOptionName_Error
:
369 *system_name
= SO_ERROR
;
371 case SocketOptionName_Type
:
372 *system_name
= SO_TYPE
;
375 case SocketOptionName_PeerCred
:
376 *system_name
= SO_PEERCRED
;
379 case SocketOptionName_ExclusiveAddressUse
:
380 #ifdef SO_EXCLUSIVEADDRUSE
381 *system_name
= SO_EXCLUSIVEADDRUSE
;
384 case SocketOptionName_UseLoopback
:
385 #ifdef SO_USELOOPBACK
386 *system_name
= SO_USELOOPBACK
;
389 case SocketOptionName_MaxConnections
:
391 *system_name
= SO_MAXCONN
;
393 #elif defined(SOMAXCONN)
394 *system_name
= SOMAXCONN
;
398 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name
);
403 case SocketOptionLevel_IP
:
404 *system_level
= mono_networking_get_ip_protocol ();
407 case SocketOptionName_IPOptions
:
408 *system_name
= IP_OPTIONS
;
411 case SocketOptionName_HeaderIncluded
:
412 *system_name
= IP_HDRINCL
;
416 case SocketOptionName_TypeOfService
:
417 *system_name
= IP_TOS
;
421 case SocketOptionName_IpTimeToLive
:
422 *system_name
= IP_TTL
;
425 case SocketOptionName_MulticastInterface
:
426 *system_name
= IP_MULTICAST_IF
;
428 case SocketOptionName_MulticastTimeToLive
:
429 *system_name
= IP_MULTICAST_TTL
;
431 case SocketOptionName_MulticastLoopback
:
432 *system_name
= IP_MULTICAST_LOOP
;
434 case SocketOptionName_AddMembership
:
435 *system_name
= IP_ADD_MEMBERSHIP
;
437 case SocketOptionName_DropMembership
:
438 *system_name
= IP_DROP_MEMBERSHIP
;
440 #ifdef HAVE_IP_PKTINFO
441 case SocketOptionName_PacketInformation
:
442 *system_name
= IP_PKTINFO
;
444 #endif /* HAVE_IP_PKTINFO */
446 case SocketOptionName_DontFragment
:
447 #ifdef HAVE_IP_DONTFRAGMENT
448 *system_name
= IP_DONTFRAGMENT
;
450 #elif defined HAVE_IP_MTU_DISCOVER
451 /* Not quite the same */
452 *system_name
= IP_MTU_DISCOVER
;
455 /* If the flag is not available on this system, we can ignore this error */
457 #endif /* HAVE_IP_DONTFRAGMENT */
458 case SocketOptionName_AddSourceMembership
:
459 case SocketOptionName_DropSourceMembership
:
460 case SocketOptionName_BlockSource
:
461 case SocketOptionName_UnblockSource
:
462 /* Can't figure out how to map these, so fall
466 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name
);
471 case SocketOptionLevel_IPv6
:
472 *system_level
= mono_networking_get_ipv6_protocol ();
475 case SocketOptionName_IpTimeToLive
:
476 case SocketOptionName_HopLimit
:
477 *system_name
= IPV6_UNICAST_HOPS
;
479 case SocketOptionName_MulticastInterface
:
480 *system_name
= IPV6_MULTICAST_IF
;
482 case SocketOptionName_MulticastTimeToLive
:
483 *system_name
= IPV6_MULTICAST_HOPS
;
485 case SocketOptionName_MulticastLoopback
:
486 *system_name
= IPV6_MULTICAST_LOOP
;
488 case SocketOptionName_AddMembership
:
489 *system_name
= IPV6_JOIN_GROUP
;
491 case SocketOptionName_DropMembership
:
492 *system_name
= IPV6_LEAVE_GROUP
;
494 case SocketOptionName_IPv6Only
:
496 *system_name
= IPV6_V6ONLY
;
501 case SocketOptionName_PacketInformation
:
502 #ifdef HAVE_IPV6_PKTINFO
503 *system_name
= IPV6_PKTINFO
;
506 case SocketOptionName_HeaderIncluded
:
507 case SocketOptionName_IPOptions
:
508 case SocketOptionName_TypeOfService
:
509 case SocketOptionName_DontFragment
:
510 case SocketOptionName_AddSourceMembership
:
511 case SocketOptionName_DropSourceMembership
:
512 case SocketOptionName_BlockSource
:
513 case SocketOptionName_UnblockSource
:
514 /* Can't figure out how to map these, so fall
518 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name
);
521 break; /* SocketOptionLevel_IPv6 */
523 case SocketOptionLevel_Tcp
:
524 *system_level
= mono_networking_get_tcp_protocol ();
527 case SocketOptionName_NoDelay
:
528 *system_name
= TCP_NODELAY
;
531 /* The documentation is talking complete
532 * bollocks here: rfc-1222 is titled
533 * 'Advancing the NSFNET Routing Architecture'
534 * and doesn't mention either of the words
535 * "expedite" or "urgent".
537 case SocketOptionName_BsdUrgent
:
538 case SocketOptionName_Expedited
:
541 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name
);
546 case SocketOptionLevel_Udp
:
547 g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level
);
550 case SocketOptionName_NoChecksum
:
551 case SocketOptionName_ChecksumCoverage
:
553 g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name
);
560 g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level
);
568 get_socket_assembly (void)
570 MonoDomain
*domain
= mono_domain_get ();
572 if (domain
->socket_assembly
== NULL
) {
573 MonoImage
*socket_assembly
;
575 socket_assembly
= mono_image_loaded ("System");
576 if (!socket_assembly
) {
577 MonoAssembly
*sa
= mono_assembly_open ("System.dll", NULL
);
580 g_assert_not_reached ();
582 socket_assembly
= mono_assembly_get_image (sa
);
585 mono_atomic_store_release (&domain
->socket_assembly
, socket_assembly
);
588 return domain
->socket_assembly
;
592 get_family_hint (MonoError
*error
)
594 MonoDomain
*domain
= mono_domain_get ();
596 mono_error_init (error
);
598 if (!domain
->inet_family_hint
) {
599 MonoImage
*socket_assembly
;
600 MonoClass
*socket_class
;
601 MonoClassField
*ipv6_field
, *ipv4_field
;
602 gint32 ipv6_enabled
= -1, ipv4_enabled
= -1;
605 socket_assembly
= get_socket_assembly ();
606 g_assert (socket_assembly
);
608 socket_class
= mono_class_load_from_name (socket_assembly
, "System.Net.Sockets", "Socket");
610 ipv4_field
= mono_class_get_field_from_name (socket_class
, "ipv4_supported");
611 g_assert (ipv4_field
);
613 ipv6_field
= mono_class_get_field_from_name (socket_class
, "ipv6_supported");
614 g_assert (ipv6_field
);
616 vtable
= mono_class_vtable (mono_domain_get (), socket_class
);
619 mono_runtime_class_init_full (vtable
, error
);
620 return_val_if_nok (error
, -1);
622 mono_field_static_get_value_checked (vtable
, ipv4_field
, &ipv4_enabled
, error
);
623 return_val_if_nok (error
, -1);
624 mono_field_static_get_value_checked (vtable
, ipv6_field
, &ipv6_enabled
, error
);
625 return_val_if_nok (error
, -1);
627 mono_domain_lock (domain
);
628 if (ipv4_enabled
== 1 && ipv6_enabled
== 1) {
629 domain
->inet_family_hint
= 1;
630 } else if (ipv4_enabled
== 1) {
631 domain
->inet_family_hint
= 2;
633 domain
->inet_family_hint
= 3;
635 mono_domain_unlock (domain
);
637 switch (domain
->inet_family_hint
) {
638 case 1: return PF_UNSPEC
;
639 case 2: return PF_INET
;
640 case 3: return PF_INET6
;
647 ves_icall_System_Net_Sockets_Socket_Socket_internal (MonoObject
*this_obj
, gint32 family
, gint32 type
, gint32 proto
, gint32
*werror
)
656 sock_family
= convert_family ((MonoAddressFamily
)family
);
657 if (sock_family
== -1) {
658 *werror
= WSAEAFNOSUPPORT
;
662 sock_proto
= convert_proto ((MonoProtocolType
)proto
);
663 if (sock_proto
== -1) {
664 *werror
= WSAEPROTONOSUPPORT
;
668 sock_type
= convert_type ((MonoSocketType
)type
);
669 if (sock_type
== -1) {
670 *werror
= WSAESOCKTNOSUPPORT
;
674 sock
= _wapi_socket (sock_family
, sock_type
, sock_proto
,
675 NULL
, 0, WSA_FLAG_OVERLAPPED
);
677 if (sock
== INVALID_SOCKET
) {
678 *werror
= WSAGetLastError ();
682 return GUINT_TO_POINTER (sock
);
685 /* FIXME: the SOCKET parameter (here and in other functions in this
686 * file) is really an IntPtr which needs to be converted to a guint32.
689 ves_icall_System_Net_Sockets_Socket_Close_internal (SOCKET sock
, gint32
*werror
)
691 LOGDEBUG (g_message ("%s: closing 0x%x", __func__
, sock
));
695 /* Clear any pending work item from this socket if the underlying
696 * polling system does not notify when the socket is closed */
697 mono_threadpool_ms_io_remove_socket (GPOINTER_TO_INT (sock
));
705 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal (void)
707 LOGDEBUG (g_message("%s: returning %d", __func__
, WSAGetLastError ()));
709 return WSAGetLastError ();
713 ves_icall_System_Net_Sockets_Socket_Available_internal (SOCKET sock
, gint32
*werror
)
720 /* FIXME: this might require amount to be unsigned long. */
721 ret
= ioctlsocket (sock
, FIONREAD
, &amount
);
722 if (ret
== SOCKET_ERROR
) {
723 *werror
= WSAGetLastError ();
731 ves_icall_System_Net_Sockets_Socket_Blocking_internal (SOCKET sock
, gboolean block
, gint32
*werror
)
738 * block == TRUE/FALSE means we will block/not block.
739 * But the ioctlsocket call takes TRUE/FALSE for non-block/block
743 ret
= ioctlsocket (sock
, FIONBIO
, (gulong
*)&block
);
744 if (ret
== SOCKET_ERROR
)
745 *werror
= WSAGetLastError ();
749 ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock
, gint32
*werror
, gboolean blocking
)
751 gboolean interrupted
;
756 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
766 MonoInternalThread
*curthread
= mono_thread_internal_current ();
767 curthread
->interrupt_on_stop
= (gpointer
)TRUE
;
768 newsock
= _wapi_accept (sock
, NULL
, 0);
769 curthread
->interrupt_on_stop
= (gpointer
)FALSE
;
772 newsock
= _wapi_accept (sock
, NULL
, 0);
777 if (newsock
== INVALID_SOCKET
)
778 *werror
= WSAGetLastError ();
780 mono_thread_info_uninstall_interrupt (&interrupted
);
787 return GUINT_TO_POINTER (newsock
);
791 ves_icall_System_Net_Sockets_Socket_Listen_internal(SOCKET sock
, guint32 backlog
, gint32
*werror
)
799 ret
= _wapi_listen (sock
, backlog
);
803 if (ret
== SOCKET_ERROR
)
804 *werror
= WSAGetLastError ();
807 // Check whether it's ::ffff::0:0.
809 is_ipv4_mapped_any (const struct in6_addr
*addr
)
813 for (i
= 0; i
< 10; i
++) {
814 if (addr
->s6_addr
[i
])
817 if ((addr
->s6_addr
[10] != 0xff) || (addr
->s6_addr
[11] != 0xff))
819 for (i
= 12; i
< 16; i
++) {
820 if (addr
->s6_addr
[i
])
827 create_object_from_sockaddr (struct sockaddr
*saddr
, int sa_size
, gint32
*werror
, MonoError
*error
)
829 MonoDomain
*domain
= mono_domain_get ();
830 MonoObject
*sockaddr_obj
;
832 MonoAddressFamily family
;
834 mono_error_init (error
);
836 /* Build a System.Net.SocketAddress object instance */
837 if (!domain
->sockaddr_class
)
838 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
839 sockaddr_obj
= mono_object_new_checked (domain
, domain
->sockaddr_class
, error
);
840 return_val_if_nok (error
, NULL
);
842 /* Locate the SocketAddress data buffer in the object */
843 if (!domain
->sockaddr_data_field
) {
844 domain
->sockaddr_data_field
= mono_class_get_field_from_name (domain
->sockaddr_class
, "m_Buffer");
845 g_assert (domain
->sockaddr_data_field
);
848 /* Locate the SocketAddress data buffer length in the object */
849 if (!domain
->sockaddr_data_length_field
) {
850 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name (domain
->sockaddr_class
, "m_Size");
851 g_assert (domain
->sockaddr_data_length_field
);
854 /* May be the +2 here is too conservative, as sa_len returns
855 * the length of the entire sockaddr_in/in6, including
856 * sizeof (unsigned short) of the family */
857 /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/
858 data
= mono_array_new_cached (domain
, mono_get_byte_class (), sa_size
+ 2, error
);
859 return_val_if_nok (error
, NULL
);
861 /* The data buffer is laid out as follows:
862 * bytes 0 and 1 are the address family
863 * bytes 2 and 3 are the port info
864 * the rest is the address info
867 family
= convert_to_mono_family (saddr
->sa_family
);
868 if (family
== AddressFamily_Unknown
) {
869 *werror
= WSAEAFNOSUPPORT
;
873 mono_array_set (data
, guint8
, 0, family
& 0x0FF);
874 mono_array_set (data
, guint8
, 1, (family
>> 8) & 0x0FF);
876 if (saddr
->sa_family
== AF_INET
) {
877 struct sockaddr_in
*sa_in
= (struct sockaddr_in
*)saddr
;
878 guint16 port
= ntohs (sa_in
->sin_port
);
879 guint32 address
= ntohl (sa_in
->sin_addr
.s_addr
);
882 if (sa_size
< buffer_size
) {
883 mono_error_set_exception_instance (error
, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
887 mono_array_set (data
, guint8
, 2, (port
>>8) & 0xff);
888 mono_array_set (data
, guint8
, 3, (port
) & 0xff);
889 mono_array_set (data
, guint8
, 4, (address
>>24) & 0xff);
890 mono_array_set (data
, guint8
, 5, (address
>>16) & 0xff);
891 mono_array_set (data
, guint8
, 6, (address
>>8) & 0xff);
892 mono_array_set (data
, guint8
, 7, (address
) & 0xff);
894 mono_field_set_value (sockaddr_obj
, domain
->sockaddr_data_field
, data
);
895 mono_field_set_value (sockaddr_obj
, domain
->sockaddr_data_length_field
, &buffer_size
);
898 } else if (saddr
->sa_family
== AF_INET6
) {
899 struct sockaddr_in6
*sa_in
= (struct sockaddr_in6
*)saddr
;
901 int buffer_size
= 28;
903 guint16 port
= ntohs (sa_in
->sin6_port
);
905 if (sa_size
< buffer_size
) {
906 mono_error_set_exception_instance (error
, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
910 mono_array_set (data
, guint8
, 2, (port
>>8) & 0xff);
911 mono_array_set (data
, guint8
, 3, (port
) & 0xff);
913 if (is_ipv4_mapped_any (&sa_in
->sin6_addr
)) {
914 // Map ::ffff:0:0 to :: (bug #5502)
915 for (i
= 0; i
< 16; i
++)
916 mono_array_set (data
, guint8
, 8 + i
, 0);
918 for (i
= 0; i
< 16; i
++) {
919 mono_array_set (data
, guint8
, 8 + i
,
920 sa_in
->sin6_addr
.s6_addr
[i
]);
924 mono_array_set (data
, guint8
, 24, sa_in
->sin6_scope_id
& 0xff);
925 mono_array_set (data
, guint8
, 25,
926 (sa_in
->sin6_scope_id
>> 8) & 0xff);
927 mono_array_set (data
, guint8
, 26,
928 (sa_in
->sin6_scope_id
>> 16) & 0xff);
929 mono_array_set (data
, guint8
, 27,
930 (sa_in
->sin6_scope_id
>> 24) & 0xff);
932 mono_field_set_value (sockaddr_obj
, domain
->sockaddr_data_field
, data
);
933 mono_field_set_value (sockaddr_obj
, domain
->sockaddr_data_length_field
, &buffer_size
);
938 else if (saddr
->sa_family
== AF_UNIX
) {
940 int buffer_size
= sa_size
+ 2;
942 for (i
= 0; i
< sa_size
; i
++)
943 mono_array_set (data
, guint8
, i
+ 2, saddr
->sa_data
[i
]);
945 mono_field_set_value (sockaddr_obj
, domain
->sockaddr_data_field
, data
);
946 mono_field_set_value (sockaddr_obj
, domain
->sockaddr_data_length_field
, &buffer_size
);
952 *werror
= WSAEAFNOSUPPORT
;
958 get_sockaddr_size (int family
)
963 if (family
== AF_INET
) {
964 size
= sizeof (struct sockaddr_in
);
965 } else if (family
== AF_INET6
) {
966 size
= sizeof (struct sockaddr_in6
);
969 else if (family
== AF_UNIX
) {
970 size
= sizeof (struct sockaddr_un
);
977 ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (SOCKET sock
, gint32 af
, gint32
*werror
)
987 salen
= get_sockaddr_size (convert_family ((MonoAddressFamily
)af
));
989 *werror
= WSAEAFNOSUPPORT
;
992 sa
= (salen
<= 128) ? (gchar
*)alloca (salen
) : (gchar
*)g_malloc0 (salen
);
996 ret
= _wapi_getsockname (sock
, (struct sockaddr
*)sa
, &salen
);
1000 if (ret
== SOCKET_ERROR
) {
1001 *werror
= WSAGetLastError ();
1007 LOGDEBUG (g_message("%s: bound to %s port %d", __func__
, inet_ntoa (((struct sockaddr_in
*)&sa
)->sin_addr
), ntohs (((struct sockaddr_in
*)&sa
)->sin_port
)));
1009 result
= create_object_from_sockaddr ((struct sockaddr
*)sa
, salen
, werror
, &error
);
1012 if (!mono_error_ok (&error
))
1013 mono_error_set_pending_exception (&error
);
1018 ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (SOCKET sock
, gint32 af
, gint32
*werror
)
1028 salen
= get_sockaddr_size (convert_family ((MonoAddressFamily
)af
));
1030 *werror
= WSAEAFNOSUPPORT
;
1033 sa
= (salen
<= 128) ? (gchar
*)alloca (salen
) : (gchar
*)g_malloc0 (salen
);
1034 /* Note: linux returns just 2 for AF_UNIX. Always. */
1038 ret
= _wapi_getpeername (sock
, (struct sockaddr
*)sa
, &salen
);
1042 if (ret
== SOCKET_ERROR
) {
1043 *werror
= WSAGetLastError ();
1049 LOGDEBUG (g_message("%s: connected to %s port %d", __func__
, inet_ntoa (((struct sockaddr_in
*)&sa
)->sin_addr
), ntohs (((struct sockaddr_in
*)&sa
)->sin_port
)));
1051 result
= create_object_from_sockaddr ((struct sockaddr
*)sa
, salen
, werror
, &error
);
1054 if (!mono_error_ok (&error
))
1055 mono_error_set_pending_exception (&error
);
1059 static struct sockaddr
*
1060 create_sockaddr_from_object (MonoObject
*saddr_obj
, socklen_t
*sa_size
, gint32
*werror
, MonoError
*error
)
1062 MonoDomain
*domain
= mono_domain_get ();
1067 mono_error_init (error
);
1069 if (!domain
->sockaddr_class
)
1070 domain
->sockaddr_class
= mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress");
1072 /* Locate the SocketAddress data buffer in the object */
1073 if (!domain
->sockaddr_data_field
) {
1074 domain
->sockaddr_data_field
= mono_class_get_field_from_name (domain
->sockaddr_class
, "m_Buffer");
1075 g_assert (domain
->sockaddr_data_field
);
1078 /* Locate the SocketAddress data buffer length in the object */
1079 if (!domain
->sockaddr_data_length_field
) {
1080 domain
->sockaddr_data_length_field
= mono_class_get_field_from_name (domain
->sockaddr_class
, "m_Size");
1081 g_assert (domain
->sockaddr_data_length_field
);
1084 data
= *(MonoArray
**)(((char *)saddr_obj
) + domain
->sockaddr_data_field
->offset
);
1086 /* The data buffer is laid out as follows:
1087 * byte 0 is the address family low byte
1088 * byte 1 is the address family high byte
1090 * bytes 2 and 3 are the port info
1091 * the rest is the address info
1093 * the rest is the file name
1095 len
= *(int *)(((char *)saddr_obj
) + domain
->sockaddr_data_length_field
->offset
);
1096 g_assert (len
>= 2);
1098 family
= convert_family ((MonoAddressFamily
)(mono_array_get (data
, guint8
, 0) + (mono_array_get (data
, guint8
, 1) << 8)));
1099 if (family
== AF_INET
) {
1100 struct sockaddr_in
*sa
;
1105 mono_error_set_exception_instance (error
, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
1109 sa
= g_new0 (struct sockaddr_in
, 1);
1110 port
= (mono_array_get (data
, guint8
, 2) << 8) +
1111 mono_array_get (data
, guint8
, 3);
1112 address
= (mono_array_get (data
, guint8
, 4) << 24) +
1113 (mono_array_get (data
, guint8
, 5) << 16 ) +
1114 (mono_array_get (data
, guint8
, 6) << 8) +
1115 mono_array_get (data
, guint8
, 7);
1117 sa
->sin_family
= family
;
1118 sa
->sin_addr
.s_addr
= htonl (address
);
1119 sa
->sin_port
= htons (port
);
1121 *sa_size
= sizeof (struct sockaddr_in
);
1122 return (struct sockaddr
*)sa
;
1123 } else if (family
== AF_INET6
) {
1124 struct sockaddr_in6
*sa
;
1130 mono_error_set_exception_instance (error
, mono_exception_from_name (mono_get_corlib (), "System", "SystemException"));
1134 sa
= g_new0 (struct sockaddr_in6
, 1);
1135 port
= mono_array_get (data
, guint8
, 3) +
1136 (mono_array_get (data
, guint8
, 2) << 8);
1137 scopeid
= mono_array_get (data
, guint8
, 24) +
1138 (mono_array_get (data
, guint8
, 25) << 8) +
1139 (mono_array_get (data
, guint8
, 26) << 16) +
1140 (mono_array_get (data
, guint8
, 27) << 24);
1142 sa
->sin6_family
= family
;
1143 sa
->sin6_port
= htons (port
);
1144 sa
->sin6_scope_id
= scopeid
;
1146 for (i
= 0; i
< 16; i
++)
1147 sa
->sin6_addr
.s6_addr
[i
] = mono_array_get (data
, guint8
, 8 + i
);
1149 *sa_size
= sizeof (struct sockaddr_in6
);
1150 return (struct sockaddr
*)sa
;
1152 #ifdef HAVE_SYS_UN_H
1153 else if (family
== AF_UNIX
) {
1154 struct sockaddr_un
*sock_un
;
1157 /* Need a byte for the '\0' terminator/prefix, and the first
1158 * two bytes hold the SocketAddress family
1160 if (len
- 2 >= sizeof (sock_un
->sun_path
)) {
1161 mono_error_set_exception_instance (error
, mono_get_exception_index_out_of_range ());
1165 sock_un
= g_new0 (struct sockaddr_un
, 1);
1167 sock_un
->sun_family
= family
;
1168 for (i
= 0; i
< len
- 2; i
++)
1169 sock_un
->sun_path
[i
] = mono_array_get (data
, guint8
, i
+ 2);
1172 return (struct sockaddr
*)sock_un
;
1176 *werror
= WSAEAFNOSUPPORT
;
1182 ves_icall_System_Net_Sockets_Socket_Bind_internal (SOCKET sock
, MonoObject
*sockaddr
, gint32
*werror
)
1185 struct sockaddr
*sa
;
1191 sa
= create_sockaddr_from_object (sockaddr
, &sa_size
, werror
, &error
);
1194 if (!mono_error_ok (&error
)) {
1195 mono_error_set_pending_exception (&error
);
1199 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
)));
1201 ret
= _wapi_bind (sock
, sa
, sa_size
);
1203 if (ret
== SOCKET_ERROR
)
1204 *werror
= WSAGetLastError ();
1216 ves_icall_System_Net_Sockets_Socket_Poll_internal (SOCKET sock
, gint mode
,
1217 gint timeout
, gint32
*werror
)
1219 MonoInternalThread
*thread
= mono_thread_internal_current ();
1222 gboolean interrupted
;
1227 pfds
= g_new0 (mono_pollfd
, 1);
1228 pfds
->fd
= GPOINTER_TO_INT (sock
);
1231 case SelectModeRead
:
1232 pfds
->events
= MONO_POLLIN
;
1234 case SelectModeWrite
:
1235 pfds
->events
= MONO_POLLOUT
;
1238 pfds
->events
= MONO_POLLERR
| MONO_POLLHUP
| MONO_POLLNVAL
;
1242 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1243 start
= time (NULL
);
1246 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1255 ret
= mono_poll (pfds
, 1, timeout
);
1259 mono_thread_info_uninstall_interrupt (&interrupted
);
1266 if (timeout
> 0 && ret
< 0) {
1268 int sec
= time (NULL
) - start
;
1270 timeout
-= sec
* 1000;
1278 if (ret
== -1 && errno
== EINTR
) {
1279 if (mono_thread_test_state (thread
, (MonoThreadState
)(ThreadState_AbortRequested
| ThreadState_StopRequested
))) {
1284 /* Suspend requested? */
1285 mono_thread_interruption_checkpoint ();
1289 } while (ret
== -1 && errno
== EINTR
);
1293 *werror
= WSAGetLastError ();
1295 *werror
= errno_to_WSA (errno
, __func__
);
1306 ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock
, MonoObject
*sockaddr
, gint32
*werror
)
1309 struct sockaddr
*sa
;
1312 gboolean interrupted
;
1316 sa
= create_sockaddr_from_object (sockaddr
, &sa_size
, werror
, &error
);
1319 if (!mono_error_ok (&error
)) {
1320 mono_error_set_pending_exception (&error
);
1324 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
)));
1326 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1334 ret
= _wapi_connect (sock
, sa
, sa_size
);
1338 if (ret
== SOCKET_ERROR
)
1339 *werror
= WSAGetLastError ();
1341 mono_thread_info_uninstall_interrupt (&interrupted
);
1348 /* These #defines from mswsock.h from wine. Defining them here allows
1349 * us to build this file on a mingw box that doesn't know the magic
1350 * numbers, but still run on a newer windows box that does.
1352 #ifndef WSAID_DISCONNECTEX
1353 #define WSAID_DISCONNECTEX {0x7fda2e11,0x8630,0x436f,{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}
1354 typedef BOOL (WINAPI
*LPFN_DISCONNECTEX
)(SOCKET
, LPOVERLAPPED
, DWORD
, DWORD
);
1357 #ifndef WSAID_TRANSMITFILE
1358 #define WSAID_TRANSMITFILE {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
1359 typedef BOOL (WINAPI
*LPFN_TRANSMITFILE
)(SOCKET
, HANDLE
, DWORD
, DWORD
, LPOVERLAPPED
, LPTRANSMIT_FILE_BUFFERS
, DWORD
);
1363 ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock
, MonoBoolean reuse
, gint32
*werror
)
1366 glong output_bytes
= 0;
1367 GUID disco_guid
= WSAID_DISCONNECTEX
;
1368 GUID trans_guid
= WSAID_TRANSMITFILE
;
1369 LPFN_DISCONNECTEX _wapi_disconnectex
= NULL
;
1370 LPFN_TRANSMITFILE _wapi_transmitfile
= NULL
;
1371 gboolean interrupted
;
1375 LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__
, sock
, reuse
));
1379 /* I _think_ the extension function pointers need to be looked
1380 * up for each socket. FIXME: check the best way to store
1381 * pointers to functions in managed objects that still works
1382 * on 64bit platforms.
1384 ret
= WSAIoctl (sock
, SIO_GET_EXTENSION_FUNCTION_POINTER
, (gchar
*)&disco_guid
, sizeof (GUID
),
1385 (gchar
*)&_wapi_disconnectex
, sizeof (void *), &output_bytes
, NULL
, NULL
);
1390 /* make sure that WSAIoctl didn't put crap in the
1393 _wapi_disconnectex
= NULL
;
1398 * Use the SIO_GET_EXTENSION_FUNCTION_POINTER to
1399 * determine the address of the disconnect method without
1400 * taking a hard dependency on a single provider
1402 * For an explanation of why this is done, you can read
1403 * the article at http://www.codeproject.com/internet/jbsocketserver3.asp
1405 ret
= WSAIoctl (sock
, SIO_GET_EXTENSION_FUNCTION_POINTER
, (gchar
*)&trans_guid
, sizeof(GUID
),
1406 (gchar
*)&_wapi_transmitfile
, sizeof(void *), &output_bytes
, NULL
, NULL
);
1411 _wapi_transmitfile
= NULL
;
1414 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1422 if (_wapi_disconnectex
!= NULL
) {
1423 if (!_wapi_disconnectex (sock
, NULL
, reuse
? TF_REUSE_SOCKET
: 0, 0))
1424 *werror
= WSAGetLastError ();
1425 } else if (_wapi_transmitfile
!= NULL
) {
1426 if (!_wapi_transmitfile (sock
, NULL
, 0, 0, NULL
, NULL
, TF_DISCONNECT
| (reuse
? TF_REUSE_SOCKET
: 0)))
1427 *werror
= WSAGetLastError ();
1429 *werror
= ERROR_NOT_SUPPORTED
;
1434 mono_thread_info_uninstall_interrupt (&interrupted
);
1440 ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock
, MonoArray
*buffer
, gint32 offset
, gint32 count
, gint32 flags
, gint32
*werror
)
1446 gboolean interrupted
;
1447 MonoInternalThread
* curthread G_GNUC_UNUSED
= mono_thread_internal_current ();
1451 alen
= mono_array_length (buffer
);
1452 if (offset
> alen
- count
)
1455 buf
= mono_array_addr (buffer
, guchar
, offset
);
1457 recvflags
= convert_socketflags (flags
);
1458 if (recvflags
== -1) {
1459 *werror
= WSAEOPNOTSUPP
;
1463 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1471 curthread
->interrupt_on_stop
= (gpointer
)TRUE
;
1472 ret
= _wapi_recv (sock
, buf
, count
, recvflags
);
1473 curthread
->interrupt_on_stop
= (gpointer
)FALSE
;
1476 ret
= _wapi_recv (sock
, buf
, count
, recvflags
);
1481 if (ret
== SOCKET_ERROR
)
1482 *werror
= WSAGetLastError ();
1484 mono_thread_info_uninstall_interrupt (&interrupted
);
1495 ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock
, MonoArray
*buffers
, gint32 flags
, gint32
*werror
)
1498 gboolean interrupted
;
1501 DWORD recvflags
= 0;
1505 wsabufs
= mono_array_addr (buffers
, WSABUF
, 0);
1506 count
= mono_array_length (buffers
);
1508 recvflags
= convert_socketflags (flags
);
1509 if (recvflags
== -1) {
1510 *werror
= WSAEOPNOTSUPP
;
1514 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1522 ret
= WSARecv (sock
, wsabufs
, count
, &recv
, &recvflags
, NULL
, NULL
);
1526 if (ret
== SOCKET_ERROR
)
1527 *werror
= WSAGetLastError ();
1529 mono_thread_info_uninstall_interrupt (&interrupted
);
1540 ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock
, MonoArray
*buffer
, gint32 offset
, gint32 count
, gint32 flags
, MonoObject
**sockaddr
, gint32
*werror
)
1547 struct sockaddr
*sa
;
1549 gboolean interrupted
;
1553 alen
= mono_array_length (buffer
);
1554 if (offset
> alen
- count
)
1557 sa
= create_sockaddr_from_object (*sockaddr
, &sa_size
, werror
, &error
);
1560 if (!mono_error_ok (&error
)) {
1561 mono_error_set_pending_exception (&error
);
1565 buf
= mono_array_addr (buffer
, guchar
, offset
);
1567 recvflags
= convert_socketflags (flags
);
1568 if (recvflags
== -1) {
1569 *werror
= WSAEOPNOTSUPP
;
1573 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1582 ret
= _wapi_recvfrom (sock
, buf
, count
, recvflags
, sa
, &sa_size
);
1586 if (ret
== SOCKET_ERROR
)
1587 *werror
= WSAGetLastError ();
1589 mono_thread_info_uninstall_interrupt (&interrupted
);
1599 /* If we didn't get a socket size, then we're probably a
1600 * connected connection-oriented socket and the stack hasn't
1601 * returned the remote address. All we can do is return null.
1604 *sockaddr
= create_object_from_sockaddr (sa
, sa_size
, werror
, &error
);
1605 if (!mono_error_ok (&error
)) {
1606 mono_error_set_pending_exception (&error
);
1620 ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock
, MonoArray
*buffer
, gint32 offset
, gint32 count
, gint32 flags
, gint32
*werror
)
1626 gboolean interrupted
;
1630 alen
= mono_array_length (buffer
);
1631 if (offset
> alen
- count
)
1634 LOGDEBUG (g_message("%s: alen: %d", __func__
, alen
));
1636 buf
= mono_array_addr (buffer
, guchar
, offset
);
1638 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1640 sendflags
= convert_socketflags (flags
);
1641 if (sendflags
== -1) {
1642 *werror
= WSAEOPNOTSUPP
;
1646 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1654 ret
= _wapi_send (sock
, buf
, count
, sendflags
);
1658 if (ret
== SOCKET_ERROR
)
1659 *werror
= WSAGetLastError ();
1661 mono_thread_info_uninstall_interrupt (&interrupted
);
1672 ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock
, MonoArray
*buffers
, gint32 flags
, gint32
*werror
)
1677 DWORD sendflags
= 0;
1678 gboolean interrupted
;
1682 wsabufs
= mono_array_addr (buffers
, WSABUF
, 0);
1683 count
= mono_array_length (buffers
);
1685 sendflags
= convert_socketflags (flags
);
1686 if (sendflags
== -1) {
1687 *werror
= WSAEOPNOTSUPP
;
1691 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1699 ret
= WSASend (sock
, wsabufs
, count
, &sent
, sendflags
, NULL
, NULL
);
1703 if (ret
== SOCKET_ERROR
)
1704 *werror
= WSAGetLastError ();
1706 mono_thread_info_uninstall_interrupt (&interrupted
);
1717 ves_icall_System_Net_Sockets_Socket_SendTo_internal (SOCKET sock
, MonoArray
*buffer
, gint32 offset
, gint32 count
, gint32 flags
, MonoObject
*sockaddr
, gint32
*werror
)
1724 struct sockaddr
*sa
;
1726 gboolean interrupted
;
1730 alen
= mono_array_length (buffer
);
1731 if (offset
> alen
- count
) {
1735 sa
= create_sockaddr_from_object(sockaddr
, &sa_size
, werror
, &error
);
1738 if (!mono_error_ok (&error
)) {
1739 mono_error_set_pending_exception (&error
);
1743 LOGDEBUG (g_message ("%s: alen: %d", __func__
, alen
));
1745 buf
= mono_array_addr (buffer
, guchar
, offset
);
1747 LOGDEBUG (g_message("%s: Sending %d bytes", __func__
, count
));
1749 sendflags
= convert_socketflags (flags
);
1750 if (sendflags
== -1) {
1752 *werror
= WSAEOPNOTSUPP
;
1756 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1765 ret
= _wapi_sendto (sock
, buf
, count
, sendflags
, sa
, sa_size
);
1769 if (ret
== SOCKET_ERROR
)
1770 *werror
= WSAGetLastError ();
1772 mono_thread_info_uninstall_interrupt (&interrupted
);
1785 Socket_to_SOCKET (MonoObject
*sockobj
)
1787 MonoSafeHandle
*safe_handle
;
1788 MonoClassField
*field
;
1790 field
= mono_class_get_field_from_name (sockobj
->vtable
->klass
, "m_Handle");
1791 safe_handle
= ((MonoSafeHandle
*)(*(gpointer
*)(((char *)sockobj
) + field
->offset
)));
1793 if (safe_handle
== NULL
)
1796 return (SOCKET
)safe_handle
->handle
;
1799 #define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
1802 ves_icall_System_Net_Sockets_Socket_Select_internal (MonoArray
**sockets
, gint32 timeout
, gint32
*werror
)
1805 MonoInternalThread
*thread
= mono_thread_internal_current ();
1812 MonoClass
*sock_arr_class
;
1815 uintptr_t socks_size
;
1816 gboolean interrupted
;
1820 /* *sockets -> READ, null, WRITE, null, ERROR, null */
1821 count
= mono_array_length (*sockets
);
1822 nfds
= count
- 3; /* NULL separators */
1823 pfds
= g_new0 (mono_pollfd
, nfds
);
1825 for (i
= 0; i
< count
; i
++) {
1826 obj
= mono_array_get (*sockets
, MonoObject
*, i
);
1833 /* The socket array was bogus */
1835 *werror
= WSAEFAULT
;
1839 pfds
[idx
].fd
= Socket_to_SOCKET (obj
);
1840 pfds
[idx
].events
= (mode
== 0) ? MONO_POLLIN
: (mode
== 1) ? MONO_POLLOUT
: POLL_ERRORS
;
1844 timeout
= (timeout
>= 0) ? (timeout
/ 1000) : -1;
1845 start
= time (NULL
);
1847 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
1856 ret
= mono_poll (pfds
, nfds
, timeout
);
1860 mono_thread_info_uninstall_interrupt (&interrupted
);
1867 if (timeout
> 0 && ret
< 0) {
1869 int sec
= time (NULL
) - start
;
1871 timeout
-= sec
* 1000;
1877 if (ret
== -1 && errno
== EINTR
) {
1878 if (mono_thread_test_state (thread
, (MonoThreadState
)(ThreadState_AbortRequested
| ThreadState_StopRequested
))) {
1884 /* Suspend requested? */
1885 mono_thread_interruption_checkpoint ();
1889 } while (ret
== -1 && errno
== EINTR
);
1893 *werror
= WSAGetLastError ();
1895 *werror
= errno_to_WSA (errno
, __func__
);
1907 sock_arr_class
= ((MonoObject
*)*sockets
)->vtable
->klass
;
1908 socks_size
= ((uintptr_t)ret
) + 3; /* space for the NULL delimiters */
1909 socks
= mono_array_new_full_checked (mono_domain_get (), sock_arr_class
, &socks_size
, NULL
, &error
);
1910 if (!mono_error_ok (&error
)) {
1911 mono_error_set_pending_exception (&error
);
1917 for (i
= 0; i
< count
&& ret
> 0; i
++) {
1920 obj
= mono_array_get (*sockets
, MonoObject
*, i
);
1927 pfd
= &pfds
[i
- mode
];
1928 if (pfd
->revents
== 0)
1932 if (mode
== 0 && (pfd
->revents
& (MONO_POLLIN
| POLL_ERRORS
)) != 0) {
1933 mono_array_setref (socks
, idx
++, obj
);
1934 } else if (mode
== 1 && (pfd
->revents
& (MONO_POLLOUT
| POLL_ERRORS
)) != 0) {
1935 mono_array_setref (socks
, idx
++, obj
);
1936 } else if ((pfd
->revents
& POLL_ERRORS
) != 0) {
1937 mono_array_setref (socks
, idx
++, obj
);
1946 int_to_object (MonoDomain
*domain
, int val
, MonoError
*error
)
1948 return mono_value_box_checked (domain
, mono_get_int32_class (), &val
, error
);
1952 ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock
, gint32 level
, gint32 name
, MonoObject
**obj_val
, gint32
*werror
)
1954 int system_level
= 0;
1955 int system_name
= 0;
1958 socklen_t valsize
= sizeof (val
);
1959 struct linger linger
;
1960 socklen_t lingersize
= sizeof (linger
);
1962 socklen_t time_ms_size
= sizeof (time_ms
);
1964 # if defined(__OpenBSD__)
1965 struct sockpeercred cred
;
1969 socklen_t credsize
= sizeof (cred
);
1972 MonoDomain
*domain
= mono_domain_get ();
1974 MonoClass
*obj_class
;
1975 MonoClassField
*field
;
1979 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
1980 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
1981 system_level
= SOL_SOCKET
;
1982 system_name
= SO_REUSEADDR
;
1987 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
, &system_name
);
1991 *werror
= WSAENOPROTOOPT
;
1995 *obj_val
= int_to_object (domain
, 0, &error
);
1996 mono_error_set_pending_exception (&error
);
2002 /* No need to deal with MulticastOption names here, because
2003 * you cant getsockopt AddMembership or DropMembership (the
2004 * int getsockopt will error, causing an exception)
2007 case SocketOptionName_Linger
:
2008 case SocketOptionName_DontLinger
:
2009 ret
= _wapi_getsockopt (sock
, system_level
, system_name
, &linger
, &lingersize
);
2012 case SocketOptionName_SendTimeout
:
2013 case SocketOptionName_ReceiveTimeout
:
2014 ret
= _wapi_getsockopt (sock
, system_level
, system_name
, (char *)&time_ms
, &time_ms_size
);
2018 case SocketOptionName_PeerCred
:
2019 ret
= _wapi_getsockopt (sock
, system_level
, system_name
, &cred
, &credsize
);
2024 ret
= _wapi_getsockopt (sock
, system_level
, system_name
, &val
, &valsize
);
2029 if (ret
== SOCKET_ERROR
) {
2030 *werror
= WSAGetLastError ();
2035 case SocketOptionName_Linger
:
2036 /* build a System.Net.Sockets.LingerOption */
2037 obj_class
= mono_class_load_from_name (get_socket_assembly (),
2038 "System.Net.Sockets",
2040 obj
= mono_object_new_checked (domain
, obj_class
, &error
);
2041 if (!mono_error_ok (&error
)) {
2042 mono_error_set_pending_exception (&error
);
2046 /* Locate and set the fields "bool enabled" and "int
2049 field
= mono_class_get_field_from_name(obj_class
, "enabled");
2050 *(guint8
*)(((char *)obj
)+field
->offset
) = linger
.l_onoff
;
2052 field
= mono_class_get_field_from_name(obj_class
, "lingerTime");
2053 *(guint32
*)(((char *)obj
)+field
->offset
)=linger
.l_linger
;
2055 case SocketOptionName_DontLinger
:
2056 /* construct a bool int in val - true if linger is off */
2057 obj
= int_to_object (domain
, !linger
.l_onoff
, &error
);
2058 mono_error_set_pending_exception (&error
);
2060 case SocketOptionName_SendTimeout
:
2061 case SocketOptionName_ReceiveTimeout
:
2062 obj
= int_to_object (domain
, time_ms
, &error
);
2063 mono_error_set_pending_exception (&error
);
2067 case SocketOptionName_PeerCred
: {
2069 * build a Mono.Posix.PeerCred+PeerCredData if
2072 static MonoImage
*mono_posix_image
= NULL
;
2073 MonoPeerCredData
*cred_data
;
2075 if (mono_posix_image
== NULL
) {
2076 mono_posix_image
= mono_image_loaded ("Mono.Posix");
2077 if (!mono_posix_image
) {
2078 MonoAssembly
*sa
= mono_assembly_open ("Mono.Posix.dll", NULL
);
2080 *werror
= WSAENOPROTOOPT
;
2083 mono_posix_image
= mono_assembly_get_image (sa
);
2088 obj_class
= mono_class_load_from_name (mono_posix_image
,
2091 obj
= mono_object_new_checked (domain
, obj_class
, &error
);
2092 if (!mono_error_ok (&error
)) {
2093 mono_error_set_pending_exception (&error
);
2096 cred_data
= (MonoPeerCredData
*)obj
;
2097 cred_data
->pid
= cred
.pid
;
2098 cred_data
->uid
= cred
.uid
;
2099 cred_data
->gid
= cred
.gid
;
2105 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2106 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
)
2109 obj
= int_to_object (domain
, val
, &error
);
2110 mono_error_set_pending_exception (&error
);
2117 ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (SOCKET sock
, gint32 level
, gint32 name
, MonoArray
**byte_val
, gint32
*werror
)
2119 int system_level
= 0;
2120 int system_name
= 0;
2127 ret
= convert_sockopt_level_and_name((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
2130 *werror
= WSAENOPROTOOPT
;
2136 valsize
= mono_array_length (*byte_val
);
2137 buf
= mono_array_addr (*byte_val
, guchar
, 0);
2141 ret
= _wapi_getsockopt (sock
, system_level
, system_name
, buf
, &valsize
);
2145 if (ret
== SOCKET_ERROR
)
2146 *werror
= WSAGetLastError ();
2149 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2150 static struct in_addr
2151 ipaddress_to_struct_in_addr (MonoObject
*ipaddr
)
2153 struct in_addr inaddr
;
2154 MonoClassField
*field
;
2156 field
= mono_class_get_field_from_name (ipaddr
->vtable
->klass
, "m_Address");
2158 /* No idea why .net uses a 64bit type to hold a 32bit value...
2160 * Internal value of IPAddess is in little-endian order
2162 inaddr
.s_addr
= GUINT_FROM_LE ((guint32
)*(guint64
*)(((char *)ipaddr
) + field
->offset
));
2167 static struct in6_addr
2168 ipaddress_to_struct_in6_addr (MonoObject
*ipaddr
)
2170 struct in6_addr in6addr
;
2171 MonoClassField
*field
;
2175 field
= mono_class_get_field_from_name (ipaddr
->vtable
->klass
, "m_Numbers");
2177 data
= *(MonoArray
**)(((char *)ipaddr
) + field
->offset
);
2179 for (i
= 0; i
< 8; i
++) {
2180 const guint16 s
= GUINT16_TO_BE (mono_array_get (data
, guint16
, i
));
2182 /* Solaris/MacOS have only the 8 bit version. */
2184 in6addr
.s6_addr
[2 * i
+ 1] = (s
>> 8) & 0xff;
2185 in6addr
.s6_addr
[2 * i
] = s
& 0xff;
2187 in6addr
.s6_addr16
[i
] = s
;
2194 #if defined(__APPLE__) || defined(__FreeBSD__)
2197 get_local_interface_id (int family
)
2199 #if !defined(HAVE_GETIFADDRS) || !defined(HAVE_IF_NAMETOINDEX)
2202 struct ifaddrs
*ifap
= NULL
, *ptr
;
2205 if (getifaddrs (&ifap
))
2208 for (ptr
= ifap
; ptr
; ptr
= ptr
->ifa_next
) {
2209 if (!ptr
->ifa_addr
|| !ptr
->ifa_name
)
2211 if (ptr
->ifa_addr
->sa_family
!= family
)
2213 if ((ptr
->ifa_flags
& IFF_LOOPBACK
) != 0)
2215 if ((ptr
->ifa_flags
& IFF_MULTICAST
) == 0)
2218 idx
= if_nametoindex (ptr
->ifa_name
);
2227 #endif /* defined(__APPLE__) || defined(__FreeBSD__) */
2230 ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal (SOCKET sock
, gint32 level
, gint32 name
, MonoObject
*obj_val
, MonoArray
*byte_val
, gint32 int_val
, gint32
*werror
)
2232 struct linger linger
;
2233 int system_level
= 0;
2234 int system_name
= 0;
2241 sol_ipv6
= mono_networking_get_ipv6_protocol ();
2242 sol_ip
= mono_networking_get_ip_protocol ();
2244 ret
= convert_sockopt_level_and_name ((MonoSocketOptionLevel
)level
, (MonoSocketOptionName
)name
, &system_level
,
2247 #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR)
2248 if (level
== SocketOptionLevel_Socket
&& name
== SocketOptionName_ExclusiveAddressUse
) {
2249 system_name
= SO_REUSEADDR
;
2250 int_val
= int_val
? 0 : 1;
2256 *werror
= WSAENOPROTOOPT
;
2262 /* Only one of obj_val, byte_val or int_val has data */
2264 MonoClassField
*field
;
2268 case SocketOptionName_Linger
:
2269 /* Dig out "bool enabled" and "int lingerTime"
2272 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "enabled");
2273 linger
.l_onoff
= *(guint8
*)(((char *)obj_val
) + field
->offset
);
2274 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "lingerTime");
2275 linger
.l_linger
= *(guint32
*)(((char *)obj_val
) + field
->offset
);
2277 valsize
= sizeof (linger
);
2278 ret
= _wapi_setsockopt (sock
, system_level
,
2279 system_name
, &linger
, valsize
);
2281 case SocketOptionName_AddMembership
:
2282 case SocketOptionName_DropMembership
:
2283 #if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ)
2285 MonoObject
*address
= NULL
;
2287 if (system_level
== sol_ipv6
) {
2288 struct ipv6_mreq mreq6
;
2293 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "m_Group");
2295 address
= *(MonoObject
**)(((char *)obj_val
) + field
->offset
);
2298 mreq6
.ipv6mr_multiaddr
= ipaddress_to_struct_in6_addr (address
);
2300 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "m_Interface");
2301 mreq6
.ipv6mr_interface
= *(guint64
*)(((char *)obj_val
) + field
->offset
);
2303 #if defined(__APPLE__) || defined(__FreeBSD__)
2307 * Mac OS Lion doesn't allow ipv6mr_interface = 0.
2309 * Tests on Windows and Linux show that the multicast group is only
2310 * joined on one NIC when interface = 0, so we simply use the interface
2311 * id from the first non-loopback interface (this is also what
2312 * Dns.GetHostName (string.Empty) would return).
2314 if (!mreq6
.ipv6mr_interface
)
2315 mreq6
.ipv6mr_interface
= get_local_interface_id (AF_INET6
);
2318 ret
= _wapi_setsockopt (sock
, system_level
,
2319 system_name
, &mreq6
,
2321 } else if (system_level
== sol_ip
) {
2322 #ifdef HAVE_STRUCT_IP_MREQN
2323 struct ip_mreqn mreq
= {{0}};
2325 struct ip_mreq mreq
= {{0}};
2326 #endif /* HAVE_STRUCT_IP_MREQN */
2329 * pain! MulticastOption holds two IPAddress
2330 * members, so I have to dig the value out of
2333 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "group");
2334 address
= *(MonoObject
**)(((char *)obj_val
) + field
->offset
);
2336 /* address might not be defined and if so, set the address to ADDR_ANY.
2339 mreq
.imr_multiaddr
= ipaddress_to_struct_in_addr (address
);
2341 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "localAddress");
2342 address
= *(MonoObject
**)(((char *)obj_val
) + field
->offset
);
2344 #ifdef HAVE_STRUCT_IP_MREQN
2346 mreq
.imr_address
= ipaddress_to_struct_in_addr (address
);
2348 field
= mono_class_get_field_from_name (obj_val
->vtable
->klass
, "ifIndex");
2349 mreq
.imr_ifindex
= *(gint32
*)(((char *)obj_val
) + field
->offset
);
2352 mreq
.imr_interface
= ipaddress_to_struct_in_addr (address
);
2353 #endif /* HAVE_STRUCT_IP_MREQN */
2355 ret
= _wapi_setsockopt (sock
, system_level
,
2361 #endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */
2363 /* Cause an exception to be thrown */
2364 *werror
= WSAEINVAL
;
2367 } else if (byte_val
!=NULL
) {
2368 int valsize
= mono_array_length (byte_val
);
2369 guchar
*buf
= mono_array_addr (byte_val
, guchar
, 0);
2372 case SocketOptionName_DontLinger
:
2374 linger
.l_onoff
= (*buf
) ? 0 : 1;
2375 linger
.l_linger
= 0;
2376 ret
= _wapi_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2378 *werror
= WSAEINVAL
;
2382 ret
= _wapi_setsockopt (sock
, system_level
, system_name
, buf
, valsize
);
2386 /* ReceiveTimeout/SendTimeout get here */
2388 case SocketOptionName_DontLinger
:
2389 linger
.l_onoff
= !int_val
;
2390 linger
.l_linger
= 0;
2391 ret
= _wapi_setsockopt (sock
, system_level
, system_name
, &linger
, sizeof (linger
));
2393 case SocketOptionName_MulticastInterface
:
2395 #ifdef HAVE_STRUCT_IP_MREQN
2396 int_val
= GUINT32_FROM_BE (int_val
);
2397 if ((int_val
& 0xff000000) == 0) {
2398 /* int_val is interface index */
2399 struct ip_mreqn mreq
= {{0}};
2400 mreq
.imr_ifindex
= int_val
;
2401 ret
= _wapi_setsockopt (sock
, system_level
, system_name
, (char *) &mreq
, sizeof (mreq
));
2404 int_val
= GUINT32_TO_BE (int_val
);
2405 #endif /* HAVE_STRUCT_IP_MREQN */
2406 #endif /* HOST_WIN32 */
2407 /* int_val is in_addr */
2408 ret
= _wapi_setsockopt (sock
, system_level
, system_name
, (char *) &int_val
, sizeof (int_val
));
2410 case SocketOptionName_DontFragment
:
2411 #ifdef HAVE_IP_MTU_DISCOVER
2412 /* Fiddle with the value slightly if we're
2416 int_val
= IP_PMTUDISC_DO
;
2421 ret
= _wapi_setsockopt (sock
, system_level
, system_name
, (char *) &int_val
, sizeof (int_val
));
2425 if (ret
== SOCKET_ERROR
)
2426 *werror
= WSAGetLastError ();
2430 ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock
, gint32 how
, gint32
*werror
)
2433 gboolean interrupted
;
2437 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
2445 /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
2446 ret
= _wapi_shutdown (sock
, how
);
2450 if (ret
== SOCKET_ERROR
)
2451 *werror
= WSAGetLastError ();
2453 mono_thread_info_uninstall_interrupt (&interrupted
);
2461 ves_icall_System_Net_Sockets_Socket_IOControl_internal (SOCKET sock
, gint32 code
, MonoArray
*input
, MonoArray
*output
, gint32
*werror
)
2463 glong output_bytes
= 0;
2464 gchar
*i_buffer
, *o_buffer
;
2470 if ((guint32
)code
== FIONBIO
)
2471 /* Invalid command. Must use Socket.Blocking */
2474 if (input
== NULL
) {
2478 i_buffer
= mono_array_addr (input
, gchar
, 0);
2479 i_len
= mono_array_length (input
);
2482 if (output
== NULL
) {
2486 o_buffer
= mono_array_addr (output
, gchar
, 0);
2487 o_len
= mono_array_length (output
);
2492 ret
= WSAIoctl (sock
, code
, i_buffer
, i_len
, o_buffer
, o_len
, &output_bytes
, NULL
, NULL
);
2496 if (ret
== SOCKET_ERROR
) {
2497 *werror
= WSAGetLastError ();
2501 return (gint
)output_bytes
;
2505 addrinfo_to_IPHostEntry (MonoAddressInfo
*info
, MonoString
**h_name
, MonoArray
**h_aliases
, MonoArray
**h_addr_list
, gboolean add_local_ips
, MonoError
*error
)
2508 MonoAddressEntry
*ai
= NULL
;
2509 struct in_addr
*local_in
= NULL
;
2511 struct in6_addr
*local_in6
= NULL
;
2514 MonoDomain
*domain
= mono_domain_get ();
2516 mono_error_init (error
);
2518 *h_aliases
= mono_array_new_checked (domain
, mono_get_string_class (), 0, error
);
2519 return_val_if_nok (error
, FALSE
);
2520 if (add_local_ips
) {
2521 local_in
= (struct in_addr
*) mono_get_local_interfaces (AF_INET
, &nlocal_in
);
2522 local_in6
= (struct in6_addr
*) mono_get_local_interfaces (AF_INET6
, &nlocal_in6
);
2523 if (nlocal_in
|| nlocal_in6
) {
2524 char addr
[INET6_ADDRSTRLEN
];
2525 *h_addr_list
= mono_array_new_checked (domain
, mono_get_string_class (), nlocal_in
+ nlocal_in6
, error
);
2530 MonoString
*addr_string
;
2533 for (i
= 0; i
< nlocal_in
; i
++) {
2535 mono_address_init (&maddr
, AF_INET
, &local_in
[i
]);
2536 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2537 addr_string
= mono_string_new (domain
, addr
);
2538 mono_array_setref (*h_addr_list
, addr_index
, addr_string
);
2545 MonoString
*addr_string
;
2548 for (i
= 0; i
< nlocal_in6
; i
++) {
2550 mono_address_init (&maddr
, AF_INET6
, &local_in6
[i
]);
2551 if (mono_networking_addr_to_str (&maddr
, addr
, sizeof (addr
))) {
2552 addr_string
= mono_string_new (domain
, addr
);
2553 mono_array_setref (*h_addr_list
, addr_index
, addr_string
);
2563 mono_free_address_info (info
);
2564 return is_ok (error
);;
2571 for (count
= 0, ai
= info
->entries
; ai
!= NULL
; ai
= ai
->next
) {
2572 if (ai
->family
!= AF_INET
&& ai
->family
!= AF_INET6
)
2577 *h_addr_list
= mono_array_new_checked (domain
, mono_get_string_class (), count
, error
);
2581 for (ai
= info
->entries
, i
= 0; ai
!= NULL
; ai
= ai
->next
) {
2583 MonoString
*addr_string
;
2584 char buffer
[INET6_ADDRSTRLEN
]; /* Max. size for IPv6 */
2586 if ((ai
->family
!= PF_INET
) && (ai
->family
!= PF_INET6
))
2589 mono_address_init (&maddr
, ai
->family
, &ai
->address
);
2590 if (mono_networking_addr_to_str (&maddr
, buffer
, sizeof (buffer
)))
2591 addr_string
= mono_string_new (domain
, buffer
);
2593 addr_string
= mono_string_new (domain
, "");
2595 mono_array_setref (*h_addr_list
, addr_index
, addr_string
);
2599 if (ai
->canonical_name
!= NULL
) {
2600 *h_name
= mono_string_new (domain
, ai
->canonical_name
);
2602 *h_name
= mono_string_new (domain
, buffer
);
2611 mono_free_address_info (info
);
2613 return is_ok (error
);
2617 get_addrinfo_family_hint (MonoError
*error
)
2621 mono_error_init (error
);
2623 hint
= get_family_hint (error
);
2624 return_val_if_nok (error
, 0);
2628 return MONO_HINT_UNSPECIFIED
;
2630 return MONO_HINT_IPV4
;
2633 return MONO_HINT_IPV6
;
2636 g_error ("invalid hint");
2642 ves_icall_System_Net_Dns_GetHostByName_internal (MonoString
*host
, MonoString
**h_name
, MonoArray
**h_aliases
, MonoArray
**h_addr_list
)
2645 gboolean add_local_ips
= FALSE
, add_info_ok
= TRUE
;
2646 gchar this_hostname
[256];
2647 MonoAddressInfo
*info
= NULL
;
2650 char *hostname
= mono_string_to_utf8_checked (host
, &error
);
2651 if (mono_error_set_pending_exception (&error
))
2654 hint
= get_addrinfo_family_hint (&error
);
2655 if (!mono_error_ok (&error
)) {
2656 mono_error_set_pending_exception (&error
);
2660 if (*hostname
== '\0') {
2661 add_local_ips
= TRUE
;
2665 if (!add_local_ips
&& gethostname (this_hostname
, sizeof (this_hostname
)) != -1) {
2666 if (!strcmp (hostname
, this_hostname
)) {
2667 add_local_ips
= TRUE
;
2673 // Win32 APIs already returns local interface addresses for empty hostname ("")
2674 // so we never want to add them manually.
2675 add_local_ips
= FALSE
;
2676 if (mono_get_address_info(hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2677 add_info_ok
= FALSE
;
2679 if (*hostname
&& mono_get_address_info (hostname
, 0, MONO_HINT_CANONICAL_NAME
| hint
, &info
))
2680 add_info_ok
= FALSE
;
2686 MonoBoolean result
= addrinfo_to_IPHostEntry (info
, h_name
, h_aliases
, h_addr_list
, add_local_ips
, &error
);
2687 mono_error_set_pending_exception (&error
);
2694 ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoString
*addr
, MonoString
**h_name
, MonoArray
**h_aliases
, MonoArray
**h_addr_list
)
2697 struct sockaddr_in saddr
;
2698 struct sockaddr_in6 saddr6
;
2699 MonoAddressInfo
*info
= NULL
;
2701 gint32 family
, hint
;
2702 gchar hostname
[NI_MAXHOST
] = { 0 };
2705 address
= mono_string_to_utf8_checked (addr
, &error
);
2706 if (mono_error_set_pending_exception (&error
))
2709 if (inet_pton (AF_INET
, address
, &saddr
.sin_addr
) == 1) {
2711 saddr
.sin_family
= AF_INET
;
2712 } else if (inet_pton (AF_INET6
, address
, &saddr6
.sin6_addr
) == 1) {
2714 saddr6
.sin6_family
= AF_INET6
;
2726 #if HAVE_SOCKADDR_IN_SIN_LEN
2727 saddr
.sin_len
= sizeof (saddr
);
2729 ret
= getnameinfo ((struct sockaddr
*)&saddr
, sizeof (saddr
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2733 #if HAVE_SOCKADDR_IN6_SIN_LEN
2734 saddr6
.sin6_len
= sizeof (saddr6
);
2736 ret
= getnameinfo ((struct sockaddr
*)&saddr6
, sizeof (saddr6
), hostname
, sizeof (hostname
), NULL
, 0, 0) == 0;
2740 g_assert_not_reached ();
2748 hint
= get_addrinfo_family_hint (&error
);
2749 if (!mono_error_ok (&error
)) {
2750 mono_error_set_pending_exception (&error
);
2753 if (mono_get_address_info (hostname
, 0, hint
| MONO_HINT_CANONICAL_NAME
| MONO_HINT_CONFIGURED_ONLY
, &info
) != 0)
2756 MonoBoolean result
= addrinfo_to_IPHostEntry (info
, h_name
, h_aliases
, h_addr_list
, FALSE
, &error
);
2757 mono_error_set_pending_exception (&error
);
2762 ves_icall_System_Net_Dns_GetHostName_internal (MonoString
**h_name
)
2764 gchar hostname
[NI_MAXHOST
] = { 0 };
2767 ret
= gethostname (hostname
, sizeof (hostname
));
2771 *h_name
= mono_string_new (mono_domain_get (), hostname
);
2777 ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock
, MonoString
*filename
, MonoArray
*pre_buffer
, MonoArray
*post_buffer
, gint flags
)
2782 gboolean interrupted
;
2783 TRANSMIT_FILE_BUFFERS buffers
;
2785 if (filename
== NULL
)
2788 /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
2790 file
= ves_icall_System_IO_MonoIO_Open (filename
, FileMode_Open
, FileAccess_Read
, FileShare_Read
, 0, &werror
);
2792 if (file
== INVALID_HANDLE_VALUE
) {
2793 SetLastError (werror
);
2797 memset (&buffers
, 0, sizeof (buffers
));
2798 if (pre_buffer
!= NULL
) {
2799 buffers
.Head
= mono_array_addr (pre_buffer
, guchar
, 0);
2800 buffers
.HeadLength
= mono_array_length (pre_buffer
);
2802 if (post_buffer
!= NULL
) {
2803 buffers
.Tail
= mono_array_addr (post_buffer
, guchar
, 0);
2804 buffers
.TailLength
= mono_array_length (post_buffer
);
2807 mono_thread_info_install_interrupt (abort_syscall
, (gpointer
) (gsize
) mono_native_thread_id_get (), &interrupted
);
2810 SetLastError (WSAEINTR
);
2816 ret
= TransmitFile (sock
, file
, 0, 0, NULL
, &buffers
, flags
);
2820 mono_thread_info_uninstall_interrupt (&interrupted
);
2823 SetLastError (WSAEINTR
);
2837 ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto
)
2839 #if defined (SO_REUSEPORT) || defined (HOST_WIN32)
2843 /* Linux always supports double binding for UDP, even on older kernels. */
2844 if (proto
== ProtocolType_Udp
)
2852 mono_network_init (void)
2854 mono_networking_init ();
2858 mono_network_cleanup (void)
2860 _wapi_cleanup_networking ();
2861 mono_networking_shutdown ();
2865 icall_cancel_blocking_socket_operation (MonoThread
*thread
)
2867 MonoInternalThread
*internal
;
2869 internal
= thread
->internal_thread
;
2870 g_assert (internal
);
2872 mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (internal
->tid
));
2875 #endif /* #ifndef DISABLE_SOCKETS */