Merge "OpenSSLSocket handshake overhaul" into dalvik-dev
diff --git a/luni/src/main/java/java/net/MulticastSocket.java b/luni/src/main/java/java/net/MulticastSocket.java
index 22cefb9..7815b01 100644
--- a/luni/src/main/java/java/net/MulticastSocket.java
+++ b/luni/src/main/java/java/net/MulticastSocket.java
@@ -31,9 +31,6 @@
* @see DatagramSocket
*/
public class MulticastSocket extends DatagramSocket {
-
- final static int SO_REUSEPORT = 512;
-
private InetAddress interfaceSet;
/**
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
index 7721cbb..766538c 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
@@ -296,7 +296,7 @@
@Override
public void setTTL(byte ttl) throws IOException {
- setTimeToLive(ttl);
+ setTimeToLive((int) ttl & 0xff); // Avoid sign extension.
}
@Override
diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 11c056d..bd82613 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -141,10 +141,6 @@
#define SOCKET_STEP_CHECK 20
#define SOCKET_STEP_DONE 30
-#define BROKEN_MULTICAST_IF 1
-#define BROKEN_MULTICAST_TTL 2
-#define BROKEN_TCP_NODELAY 4
-
#define SOCKET_CONNECT_STEP_START 0
#define SOCKET_CONNECT_STEP_CHECK 1
@@ -154,11 +150,7 @@
#define SOCKET_NOFLAGS 0
-// Local constants for getOrSetSocketOption
-#define SOCKOPT_GET 1
-#define SOCKOPT_SET 2
-
-struct CachedFields {
+static struct CachedFields {
jfieldID fd_descriptor;
jclass iaddr_class;
jmethodID iaddr_getbyaddress;
@@ -308,7 +300,7 @@
}
}
-jobject byteArrayToInetAddress(JNIEnv* env, jbyteArray byteArray) {
+static jobject byteArrayToInetAddress(JNIEnv* env, jbyteArray byteArray) {
if (byteArray == NULL) {
return NULL;
}
@@ -1143,7 +1135,7 @@
*
* @note on internal failure, the errno variable will be set appropriately
*/
-static int getOrSetSocketOption(int action, int socket, int ipv4Option,
+static int getSocketOption(int socket, int ipv4Option,
int ipv6Option, void *optionValue, socklen_t *optionLength) {
int option;
int protocol;
@@ -1164,28 +1156,12 @@
return -1;
}
- int ret;
- if (action == SOCKOPT_GET) {
- ret = getsockopt(socket, protocol, option, optionValue, optionLength);
+ int ret = getsockopt(socket, protocol, option, optionValue, optionLength);
#if LOG_SOCKOPT
- LOGI("getsockopt(%d, %s, %d, %p, [%d]) = %d %s",
+ LOGI("getsockopt(%d, %s, %d, %p, [%d]) = %d %s",
socket, sockoptLevelToString(protocol), option, optionValue,
*optionLength, ret, (ret == -1) ? strerror(errno) : "");
#endif
- } else if (action == SOCKOPT_SET) {
- ret = setsockopt(socket, protocol, option, optionValue, *optionLength);
-#if LOG_SOCKOPT
- LOGI("setsockopt(%d, %s, %d, [%d], %d) = %d %s",
- socket, sockoptLevelToString(protocol), option,
- // Note: this only works for integer options.
- // TODO: Use dvmPrintHexDump() to log non-integer options.
- *(int *)optionValue, *optionLength, ret,
- (ret == -1) ? strerror(errno) : "");
-#endif
- } else {
- errno = EINVAL;
- ret = -1;
- }
return ret;
}
@@ -1202,29 +1178,22 @@
*/
static int interfaceIndexFromMulticastSocket(int socket) {
int family = getSocketAddressFamily(socket);
- int interfaceIndex;
- int result;
if (family == AF_INET) {
// IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
struct ip_mreqn tempRequest;
socklen_t requestLength = sizeof(tempRequest);
- result = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest,
- &requestLength);
- interfaceIndex = tempRequest.imr_ifindex;
+ int rc = getsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &tempRequest, &requestLength);
+ return (rc == -1) ? -1 : tempRequest.imr_ifindex;
} else if (family == AF_INET6) {
// IPV6_MULTICAST_IF returns a pointer to an integer.
+ int interfaceIndex;
socklen_t requestLength = sizeof(interfaceIndex);
- result = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF,
- &interfaceIndex, &requestLength);
+ int rc = getsockopt(socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &interfaceIndex, &requestLength);
+ return (rc == -1) ? -1 : interfaceIndex;
} else {
errno = EAFNOSUPPORT;
return -1;
}
-
- if (result == 0)
- return interfaceIndex;
- else
- return -1;
}
/**
@@ -1248,8 +1217,7 @@
*
* @exception SocketException if an error occurs during the call
*/
-static void mcastAddDropMembership(JNIEnv *env, int handle, jobject optVal,
- int ignoreIF, int setSockOptVal) {
+static void mcastAddDropMembership(JNIEnv *env, int handle, jobject optVal, int setSockOptVal) {
struct sockaddr_storage sockaddrP;
int result;
// By default, let the system decide which interface to use.
@@ -1261,7 +1229,7 @@
* is passed in, only support IPv4 as obtaining an interface from an
* InetAddress is complex and should be done by the Java caller.
*/
- if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
+ if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
/*
* optVal is an InetAddress. Construct a multicast request structure
* from this address. Support IPv4 only.
@@ -1270,14 +1238,11 @@
socklen_t length = sizeof(multicastRequest);
memset(&multicastRequest, 0, length);
- // If ignoreIF is false, determine the index of the interface to use.
- if (!ignoreIF) {
- interfaceIndex = interfaceIndexFromMulticastSocket(handle);
- multicastRequest.imr_ifindex = interfaceIndex;
- if (interfaceIndex == -1) {
- jniThrowSocketException(env, errno);
- return;
- }
+ interfaceIndex = interfaceIndexFromMulticastSocket(handle);
+ multicastRequest.imr_ifindex = interfaceIndex;
+ if (interfaceIndex == -1) {
+ jniThrowSocketException(env, errno);
+ return;
}
// Convert the inetAddress to an IPv4 address structure.
@@ -1303,21 +1268,15 @@
* it and construct a multicast request structure from these. Support
* both IPv4 and IPv6.
*/
- jclass cls;
- jfieldID multiaddrID;
- jfieldID interfaceIdxID;
- jobject multiaddr;
// Get the multicast address to join or leave.
- cls = env->GetObjectClass(optVal);
- multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
- multiaddr = env->GetObjectField(optVal, multiaddrID);
+ jclass cls = env->GetObjectClass(optVal);
+ jfieldID multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
+ jobject multiaddr = env->GetObjectField(optVal, multiaddrID);
// Get the interface index to use.
- if (! ignoreIF) {
- interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
- interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
- }
+ jfieldID interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
+ interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
LOGI("mcastAddDropMembership interfaceIndex=%i", interfaceIndex);
if (!inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP)) {
@@ -2384,9 +2343,6 @@
}
case JAVASOCKOPT_TCP_NODELAY: {
- if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
- return NULL;
- }
result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
if (0 != result) {
jniThrowSocketException(env, errno);
@@ -2450,7 +2406,7 @@
}
case JAVASOCKOPT_IP_TOS: {
- result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
+ result = getSocketOption(handle, IP_TOS,
IPV6_TCLASS, &intValue, &intSize);
if (0 != result) {
jniThrowSocketException(env, errno);
@@ -2472,11 +2428,8 @@
#ifdef ENABLE_MULTICAST
case JAVASOCKOPT_MCAST_TTL: {
- if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
- return newJavaLangByte(env, 0);
- }
// Java uses a byte to store the TTL, but the kernel uses an int.
- result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
+ result = getSocketOption(handle, IP_MULTICAST_TTL,
IPV6_MULTICAST_HOPS, &intValue,
&intSize);
if (0 != result) {
@@ -2487,16 +2440,13 @@
}
case JAVASOCKOPT_IP_MULTICAST_IF: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return NULL;
- }
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
- &sockVal, &sockSize);
+ result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
if (result == -1) {
jniThrowSocketException(env, errno);
return NULL;
}
if (sockVal.ss_family != AF_INET) {
+ LOGE("sockVal.ss_family != AF_INET (%i)", sockVal.ss_family);
// Java expects an AF_INET INADDR_ANY, but Linux just returns AF_UNSPEC.
jbyteArray inAddrAny = env->NewByteArray(4); // { 0, 0, 0, 0 }
return byteArrayToInetAddress(env, inAddrAny);
@@ -2505,9 +2455,6 @@
}
case JAVASOCKOPT_IP_MULTICAST_IF2: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return NULL;
- }
struct ip_mreqn multicastRequest;
int interfaceIndex = 0;
socklen_t optionLength;
@@ -2538,7 +2485,7 @@
}
case JAVASOCKOPT_IP_MULTICAST_LOOP: {
- result = getOrSetSocketOption(SOCKOPT_GET, handle,
+ result = getSocketOption(handle,
IP_MULTICAST_LOOP,
IPV6_MULTICAST_LOOP, &intValue,
&intSize);
@@ -2563,28 +2510,31 @@
return NULL;
}
}
-
}
-static void osNetworkSystem_setSocketOption(JNIEnv* env, jobject,
- jobject fileDescriptor, jint anOption, jobject optVal) {
- int result;
- int intVal;
- socklen_t intSize = sizeof(int);
- struct sockaddr_storage sockVal;
- int sockSize = sizeof(sockVal);
+template <typename T>
+static void setSocketOption(JNIEnv* env, int fd, int level, int option, T* value) {
+ int rc = setsockopt(fd, level, option, value, sizeof(*value));
+ if (rc == -1) {
+ LOGE("setSocketOption(fd=%i, level=%i, option=%i) failed: %s (errno=%i)",
+ fd, level, option, errno, strerror(errno), errno);
+ jniThrowSocketException(env, errno);
+ }
+}
+static void osNetworkSystem_setSocketOption(JNIEnv* env, jobject, jobject fileDescriptor, jint option, jobject optVal) {
+ int fd;
+ if (!jniGetFd(env, fileDescriptor, fd)) {
+ return;
+ }
+
+ int intVal;
if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
} else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
} else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
- // TTL uses a byte in Java, but the kernel still wants an int.
intVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
- } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
- if (!inetAddressToSocketAddress(env, optVal, 0, &sockVal)) {
- return;
- }
} else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
// we'll use optVal directly
} else {
@@ -2592,150 +2542,81 @@
return;
}
- int handle;
- if (!jniGetFd(env, fileDescriptor, handle)) {
+ int family = getSocketAddressFamily(fd);
+ if (family != AF_INET && family != AF_INET6) {
+ jniThrowSocketException(env, EAFNOSUPPORT);
return;
}
- switch ((int) anOption & 0xffff) {
- case JAVASOCKOPT_SO_LINGER: {
+ switch (option) {
+ case JAVASOCKOPT_SO_LINGER:
+ {
struct linger lingr;
lingr.l_onoff = intVal > 0 ? 1 : 0;
lingr.l_linger = intVal;
- result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
- sizeof(struct linger));
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
+ setSocketOption(env, fd, SOL_SOCKET, SO_LINGER, &lingr);
+ return;
}
-
- case JAVASOCKOPT_TCP_NODELAY: {
- if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
- return;
- }
- result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- 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: {
+ case JAVASOCKOPT_SO_SNDBUF:
+ setSocketOption(env, fd, SOL_SOCKET, SO_SNDBUF, &intVal);
+ return;
+ case JAVASOCKOPT_SO_RCVBUF:
+ setSocketOption(env, fd, SOL_SOCKET, SO_RCVBUF, &intVal);
+ return;
+ case JAVASOCKOPT_SO_BROADCAST:
+ setSocketOption(env, fd, SOL_SOCKET, SO_BROADCAST, &intVal);
+ return;
+ case JAVASOCKOPT_SO_REUSEADDR:
+ setSocketOption(env, fd, SOL_SOCKET, SO_REUSEADDR, &intVal);
+ return;
+ case JAVASOCKOPT_SO_KEEPALIVE:
+ setSocketOption(env, fd, SOL_SOCKET, SO_KEEPALIVE, &intVal);
+ return;
+ case JAVASOCKOPT_SO_OOBINLINE:
+ setSocketOption(env, fd, SOL_SOCKET, SO_OOBINLINE, &intVal);
+ return;
+ case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT:
+ // SO_REUSEPORT doesn't need to get set on this System
+ setSocketOption(env, fd, SOL_SOCKET, SO_REUSEADDR, &intVal);
+ return;
+ 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;
+ setSocketOption(env, fd, SOL_SOCKET, SO_RCVTIMEO, &timeout);
+ return;
}
-
+ case JAVASOCKOPT_IP_TOS:
+ if (family == AF_INET) {
+ setSocketOption(env, fd, IPPROTO_IP, IP_TOS, &intVal);
+ } else {
+ setSocketOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &intVal);
+ }
+ return;
+ case JAVASOCKOPT_TCP_NODELAY:
+ setSocketOption(env, fd, IPPROTO_TCP, TCP_NODELAY, &intVal);
+ return;
#ifdef ENABLE_MULTICAST
- case JAVASOCKOPT_MCAST_TTL: {
- if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
- return;
- }
- result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
- IPV6_MULTICAST_HOPS, &intVal,
- &intSize);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
+ case JAVASOCKOPT_MCAST_TTL:
+ if (family == AF_INET) {
+ // Although IPv6 was cleaned up to use int, and IPv4 non-multicast TTL uses int,
+ // IPv4 multicast TTL uses a byte.
+ char ttlVal = intVal;
+ setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttlVal);
+ } else {
+ setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &intVal);
}
-
- case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
- mcastAddDropMembership(env, handle, optVal,
- (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
- break;
- }
-
- case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
- mcastAddDropMembership(env, handle, optVal,
- (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
- break;
- }
-
- case JAVASOCKOPT_IP_MULTICAST_IF: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
+ return;
+ case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP:
+ mcastAddDropMembership(env, fd, optVal, IP_ADD_MEMBERSHIP);
+ return;
+ case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP:
+ mcastAddDropMembership(env, fd, optVal, IP_DROP_MEMBERSHIP);
+ return;
+ case JAVASOCKOPT_IP_MULTICAST_IF:
+ {
+ struct sockaddr_storage sockVal;
+ if (!env->IsInstanceOf(optVal, gCachedFields.iaddr_class) ||
+ !inetAddressToSocketAddress(env, optVal, 0, &sockVal)) {
return;
}
// This call is IPv4 only. The socket may be IPv6, but the address
@@ -2746,79 +2627,41 @@
}
struct ip_mreqn mcast_req;
memset(&mcast_req, 0, sizeof(mcast_req));
- struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
- mcast_req.imr_address = sin->sin_addr;
- result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
- &mcast_req, sizeof(mcast_req));
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_IP_MULTICAST_IF2: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return;
- }
- int addressFamily = getSocketAddressFamily(handle);
- int interfaceIndex = intVal;
- void *optionValue;
- socklen_t optionLength;
- struct ip_mreqn multicastRequest;
- switch (addressFamily) {
- case AF_INET:
- // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
- memset(&multicastRequest, 0, sizeof(multicastRequest));
- multicastRequest.imr_ifindex = interfaceIndex;
- optionValue = &multicastRequest;
- optionLength = sizeof(multicastRequest);
- break;
- case AF_INET6:
- // IPV6_MULTICAST_IF expects a pointer to an integer.
- optionValue = &interfaceIndex;
- optionLength = sizeof(interfaceIndex);
- break;
- default:
- jniThrowSocketException(env, EAFNOSUPPORT);
- return;
- }
- result = getOrSetSocketOption(SOCKOPT_SET, handle,
- IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
- &optionLength);
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return;
- }
- break;
- }
-
- case JAVASOCKOPT_IP_MULTICAST_LOOP: {
- result = getOrSetSocketOption(SOCKOPT_SET, handle,
- IP_MULTICAST_LOOP,
- IPV6_MULTICAST_LOOP, &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: {
- jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+ mcast_req.imr_address = reinterpret_cast<sockaddr_in*>(&sockVal)->sin_addr;
+ setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &mcast_req);
return;
}
-#endif // def ENABLE_MULTICAST
-
- default: {
- jniThrowSocketException(env, ENOPROTOOPT);
+ case JAVASOCKOPT_IP_MULTICAST_IF2:
+ if (family == AF_INET) {
+ // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
+ struct ip_mreqn multicastRequest;
+ memset(&multicastRequest, 0, sizeof(multicastRequest));
+ multicastRequest.imr_ifindex = intVal;
+ setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &multicastRequest);
+ } else {
+ // IPV6_MULTICAST_IF expects a pointer to an integer.
+ setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &intVal);
}
+ return;
+ case JAVASOCKOPT_IP_MULTICAST_LOOP:
+ if (family == AF_INET) {
+ setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_LOOP, &intVal);
+ } else {
+ setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &intVal);
+ }
+ return;
+#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:
+ jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+ return;
+#endif // def ENABLE_MULTICAST
+ default:
+ jniThrowSocketException(env, ENOPROTOOPT);
}
}
diff --git a/luni/src/test/java/java/net/URLConnectionTest.java b/luni/src/test/java/java/net/URLConnectionTest.java
index 6050c7d..9563256 100644
--- a/luni/src/test/java/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/java/net/URLConnectionTest.java
@@ -16,12 +16,12 @@
package java.net;
-import java.net.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Arrays;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import tests.support.Support_TestWebServer;
@@ -99,7 +99,7 @@
int n = 512*1024;
AtomicInteger total = new AtomicInteger(0);
ServerSocket ss = startSinkServer(total);
- URL url = new URL("http://localhost:" + ss.getLocalPort() + "/test1");
+ URL url = new URL("http://localhost:" + ss.getLocalPort() + "/" + UUID.randomUUID());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
@@ -121,7 +121,7 @@
}
}
out.close();
- assertTrue(conn.getResponseCode() > 0);
+ assertEquals(200, conn.getResponseCode());
assertEquals(uploadKind == UploadKind.CHUNKED ? -1 : n, total.get());
}