#ifdef AF_INET6
case SocketOptionLevel_IPv6:
+#ifdef HAVE_SOL_IPV6
*system_level = SOL_IPV6;
+#else
+ if (1) {
+ static int cached = 0;
+ static int proto;
+
+ if (!cached) {
+ struct protoent *pent;
+
+ pent = getprotobyname ("IPV6");
+ proto = pent ? pent->p_proto : 41 /* 41 a good default value?? */;
+ cached = 1;
+ }
+
+ *system_level = proto;
+ }
+#endif /* HAVE_SOL_IPV6 */
switch(mono_name) {
case SocketOptionName_IpTimeToLive:
#define STASH_SYS_ASS(this) \
if(system_assembly == NULL) { \
- system_assembly=this->vtable->klass->image; \
+ system_assembly=mono_image_loaded ("System"); \
}
static MonoImage *system_assembly=NULL;
mono_raise_exception (mono_exception_from_name(mono_defaults.corlib, "System", "SystemException"));
}
- family = convert_family (mono_array_get (data, guint16, 0));
+ family = convert_family (mono_array_get (data, guint8, 0) + (mono_array_get (data, guint8, 1) << 8));
if(family==AF_INET) {
struct sockaddr_in *sa=g_new0(struct sockaddr_in, 1);
guint16 port=(mono_array_get(data, guint8, 2) << 8) +
/* Negative timeout meaning block until ready is only
* specified in Poll, not Select
*/
- if(timeout>=0) {
- divvy=div(timeout, 1000000);
- tv.tv_sec=divvy.quot;
- tv.tv_usec=divvy.rem;
+
+ divvy = div (timeout, 1000000);
- ret=select(0, readptr, writeptr, errptr, &tv);
- } else {
- ret=select(0, readptr, writeptr, errptr, NULL);
- }
+ do {
+ if(timeout>=0) {
+ tv.tv_sec=divvy.quot;
+ tv.tv_usec=divvy.rem;
+
+ ret=select(0, readptr, writeptr, errptr, &tv);
+ } else {
+ ret=select(0, readptr, writeptr, errptr, NULL);
+ }
+ } while ((ret==SOCKET_ERROR) && (WSAGetLastError() == WSAEINTR));
if(ret==SOCKET_ERROR) {
mono_raise_exception(get_socket_exception(WSAGetLastError()));
}
}
+static MonoObject* int_to_object (MonoDomain *domain, int val)
+{
+ /* construct an Int32 object to hold val */
+ MonoObject* obj = mono_object_new(domain, mono_defaults.int32_class);
+
+ /* Locate and set the "value" field */
+ MonoClassField *field = mono_class_get_field_from_name(mono_defaults.int32_class,
+ "value");
+ *(gint32 *)(((char *)obj)+field->offset)=val;
+ return obj;
+}
+
+
void ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal(SOCKET sock, gint32 level, gint32 name, MonoObject **obj_val)
{
int system_level;
int valsize=sizeof(val);
struct linger linger;
int lingersize=sizeof(linger);
+ struct timeval tv;
+ int tvsize=sizeof(tv);
MonoDomain *domain=mono_domain_get();
MonoObject *obj;
MonoClass *obj_class;
&lingersize);
break;
+ case SocketOptionName_SendTimeout:
+ case SocketOptionName_ReceiveTimeout:
+ ret=getsockopt(sock, system_level, system_name, &tv,
+ &tvsize);
+ break;
+
default:
ret=getsockopt(sock, system_level, system_name, &val,
&valsize);
case SocketOptionName_DontLinger:
/* construct a bool int in val - true if linger is off */
- val=!linger.l_onoff;
-
- /* fall through */
+ obj = int_to_object (domain, !linger.l_onoff);
+ break;
+ case SocketOptionName_SendTimeout:
+ case SocketOptionName_ReceiveTimeout:
+ obj = int_to_object (domain, (tv.tv_sec * 1000) + (tv.tv_usec / 1000));
+ break;
+
default:
- /* construct an Int32 object to hold val */
- obj=mono_object_new(domain, mono_defaults.int32_class);
-
- /* Locate and set the "value" field */
- field=mono_class_get_field_from_name(mono_defaults.int32_class,
- "value");
- *(gint32 *)(((char *)obj)+field->offset)=val;
+ obj = int_to_object (domain, val);
}
*obj_val=obj;
field=mono_class_get_field_from_name(ipaddr->vtable->klass, "_numbers");
data=*(MonoArray **)(((char *)ipaddr) + field->offset);
+/* Solaris has only the 8 bit version. */
+#ifndef s6_addr16
+ for(i=0; i<8; i++) {
+ guint16 s = mono_array_get (data, guint16, i);
+ in6addr.s6_addr[2 * i] = (s >> 8) & 0xff;
+ in6addr.s6_addr[2 * i + 1] = s & 0xff;
+ }
+#else
for(i=0; i<8; i++)
in6addr.s6_addr16[i] = mono_array_get (data, guint16, i);
-
+#endif
return(in6addr);
}
#endif /* AF_INET6 */
int system_level;
int system_name;
int ret;
+#ifdef AF_INET6
+ int sol_ip;
+ int sol_ipv6;
+
+#ifdef HAVE_SOL_IPV6
+ sol_ipv6 = SOL_IPV6;
+#else
+ {
+ struct protoent *pent;
+ pent = getprotobyname ("ipv6");
+ sol_ipv6 = (pent != NULL) ? pent->p_proto : 41;
+ }
+#endif
+
+#ifdef HAVE_SOL_IP
+ sol_ip = SOL_IP;
+#else
+ {
+ struct protoent *pent;
+ pent = getprotobyname ("ip");
+ sol_ip = (pent != NULL) ? pent->p_proto : 0;
+ }
+#endif
+#endif /* AF_INET6 */
MONO_ARCH_SAVE_REGS;
MonoObject *address = NULL;
#ifdef AF_INET6
- if(system_level == SOL_IPV6) {
+ if(system_level == sol_ipv6) {
struct ipv6_mreq mreq6;
/*
ret = setsockopt (sock, system_level,
system_name, &mreq6,
sizeof (mreq6));
- } else if(system_level == SOL_IP)
+ } else if(system_level == sol_ip)
#endif /* AF_INET6 */
{
#ifdef HAVE_STRUCT_IP_MREQN
mono_raise_exception(get_socket_exception(WSAGetLastError()));
}
} else {
- ret=setsockopt(sock, system_level, system_name, &int_val,
+ switch(name) {
+ case SocketOptionName_SendTimeout:
+ case SocketOptionName_ReceiveTimeout: {
+ struct timeval tv;
+ tv.tv_sec = int_val / 1000;
+ tv.tv_usec = (int_val % 1000) * 1000;
+ ret=setsockopt(sock, system_level, system_name, &tv, sizeof (tv));
+ break;
+ }
+ default:
+ ret=setsockopt(sock, system_level, system_name, &int_val,
sizeof(int_val));
+ }
}
if(ret==SOCKET_ERROR) {