Fri Mar 29 18:09:08 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / socket-io.c
index 96ed55736dce6273f251c9b5eef308efe92de893..27f81def12e671357f2df57d5ffd768f68b08769 100644 (file)
@@ -8,7 +8,10 @@
  */
 
 #include <config.h>
+
 #include <glib.h>
+#include <string.h>
+#include <stdlib.h>
 
 #include <mono/metadata/object.h>
 #include <mono/io-layer/io-layer.h>
 
 #include <sys/time.h> 
 
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
 #undef DEBUG
 
 static gint32 convert_family(MonoAddressFamily mono_family)
@@ -213,67 +220,67 @@ static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
                                             int *system_level,
                                             int *system_name)
 {
-       switch(mono_level) {
+       switch (mono_level) {
        case SocketOptionLevel_Socket:
-               *system_level=SOL_SOCKET;
-
+               *system_level = SOL_SOCKET;
+               
                switch(mono_name) {
                case SocketOptionName_DontLinger:
                        /* This is SO_LINGER, because the setsockopt
                         * internal call maps DontLinger to SO_LINGER
                         * with l_onoff=0
                         */
-                       *system_name=SO_LINGER;
+                       *system_name = SO_LINGER;
                        break;
                case SocketOptionName_Debug:
-                       *system_name=SO_DEBUG;
+                       *system_name = SO_DEBUG;
                        break;
 #ifdef SO_ACCEPTCONN
                case SocketOptionName_AcceptConnection:
-                       *system_name=SO_ACCEPTCONN;
+                       *system_name = SO_ACCEPTCONN;
                        break;
 #endif
                case SocketOptionName_ReuseAddress:
-                       *system_name=SO_REUSEADDR;
+                       *system_name = SO_REUSEADDR;
                        break;
                case SocketOptionName_KeepAlive:
-                       *system_name=SO_KEEPALIVE;
+                       *system_name = SO_KEEPALIVE;
                        break;
                case SocketOptionName_DontRoute:
-                       *system_name=SO_DONTROUTE;
+                       *system_name = SO_DONTROUTE;
                        break;
                case SocketOptionName_Broadcast:
-                       *system_name=SO_BROADCAST;
+                       *system_name = SO_BROADCAST;
                        break;
                case SocketOptionName_Linger:
-                       *system_name=SO_LINGER;
+                       *system_name = SO_LINGER;
                        break;
                case SocketOptionName_OutOfBandInline:
-                       *system_name=SO_OOBINLINE;
+                       *system_name = SO_OOBINLINE;
                        break;
                case SocketOptionName_SendBuffer:
-                       *system_name=SO_SNDBUF;
+                       *system_name = SO_SNDBUF;
                        break;
                case SocketOptionName_ReceiveBuffer:
-                       *system_name=SO_RCVBUF;
+                       *system_name = SO_RCVBUF;
                        break;
                case SocketOptionName_SendLowWater:
-                       *system_name=SO_SNDLOWAT;
+                       *system_name = SO_SNDLOWAT;
                        break;
                case SocketOptionName_ReceiveLowWater:
-                       *system_name=SO_RCVLOWAT;
+                       *system_name = SO_RCVLOWAT;
                        break;
                case SocketOptionName_SendTimeout:
-                       *system_name=SO_SNDTIMEO;
+                       *system_name = SO_SNDTIMEO;
                        break;
                case SocketOptionName_ReceiveTimeout:
-                       *system_name=SO_RCVTIMEO;
+                       *system_name = SO_RCVTIMEO;
                        break;
                case SocketOptionName_Error:
-                       *system_name=SO_ERROR;
+                       *system_name = SO_ERROR;
                        break;
                case SocketOptionName_Type:
-                       *system_name=SO_TYPE;
+                       *system_name = SO_TYPE;
                        break;
                case SocketOptionName_ExclusiveAddressUse:
                case SocketOptionName_UseLoopback:
@@ -288,39 +295,64 @@ static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
                break;
                
        case SocketOptionLevel_IP:
-               *system_level=SOL_IP;
-
+#ifdef HAVE_SOL_IP
+               *system_level = SOL_IP;
+#else
+               if (1) {
+                       static int cached = 0;
+                       static int proto;
+                       
+                       if (!cached) {
+                               struct protoent *pent;
+                               
+                               pent = getprotobyname ("IP");
+                               proto = pent ? pent->p_proto : 0 /* 0 a good default value?? */;
+                               cached = 1;
+                       }
+                       
+                       *system_level = proto;
+               }
+#endif /* HAVE_SOL_IP */
+               
                switch(mono_name) {
                case SocketOptionName_IPOptions:
-                       *system_name=IP_OPTIONS;
+                       *system_name = IP_OPTIONS;
                        break;
+#ifdef IP_HDRINCL
                case SocketOptionName_HeaderIncluded:
-                       *system_name=IP_HDRINCL;
+                       *system_name = IP_HDRINCL;
                        break;
+#endif
+#ifdef IP_TOS
                case SocketOptionName_TypeOfService:
-                       *system_name=IP_TOS;
+                       *system_name = IP_TOS;
                        break;
+#endif
+#ifdef IP_TTL
                case SocketOptionName_IpTimeToLive:
-                       *system_name=IP_TTL;
+                       *system_name = IP_TTL;
                        break;
+#endif
                case SocketOptionName_MulticastInterface:
-                       *system_name=IP_MULTICAST_IF;
+                       *system_name = IP_MULTICAST_IF;
                        break;
                case SocketOptionName_MulticastTimeToLive:
-                       *system_name=IP_MULTICAST_TTL;
+                       *system_name = IP_MULTICAST_TTL;
                        break;
                case SocketOptionName_MulticastLoopback:
-                       *system_name=IP_MULTICAST_LOOP;
+                       *system_name = IP_MULTICAST_LOOP;
                        break;
                case SocketOptionName_AddMembership:
-                       *system_name=IP_ADD_MEMBERSHIP;
+                       *system_name = IP_ADD_MEMBERSHIP;
                        break;
                case SocketOptionName_DropMembership:
-                       *system_name=IP_DROP_MEMBERSHIP;
+                       *system_name = IP_DROP_MEMBERSHIP;
                        break;
+#ifdef HAVE_IP_PKTINFO
                case SocketOptionName_PacketInformation:
-                       *system_name=IP_PKTINFO;
+                       *system_name = IP_PKTINFO;
                        break;
+#endif /* HAVE_IP_PKTINFO */
                case SocketOptionName_DontFragment:
                case SocketOptionName_AddSourceMembership:
                case SocketOptionName_DropSourceMembership:
@@ -336,11 +368,28 @@ static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
                break;
                
        case SocketOptionLevel_Tcp:
-               *system_level=SOL_TCP;
-
+#ifdef HAVE_SOL_TCP
+               *system_level = SOL_TCP;
+#else
+               if (1) {
+                       static int cached = 0;
+                       static int proto;
+                       
+                       if (!cached) {
+                               struct protoent *pent;
+                               
+                               pent = getprotobyname ("TCP");
+                               proto = pent ? pent->p_proto : 6 /* is 6 a good default value?? */;
+                               cached = 1;
+                       }
+                       
+                       *system_level = proto;
+               }
+#endif /* HAVE_SOL_TCP */
+               
                switch(mono_name) {
                case SocketOptionName_NoDelay:
-                       *system_name=TCP_NODELAY;
+                       *system_name = TCP_NODELAY;
                        break;
 #if 0
                        /* The documentation is talking complete
@@ -380,7 +429,7 @@ static gint32 convert_sockopt_level_and_name(MonoSocketOptionLevel mono_level,
 }
 
 #define STASH_SYS_ASS(this) \
-       if(system_assembly==NULL) { \
+       if(system_assembly == NULL) { \
                system_assembly=this->vtable->klass->image; \
        }
 
@@ -815,13 +864,13 @@ gint32 ves_icall_System_Net_Sockets_Socket_SendTo_internal(SOCKET sock, MonoArra
        return(ret);
 }
 
-static SOCKET Socket_to_SOCKET(MonoObject *socket)
+static SOCKET Socket_to_SOCKET(MonoObject *sockobj)
 {
        SOCKET sock;
        MonoClassField *field;
        
-       field=mono_class_get_field_from_name(socket->vtable->klass, "socket");
-       sock=*(SOCKET *)(((char *)socket)+field->offset);
+       field=mono_class_get_field_from_name(sockobj->vtable->klass, "socket");
+       sock=*(SOCKET *)(((char *)sockobj)+field->offset);
 
        return(sock);
 }
@@ -1081,10 +1130,9 @@ void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, g
 
        /* Only one of obj_val, byte_val or int_val has data */
        if(obj_val!=NULL) {
+               MonoClassField *field;
                struct linger linger;
-               struct ip_mreqn mreq;
                int valsize;
-               MonoClassField *field;
                
                switch(name) {
                case SocketOptionName_DontLinger:
@@ -1108,23 +1156,35 @@ void ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal(SOCKET sock, g
                        ret=setsockopt(sock, system_level, system_name,
                                       &linger, valsize);
                        break;
-                       
                case SocketOptionName_AddMembership:
                case SocketOptionName_DropMembership:
+               {
+#ifdef HAVE_STRUCT_IP_MREQN
+                       struct ip_mreqn mreq;
+#else
+                       struct ip_mreq mreq;
+#endif /* HAVE_STRUCT_IP_MREQN */
+                       
                        /* pain! MulticastOption holds two IPAddress
                         * members, so I have to dig the value out of
                         * those :-(
                         */
-                       field=mono_class_get_field_from_name(obj_val->vtable->klass, "group");
-                       mreq.imr_multiaddr=ipaddress_to_struct_in_addr(*(gpointer *)(((char *)obj_val)+field->offset));
-                       field=mono_class_get_field_from_name(obj_val->vtable->klass, "local");
-                       mreq.imr_address=ipaddress_to_struct_in_addr(*(gpointer *)(((char *)obj_val)+field->offset))
-;
-                       valsize=sizeof(mreq);
-                       ret=setsockopt(sock, system_level, system_name,
-                                      &mreq, valsize);
+                       field = mono_class_get_field_from_name (obj_val->vtable->klass, "group");
+                       mreq.imr_multiaddr = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
+                                                                                       field->offset));
+                       field = mono_class_get_field_from_name (obj_val->vtable->klass, "local");
+#ifdef HAVE_STRUCT_IP_MREQN
+                       mreq.imr_address = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
+                                                                                     field->offset));
+#else
+                       mreq.imr_interface = ipaddress_to_struct_in_addr (*(gpointer *)(((char *)obj_val) +
+                                                                                       field->offset));
+#endif /* HAVE_STRUCT_IP_MREQN */
+                       
+                       ret = setsockopt (sock, system_level, system_name,
+                                         &mreq, sizeof (mreq));
                        break;
-
+               }
                default:
                        /* Throw an exception */
                        mono_raise_exception(get_socket_exception(WSAEINVAL));
@@ -1246,7 +1306,7 @@ inet_pton (int family, const char *address, void *inaddrp)
 #else
                /* assume the system has inet_addr(), if it doesn't
                   have that we're pretty much screwed... */
-               in_addr_t inaddr;
+               guint32 inaddr;
                
                if (!strcmp (address, "255.255.255.255")) {
                        /* special-case hack */
@@ -1260,12 +1320,11 @@ inet_pton (int family, const char *address, void *inaddrp)
                                return 0;
                }
                
-               memcpy (inaddrp, &inaddr, sizeof (in_addr_t));
+               memcpy (inaddrp, &inaddr, sizeof (guint32));
                return 1;
 #endif /* HAVE_INET_ATON */
        }
        
-       errno = EAFNOSUPPRT;
        return -1;
 }
 #endif /* !HAVE_INET_PTON */