Only compile in multicast support on Linux, for the time being.
The calls and structs provided by the underlying platform for
multicast aren't yet exactly well-established POSIX standards, and the
current Linux code is still not considered to be super-robust, and as
such it isn't a good idea to try to duplicate its functionality for
other platforms. We will revisit the issue once the Linux side has
matured a bit.
Change-Id: I630086e22f6980726fd4523cb60dfc8c9fb9b011
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index f8fd628..16391a0 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -51,6 +51,25 @@
#endif
#endif
+/*
+ * The contents of a struct in6_addr are fairly uniform across
+ * platforms, but the member names and convenience macros to access
+ * its embedded union are not. The following definition has been
+ * checked for correctness on OS X and FreeBSD, but it may not work on
+ * other platforms.
+ */
+#ifndef s6_addr32
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+/*
+ * TODO: The multicast code is highly platform-dependent, and for now
+ * we just punt on anything but Linux.
+ */
+#ifdef __linux__
+#define ENABLE_MULTICAST
+#endif
+
/**
* @name Socket Errors
* Error codes for socket operations
@@ -1213,6 +1232,7 @@
return ret;
}
+#ifdef ENABLE_MULTICAST
/*
* Find the interface index that was set for this socket by the IP_MULTICAST_IF
* or IPV6_MULTICAST_IF socket option.
@@ -1271,7 +1291,7 @@
*
* @exception SocketException if an error occurs during the call
*/
-static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
+static void mcastAddDropMembership(JNIEnv *env, int handle, jobject optVal,
int ignoreIF, int setSockOptVal) {
struct sockaddr_storage sockaddrP;
int result;
@@ -1398,6 +1418,7 @@
}
}
}
+#endif // def ENABLE_MULTICAST
static void osNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
jboolean jcl_supports_ipv6) {
@@ -2348,7 +2369,7 @@
return true;
}
-static bool translateFdSet(JNIEnv* env, jobjectArray fdArray, jint count, const fd_set& fdSet, jint* flagArray, size_t offset, jint op) {
+static bool translateFdSet(JNIEnv* env, jobjectArray fdArray, jint count, fd_set& fdSet, jint* flagArray, size_t offset, jint op) {
for (int i = 0; i < count; ++i) {
jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i);
if (fileDescriptor == NULL) {
@@ -2357,7 +2378,12 @@
const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
const bool valid = fd >= 0 && fd < 1024;
-
+
+ /*
+ * Note: On Linux, FD_ISSET() is sane and takes a (const fd_set *)
+ * but the argument isn't const on all platforms, even though
+ * the function doesn't ever modify the argument.
+ */
if (valid && FD_ISSET(fd, &fdSet)) {
flagArray[i + offset] = op;
} else {
@@ -2486,6 +2512,7 @@
}
return newJavaLangInteger(env, intValue);
}
+
case JAVASOCKOPT_TCP_NODELAY: {
if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
return NULL;
@@ -2497,6 +2524,83 @@
}
return newJavaLangBoolean(env, intValue);
}
+
+ case JAVASOCKOPT_SO_SNDBUF: {
+ result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangInteger(env, intValue);
+ }
+
+ case JAVASOCKOPT_SO_RCVBUF: {
+ result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangInteger(env, intValue);
+ }
+
+ case JAVASOCKOPT_SO_BROADCAST: {
+ result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangBoolean(env, intValue);
+ }
+
+ case JAVASOCKOPT_SO_REUSEADDR: {
+ result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangBoolean(env, intValue);
+ }
+
+ case JAVASOCKOPT_SO_KEEPALIVE: {
+ result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangBoolean(env, intValue);
+ }
+
+ case JAVASOCKOPT_SO_OOBINLINE: {
+ result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangBoolean(env, intValue);
+ }
+
+ case JAVASOCKOPT_IP_TOS: {
+ result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
+ IPV6_TCLASS, &intValue, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangInteger(env, intValue);
+ }
+
+ case JAVASOCKOPT_SO_RCVTIMEOUT: {
+ struct timeval timeout;
+ socklen_t size = sizeof(timeout);
+ result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return NULL;
+ }
+ return newJavaLangInteger(env, toMs(timeout));
+ }
+
+#ifdef ENABLE_MULTICAST
case JAVASOCKOPT_MCAST_TTL: {
if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
return newJavaLangByte(env, 0);
@@ -2511,6 +2615,7 @@
}
return newJavaLangByte(env, (jbyte)(intValue & 0xFF));
}
+
case JAVASOCKOPT_IP_MULTICAST_IF: {
if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
return NULL;
@@ -2528,6 +2633,7 @@
}
return socketAddressToInetAddress(env, &sockVal);
}
+
case JAVASOCKOPT_IP_MULTICAST_IF2: {
if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
return NULL;
@@ -2560,54 +2666,7 @@
}
return newJavaLangInteger(env, interfaceIndex);
}
- case JAVASOCKOPT_SO_SNDBUF: {
- result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangInteger(env, intValue);
- }
- case JAVASOCKOPT_SO_RCVBUF: {
- result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangInteger(env, intValue);
- }
- case JAVASOCKOPT_SO_BROADCAST: {
- result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_SO_REUSEADDR: {
- result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_SO_KEEPALIVE: {
- result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
- case JAVASOCKOPT_SO_OOBINLINE: {
- result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangBoolean(env, intValue);
- }
+
case JAVASOCKOPT_IP_MULTICAST_LOOP: {
result = getOrSetSocketOption(SOCKOPT_GET, handle,
IP_MULTICAST_LOOP,
@@ -2619,25 +2678,16 @@
}
return newJavaLangBoolean(env, intValue);
}
- case JAVASOCKOPT_IP_TOS: {
- result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
- IPV6_TCLASS, &intValue, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangInteger(env, intValue);
+#else
+ case JAVASOCKOPT_MCAST_TTL:
+ case JAVASOCKOPT_IP_MULTICAST_IF:
+ case JAVASOCKOPT_IP_MULTICAST_IF2:
+ case JAVASOCKOPT_IP_MULTICAST_LOOP: {
+ jniThrowSocketException(env, EAFNOSUPPORT);
+ return NULL;
}
- case JAVASOCKOPT_SO_RCVTIMEOUT: {
- struct timeval timeout;
- socklen_t size = sizeof(timeout);
- result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangInteger(env, toMs(timeout));
- }
+#endif // def ENABLE_MULTICAST
+
default: {
jniThrowSocketException(env, ENOPROTOOPT);
return NULL;
@@ -2705,6 +2755,91 @@
break;
}
+ case JAVASOCKOPT_SO_SNDBUF: {
+ result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_SO_RCVBUF: {
+ result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_SO_BROADCAST: {
+ result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_SO_REUSEADDR: {
+ result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+ case JAVASOCKOPT_SO_KEEPALIVE: {
+ result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_SO_OOBINLINE: {
+ result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_IP_TOS: {
+ result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
+ IPV6_TCLASS, &intVal, &intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
+ // SO_REUSEPORT doesn't need to get set on this System
+ result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+ case JAVASOCKOPT_SO_RCVTIMEOUT: {
+ timeval timeout(toTimeval(intVal));
+ result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
+ sizeof(struct timeval));
+ if (0 != result) {
+ jniThrowSocketException(env, errno);
+ return;
+ }
+ break;
+ }
+
+#ifdef ENABLE_MULTICAST
case JAVASOCKOPT_MCAST_TTL: {
if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
return;
@@ -2790,59 +2925,6 @@
break;
}
- case JAVASOCKOPT_SO_SNDBUF: {
- result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_RCVBUF: {
- result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_BROADCAST: {
- result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_REUSEADDR: {
- result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
- case JAVASOCKOPT_SO_KEEPALIVE: {
- result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_OOBINLINE: {
- result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
case JAVASOCKOPT_IP_MULTICAST_LOOP: {
result = getOrSetSocketOption(SOCKOPT_SET, handle,
IP_MULTICAST_LOOP,
@@ -2854,37 +2936,17 @@
}
break;
}
-
- case JAVASOCKOPT_IP_TOS: {
- result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
- IPV6_TCLASS, &intVal, &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
+#else
+ case JAVASOCKOPT_MCAST_TTL:
+ case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP:
+ case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP:
+ case JAVASOCKOPT_IP_MULTICAST_IF:
+ case JAVASOCKOPT_IP_MULTICAST_IF2:
+ case JAVASOCKOPT_IP_MULTICAST_LOOP: {
+ jniThrowSocketException(env, EAFNOSUPPORT);
+ return;
}
-
- case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
- // SO_REUSEPORT doesn't need to get set on this System
- result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_SO_RCVTIMEOUT: {
- timeval timeout(toTimeval(intVal));
- result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
- sizeof(struct timeval));
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
+#endif // def ENABLE_MULTICAST
default: {
jniThrowSocketException(env, ENOPROTOOPT);