diff options
13 files changed, 47 insertions, 121 deletions
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java index d3c5088..d212cfc 100644 --- a/dalvik/src/main/java/dalvik/system/BlockGuard.java +++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java @@ -264,11 +264,6 @@ public final class BlockGuard { return mNetwork.select(readFDs, writeFDs, numReadable, numWritable, timeout, flags); } - public void setSocketOption(FileDescriptor aFD, int opt, Object optVal) - throws SocketException { - mNetwork.setSocketOption(aFD, opt, optVal); - } - public void close(FileDescriptor aFD) throws IOException { // We exclude sockets without SO_LINGER so that apps can close their network connections // in methods like onDestroy, which will run on the UI thread, without jumping through diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java index ad9a551..95f1003 100644 --- a/luni/src/main/java/java/net/DatagramSocket.java +++ b/luni/src/main/java/java/net/DatagramSocket.java @@ -19,6 +19,9 @@ package java.net; import java.io.IOException; import java.nio.channels.DatagramChannel; +import libcore.io.ErrnoException; +import libcore.io.Libcore; +import static libcore.io.OsConstants.*; /** * This class implements a UDP socket for sending and receiving {@code @@ -377,7 +380,7 @@ public class DatagramSocket { * via this socket are transmitted via the specified interface. Any * packets received by this socket will come from the specified * interface. Broadcast datagrams received on this interface will - * be processed by this socket. {@see SocketOptions#SO_BINDTODEVICE} + * be processed by this socket. This corresponds to Linux's SO_BINDTODEVICE. * * @hide used by GoogleTV for DHCP */ @@ -385,7 +388,11 @@ public class DatagramSocket { if (netInterface == null) { throw new NullPointerException("networkInterface == null"); } - impl.setOption(SocketOptions.SO_BINDTODEVICE, Integer.valueOf(netInterface.getIndex())); + try { + Libcore.os.setsockoptIfreq(impl.fd, SOL_SOCKET, SO_BINDTODEVICE, netInterface.getName()); + } catch (ErrnoException errnoException) { + throw errnoException.rethrowAsSocketException(); + } } /** diff --git a/luni/src/main/java/java/net/SocketOptions.java b/luni/src/main/java/java/net/SocketOptions.java index b2a1bb1..e23fc97 100644 --- a/luni/src/main/java/java/net/SocketOptions.java +++ b/luni/src/main/java/java/net/SocketOptions.java @@ -97,17 +97,6 @@ public interface SocketOptions { public static final int SO_RCVBUF = 4098; /** - * This integer option can be used to bind a datagram socket to a - * particular network interface. When this is done, only packets - * received on the specified interface will be processed by the - * socket. Packets sent via this socket will be transmitted by - * the specified interface. The argument to this operation is the - * network interface index. - * @hide - */ - public static final int SO_BINDTODEVICE = 8192; - - /** * This boolean option specifies whether the kernel sends keepalive messages. */ public static final int SO_KEEPALIVE = 8; diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index 397fa10..8149e9a 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -73,7 +73,9 @@ public class ForwardingOs implements Os { public void rename(String oldPath, String newPath) throws ErrnoException { os.rename(oldPath, newPath); } public long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException { return os.sendfile(outFd, inFd, inOffset, byteCount); } public void setsockoptByte(FileDescriptor fd, int level, int option, int value) throws ErrnoException { os.setsockoptByte(fd, level, option, value); } + public void setsockoptIfreq(FileDescriptor fd, int level, int option, String value) throws ErrnoException { os.setsockoptIfreq(fd, level, option, value); } public void setsockoptInt(FileDescriptor fd, int level, int option, int value) throws ErrnoException { os.setsockoptInt(fd, level, option, value); } + public void setsockoptIpMreqn(FileDescriptor fd, int level, int option, int value) throws ErrnoException { os.setsockoptIpMreqn(fd, level, option, value); } public void setsockoptGroupReq(FileDescriptor fd, int level, int option, StructGroupReq value) throws ErrnoException { os.setsockoptGroupReq(fd, level, option, value); } public void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException { os.setsockoptLinger(fd, level, option, value); } public void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException { os.setsockoptTimeval(fd, level, option, value); } diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java index 6334d2b..bf4e422 100644 --- a/luni/src/main/java/libcore/io/IoUtils.java +++ b/luni/src/main/java/libcore/io/IoUtils.java @@ -289,7 +289,7 @@ public final class IoUtils { case SocketOptions.TCP_NODELAY: return booleanFromInt(Libcore.os.getsockoptInt(fd, IPPROTO_TCP, TCP_NODELAY)); default: - throw new SocketException("unknown socket option " + option); + throw new SocketException("Unknown socket option: " + option); } } @@ -316,12 +316,11 @@ public final class IoUtils { private static void setSocketOptionErrno(FileDescriptor fd, int option, Object value) throws SocketException { switch (option) { case SocketOptions.IP_MULTICAST_IF: - // TODO - org.apache.harmony.luni.platform.Platform.NETWORK.setSocketOption(fd, option, value); - return; + throw new UnsupportedOperationException("Use IP_MULTICAST_IF2 on Android"); case SocketOptions.IP_MULTICAST_IF2: - // TODO - org.apache.harmony.luni.platform.Platform.NETWORK.setSocketOption(fd, option, value); + // Although IPv6 was cleaned up to use int, IPv4 uses an ip_mreqn containing an int. + Libcore.os.setsockoptIpMreqn(fd, IPPROTO_IP, IP_MULTICAST_IF, (Integer) value); + Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (Integer) value); return; case SocketOptions.IP_MULTICAST_LOOP: // Although IPv6 was cleaned up to use int, IPv4 multicast loopback uses a byte. @@ -382,10 +381,7 @@ public final class IoUtils { Libcore.os.setsockoptGroupReq(fd, level, op, groupReq); return; default: - // TODO - org.apache.harmony.luni.platform.Platform.NETWORK.setSocketOption(fd, option, value); - return; - //throw new SocketException("unknown socket option " + option); + throw new SocketException("Unknown socket option: " + option); } } diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index 08b8564..6be0313 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -64,7 +64,9 @@ public interface Os { public void rename(String oldPath, String newPath) throws ErrnoException; public long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException; public void setsockoptByte(FileDescriptor fd, int level, int option, int value) throws ErrnoException; + public void setsockoptIfreq(FileDescriptor fd, int level, int option, String value) throws ErrnoException; public void setsockoptInt(FileDescriptor fd, int level, int option, int value) throws ErrnoException; + public void setsockoptIpMreqn(FileDescriptor fd, int level, int option, int value) throws ErrnoException; public void setsockoptGroupReq(FileDescriptor fd, int level, int option, StructGroupReq value) throws ErrnoException; public void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException; public void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException; diff --git a/luni/src/main/java/libcore/io/OsConstants.java b/luni/src/main/java/libcore/io/OsConstants.java index 616e60a..72a64f0 100644 --- a/luni/src/main/java/libcore/io/OsConstants.java +++ b/luni/src/main/java/libcore/io/OsConstants.java @@ -207,6 +207,7 @@ public final class OsConstants { public static final int SOCK_SEQPACKET = placeholder(); public static final int SOCK_STREAM = placeholder(); public static final int SOL_SOCKET = placeholder(); + public static final int SO_BINDTODEVICE = placeholder(); public static final int SO_BROADCAST = placeholder(); public static final int SO_DEBUG = placeholder(); public static final int SO_DONTROUTE = placeholder(); diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index 72ebc62..682416e 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -73,7 +73,9 @@ public final class Posix implements Os { public native void rename(String oldPath, String newPath) throws ErrnoException; public native long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException; public native void setsockoptByte(FileDescriptor fd, int level, int option, int value) throws ErrnoException; + public native void setsockoptIfreq(FileDescriptor fd, int level, int option, String value) throws ErrnoException; public native void setsockoptInt(FileDescriptor fd, int level, int option, int value) throws ErrnoException; + public native void setsockoptIpMreqn(FileDescriptor fd, int level, int option, int value) throws ErrnoException; public native void setsockoptGroupReq(FileDescriptor fd, int level, int option, StructGroupReq value) throws ErrnoException; public native void setsockoptLinger(FileDescriptor fd, int level, int option, StructLinger value) throws ErrnoException; public native void setsockoptTimeval(FileDescriptor fd, int level, int option, StructTimeval value) throws ErrnoException; diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java index e5a511e..8d1c76f 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java @@ -96,17 +96,6 @@ public interface INetworkSystem { int numReadable, int numWritable, long timeout, int[] flags) throws SocketException; - /* - * Set the nominated socket option in the IP stack. - * - * @param fd the socket descriptor @param opt the option selector @param - * optVal the nominated option value - * - * @throws SocketException if the option is invalid or cannot be set - */ - public void setSocketOption(FileDescriptor fd, int opt, Object optVal) - throws SocketException; - /** * It is an error to close the same file descriptor from multiple threads * concurrently. diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java index 3fc4ab4..1796507 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java @@ -91,9 +91,6 @@ final class OSNetworkSystem implements INetworkSystem { public native void sendUrgentData(FileDescriptor fd, byte value); - public native void setSocketOption(FileDescriptor fd, int opt, Object optVal) - throws SocketException; - public native void close(FileDescriptor fd) throws IOException; public native int write(FileDescriptor fd, byte[] data, int offset, int count) diff --git a/luni/src/main/native/libcore_io_OsConstants.cpp b/luni/src/main/native/libcore_io_OsConstants.cpp index 6165256..a461262 100644 --- a/luni/src/main/native/libcore_io_OsConstants.cpp +++ b/luni/src/main/native/libcore_io_OsConstants.cpp @@ -210,6 +210,7 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "SOCK_SEQPACKET", SOCK_SEQPACKET); initConstant(env, c, "SOCK_STREAM", SOCK_STREAM); initConstant(env, c, "SOL_SOCKET", SOL_SOCKET); + initConstant(env, c, "SO_BINDTODEVICE", SO_BINDTODEVICE); initConstant(env, c, "SO_BROADCAST", SO_BROADCAST); initConstant(env, c, "SO_DEBUG", SO_DEBUG); initConstant(env, c, "SO_DONTROUTE", SO_DONTROUTE); diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index 883719c..cf1c56e 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -27,6 +27,7 @@ #include <errno.h> #include <fcntl.h> +#include <net/if.h> #include <netinet/in.h> #include <stdlib.h> #include <sys/ioctl.h> @@ -604,11 +605,32 @@ static void Posix_setsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint leve throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &byte, sizeof(byte)))); } +static void Posix_setsockoptIfreq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jstring value) { + ScopedUtfChars interfaceName(env, value); + if (interfaceName.c_str() == NULL) { + return; + } + struct ifreq req; + memset(&req, 0, sizeof(req)); + strncpy(req.ifr_name, interfaceName.c_str(), sizeof(req.ifr_name)); + req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; + int fd = jniGetFDFromFileDescriptor(env, javaFd); + throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)))); +} + static void Posix_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) { int fd = jniGetFDFromFileDescriptor(env, javaFd); throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value)))); } +static void Posix_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) { + ip_mreqn req; + memset(&req, 0, sizeof(req)); + req.imr_ifindex = value; + int fd = jniGetFDFromFileDescriptor(env, javaFd); + throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)))); +} + static void Posix_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupReq) { struct group_req value; @@ -788,7 +810,9 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"), NATIVE_METHOD(Posix, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Llibcore/util/MutableLong;J)J"), NATIVE_METHOD(Posix, setsockoptByte, "(Ljava/io/FileDescriptor;III)V"), + NATIVE_METHOD(Posix, setsockoptIfreq, "(Ljava/io/FileDescriptor;IILjava/lang/String;)V"), NATIVE_METHOD(Posix, setsockoptInt, "(Ljava/io/FileDescriptor;III)V"), + NATIVE_METHOD(Posix, setsockoptIpMreqn, "(Ljava/io/FileDescriptor;III)V"), NATIVE_METHOD(Posix, setsockoptGroupReq, "(Ljava/io/FileDescriptor;IILlibcore/io/StructGroupReq;)V"), NATIVE_METHOD(Posix, setsockoptLinger, "(Ljava/io/FileDescriptor;IILlibcore/io/StructLinger;)V"), NATIVE_METHOD(Posix, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILlibcore/io/StructTimeval;)V"), 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 96c2c4b..9e8f4e8 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 @@ -40,10 +40,6 @@ #include <sys/un.h> #include <unistd.h> -#define JAVASOCKOPT_IP_MULTICAST_IF 16 -#define JAVASOCKOPT_IP_MULTICAST_IF2 31 -#define JAVASOCKOPT_SO_BINDTODEVICE 8192 - /* constants for OSNetworkSystem_selectImpl */ #define SOCKET_OP_NONE 0 #define SOCKET_OP_READ 1 @@ -765,80 +761,6 @@ static jboolean OSNetworkSystem_selectImpl(JNIEnv* env, jclass, translateFdSet(env, writeFDArray, countWriteC, writeFds, flagArray.get(), countReadC, SOCKET_OP_WRITE); } -template <typename T> -static void setSocketOption(JNIEnv* env, const NetFd& fd, int level, int option, T* value) { - int rc = setsockopt(fd.get(), level, option, value, sizeof(*value)); - if (rc == -1) { - LOGE("setSocketOption(fd=%i, level=%i, option=%i) failed: %s (errno=%i)", - fd.get(), level, option, strerror(errno), errno); - jniThrowSocketException(env, errno); - } -} - -static void OSNetworkSystem_setSocketOption(JNIEnv* env, jobject, jobject fileDescriptor, jint option, jobject optVal) { - NetFd fd(env, fileDescriptor); - if (fd.isClosed()) { - return; - } - - int intVal; - bool wasBoolean = false; - if (env->IsInstanceOf(optVal, JniConstants::integerClass)) { - intVal = intValue(env, optVal); - } else if (env->IsInstanceOf(optVal, JniConstants::booleanClass)) { - intVal = (int) booleanValue(env, optVal); - wasBoolean = true; - } else if (env->IsInstanceOf(optVal, JniConstants::inetAddressClass)) { - // We use optVal directly as an InetAddress for IP_MULTICAST_IF. - } else { - jniThrowSocketException(env, EINVAL); - return; - } - - switch (option) { - case JAVASOCKOPT_SO_BINDTODEVICE: { - // intVal contains the interface index - char ifname[IF_NAMESIZE]; - - if (if_indextoname(intVal, ifname) == NULL) { - jniThrowSocketException(env, ENODEV); - } else { - ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; - setSocketOption(env, fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr); - } - return; - } - case JAVASOCKOPT_IP_MULTICAST_IF: - { - sockaddr_storage sockVal; - if (!env->IsInstanceOf(optVal, JniConstants::inetAddressClass) || - !inetAddressToSocketAddress(env, optVal, 0, &sockVal)) { - return; - } - ip_mreqn mcast_req; - memset(&mcast_req, 0, sizeof(mcast_req)); - mcast_req.imr_address = reinterpret_cast<sockaddr_in*>(&sockVal)->sin_addr; - setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &mcast_req); - return; - } - case JAVASOCKOPT_IP_MULTICAST_IF2: - // IP_MULTICAST_IF expects a pointer to an ip_mreqn struct. - ip_mreqn multicastRequest; - memset(&multicastRequest, 0, sizeof(multicastRequest)); - multicastRequest.imr_ifindex = intVal; - setSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &multicastRequest); - // IPV6_MULTICAST_IF expects a pointer to an integer. - setSocketOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &intVal); - return; - default: - jniThrowSocketException(env, ENOPROTOOPT); - } -} - static void OSNetworkSystem_close(JNIEnv* env, jobject, jobject fileDescriptor) { NetFd fd(env, fileDescriptor); if (fd.isClosed()) { @@ -869,7 +791,6 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(OSNetworkSystem, send, "(Ljava/io/FileDescriptor;[BIIILjava/net/InetAddress;)I"), NATIVE_METHOD(OSNetworkSystem, sendDirect, "(Ljava/io/FileDescriptor;IIIILjava/net/InetAddress;)I"), NATIVE_METHOD(OSNetworkSystem, sendUrgentData, "(Ljava/io/FileDescriptor;B)V"), - NATIVE_METHOD(OSNetworkSystem, setSocketOption, "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V"), NATIVE_METHOD(OSNetworkSystem, write, "(Ljava/io/FileDescriptor;[BII)I"), NATIVE_METHOD(OSNetworkSystem, writeDirect, "(Ljava/io/FileDescriptor;III)I"), }; |