summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dalvik/src/main/java/dalvik/system/BlockGuard.java25
-rw-r--r--luni/src/main/java/java/net/DatagramSocketImpl.java12
-rw-r--r--luni/src/main/java/java/net/PlainDatagramSocketImpl.java27
-rw-r--r--luni/src/main/java/java/net/PlainSocketImpl.java7
-rw-r--r--luni/src/main/java/java/net/Socket.java4
-rw-r--r--luni/src/main/java/java/nio/DatagramChannelImpl.java8
-rw-r--r--luni/src/main/java/java/nio/SocketChannelImpl.java6
-rw-r--r--luni/src/main/java/libcore/io/ForwardingOs.java8
-rw-r--r--luni/src/main/java/libcore/io/IoUtils.java108
-rw-r--r--luni/src/main/java/libcore/io/Os.java8
-rw-r--r--luni/src/main/java/libcore/io/OsConstants.java3
-rw-r--r--luni/src/main/java/libcore/io/Posix.java8
-rw-r--r--luni/src/main/java/libcore/io/StructLinger.java42
-rw-r--r--luni/src/main/java/libcore/io/StructTimeval.java48
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java21
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java6
-rw-r--r--luni/src/main/native/JniConstants.cpp6
-rw-r--r--luni/src/main/native/JniConstants.h3
-rw-r--r--luni/src/main/native/NetworkUtilities.cpp12
-rw-r--r--luni/src/main/native/NetworkUtilities.h4
-rw-r--r--luni/src/main/native/libcore_io_OsConstants.cpp4
-rw-r--r--luni/src/main/native/libcore_io_Posix.cpp113
-rw-r--r--luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp205
23 files changed, 389 insertions, 299 deletions
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index 56abeb8..d3c5088 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -24,7 +24,10 @@ import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketOptions;
+import libcore.io.Libcore;
+import libcore.io.StructLinger;
import org.apache.harmony.luni.platform.INetworkSystem;
+import static libcore.io.OsConstants.*;
/**
* Mechanism to let threads set restrictions on what code is allowed
@@ -254,10 +257,6 @@ public final class BlockGuard {
mNetwork.connect(aFD, inetAddress, port, timeout);
}
- public InetAddress getSocketLocalAddress(FileDescriptor aFD) {
- return mNetwork.getSocketLocalAddress(aFD);
- }
-
public boolean select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
int numReadable, int numWritable, long timeout, int[] flags)
throws SocketException {
@@ -265,15 +264,6 @@ public final class BlockGuard {
return mNetwork.select(readFDs, writeFDs, numReadable, numWritable, timeout, flags);
}
- public int getSocketLocalPort(FileDescriptor aFD) {
- return mNetwork.getSocketLocalPort(aFD);
- }
-
- public Object getSocketOption(FileDescriptor aFD, int opt)
- throws SocketException {
- return mNetwork.getSocketOption(aFD, opt);
- }
-
public void setSocketOption(FileDescriptor aFD, int opt, Object optVal)
throws SocketException {
mNetwork.setSocketOption(aFD, opt, optVal);
@@ -291,13 +281,8 @@ public final class BlockGuard {
private boolean isLingerSocket(FileDescriptor fd) throws SocketException {
try {
- Object lingerValue = mNetwork.getSocketOption(fd, SocketOptions.SO_LINGER);
- if (lingerValue instanceof Boolean) {
- return (Boolean) lingerValue;
- } else if (lingerValue instanceof Integer) {
- return ((Integer) lingerValue) != 0;
- }
- throw new AssertionError(lingerValue.getClass().getName());
+ StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER);
+ return linger.isOn() && linger.l_linger > 0;
} catch (Exception ignored) {
// We're called via Socket.close (which doesn't ask for us to be called), so we
// must not throw here, because Socket.close must not throw if asked to close an
diff --git a/luni/src/main/java/java/net/DatagramSocketImpl.java b/luni/src/main/java/java/net/DatagramSocketImpl.java
index e92cb72..4485b18 100644
--- a/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -19,7 +19,7 @@ package java.net;
import java.io.FileDescriptor;
import java.io.IOException;
-import org.apache.harmony.luni.platform.Platform;
+import libcore.io.IoUtils;
/**
* The abstract superclass for datagram and multicast socket implementations.
@@ -82,18 +82,14 @@ public abstract class DatagramSocketImpl implements SocketOptions {
}
/**
- * Gets the local address to which the socket is bound.
- *
- * @return the local address to which the socket is bound.
+ * Returns the local address to which the socket is bound.
*/
InetAddress getLocalAddress() {
- return Platform.NETWORK.getSocketLocalAddress(fd);
+ return IoUtils.getSocketLocalAddress(fd);
}
/**
- * Gets the local port of this socket.
- *
- * @return the local port to which this socket is bound.
+ * Returns the local port to which this socket is bound.
*/
protected int getLocalPort() {
return localPort;
diff --git a/luni/src/main/java/java/net/PlainDatagramSocketImpl.java b/luni/src/main/java/java/net/PlainDatagramSocketImpl.java
index e023cae..e3ef565 100644
--- a/luni/src/main/java/java/net/PlainDatagramSocketImpl.java
+++ b/luni/src/main/java/java/net/PlainDatagramSocketImpl.java
@@ -38,13 +38,6 @@ import org.apache.harmony.luni.platform.Platform;
*/
public class PlainDatagramSocketImpl extends DatagramSocketImpl {
- private static final int MCAST_JOIN_GROUP = 19;
- private static final int MCAST_LEAVE_GROUP = 20;
-
- private static final int SO_BROADCAST = 32;
-
- private static final int IP_MULTICAST_TTL = 17;
-
private volatile boolean isNativeConnected;
private final CloseGuard guard = CloseGuard.get();
@@ -75,11 +68,11 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl {
if (port != 0) {
localPort = port;
} else {
- localPort = Platform.NETWORK.getSocketLocalPort(fd);
+ localPort = IoUtils.getSocketLocalPort(fd);
}
try {
- setOption(SO_BROADCAST, Boolean.TRUE);
+ setOption(SocketOptions.SO_BROADCAST, Boolean.TRUE);
} catch (IOException ignored) {
}
}
@@ -109,13 +102,13 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl {
}
}
- public Object getOption(int optID) throws SocketException {
- return Platform.NETWORK.getSocketOption(fd, optID);
+ @Override public Object getOption(int option) throws SocketException {
+ return IoUtils.getSocketOption(fd, option);
}
@Override
public int getTimeToLive() throws IOException {
- return (Integer) getOption(IP_MULTICAST_TTL);
+ return (Integer) getOption(IoUtils.IP_MULTICAST_TTL);
}
@Override
@@ -125,27 +118,27 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl {
@Override
public void join(InetAddress addr) throws IOException {
- setOption(MCAST_JOIN_GROUP, new MulticastGroupRequest(addr, null));
+ setOption(IoUtils.MCAST_JOIN_GROUP, new MulticastGroupRequest(addr, null));
}
@Override
public void joinGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
if (addr instanceof InetSocketAddress) {
InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
- setOption(MCAST_JOIN_GROUP, new MulticastGroupRequest(groupAddr, netInterface));
+ setOption(IoUtils.MCAST_JOIN_GROUP, new MulticastGroupRequest(groupAddr, netInterface));
}
}
@Override
public void leave(InetAddress addr) throws IOException {
- setOption(MCAST_LEAVE_GROUP, new MulticastGroupRequest(addr, null));
+ setOption(IoUtils.MCAST_LEAVE_GROUP, new MulticastGroupRequest(addr, null));
}
@Override
public void leaveGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {
if (addr instanceof InetSocketAddress) {
InetAddress groupAddr = ((InetSocketAddress) addr).getAddress();
- setOption(MCAST_LEAVE_GROUP, new MulticastGroupRequest(groupAddr, netInterface));
+ setOption(IoUtils.MCAST_LEAVE_GROUP, new MulticastGroupRequest(groupAddr, netInterface));
}
}
@@ -192,7 +185,7 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl {
@Override
public void setTimeToLive(int ttl) throws IOException {
- setOption(IP_MULTICAST_TTL, Integer.valueOf(ttl));
+ setOption(IoUtils.IP_MULTICAST_TTL, Integer.valueOf(ttl));
}
@Override
diff --git a/luni/src/main/java/java/net/PlainSocketImpl.java b/luni/src/main/java/java/net/PlainSocketImpl.java
index 7e608a9..937193e 100644
--- a/luni/src/main/java/java/net/PlainSocketImpl.java
+++ b/luni/src/main/java/java/net/PlainSocketImpl.java
@@ -133,7 +133,7 @@ public class PlainSocketImpl extends SocketImpl {
if (port != 0) {
this.localport = port;
} else {
- this.localport = Platform.NETWORK.getSocketLocalPort(fd);
+ this.localport = IoUtils.getSocketLocalPort(fd);
}
}
@@ -226,9 +226,8 @@ public class PlainSocketImpl extends SocketImpl {
}
}
- @Override
- public Object getOption(int optID) throws SocketException {
- return Platform.NETWORK.getSocketOption(fd, optID);
+ @Override public Object getOption(int option) throws SocketException {
+ return IoUtils.getSocketOption(fd, option);
}
@Override protected synchronized OutputStream getOutputStream() throws IOException {
diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java
index 3caf6ac..337f414 100644
--- a/luni/src/main/java/java/net/Socket.java
+++ b/luni/src/main/java/java/net/Socket.java
@@ -21,7 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.SocketChannel;
-import org.apache.harmony.luni.platform.Platform;
+import libcore.io.IoUtils;
/**
* Provides a client-side TCP socket.
@@ -948,7 +948,7 @@ public class Socket {
}
private void cacheLocalAddress() {
- this.localAddress = Platform.NETWORK.getSocketLocalAddress(impl.fd);
+ this.localAddress = IoUtils.getSocketLocalAddress(impl.fd);
}
/**
diff --git a/luni/src/main/java/java/nio/DatagramChannelImpl.java b/luni/src/main/java/java/nio/DatagramChannelImpl.java
index 7333549..9887394 100644
--- a/luni/src/main/java/java/nio/DatagramChannelImpl.java
+++ b/luni/src/main/java/java/nio/DatagramChannelImpl.java
@@ -96,14 +96,10 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann
}
/**
- * Returns the local address from the IP stack. This method should not be
- * called directly as it does not check the security policy.
- *
- * @return InetAddress the local address to which the socket is bound.
- * @see DatagramSocket
+ * Returns the local address to which the socket is bound.
*/
InetAddress getLocalAddress() {
- return Platform.NETWORK.getSocketLocalAddress(fd);
+ return IoUtils.getSocketLocalAddress(fd);
}
/**
diff --git a/luni/src/main/java/java/nio/SocketChannelImpl.java b/luni/src/main/java/java/nio/SocketChannelImpl.java
index 7d92502..35f5490 100644
--- a/luni/src/main/java/java/nio/SocketChannelImpl.java
+++ b/luni/src/main/java/java/nio/SocketChannelImpl.java
@@ -220,8 +220,10 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorChannel {
}
private void initLocalAddressAndPort() {
- localAddress = Platform.NETWORK.getSocketLocalAddress(fd);
- localPort = Platform.NETWORK.getSocketLocalPort(fd);
+ SocketAddress sa = Libcore.os.getsockname(fd);
+ InetSocketAddress isa = (InetSocketAddress) sa;
+ localAddress = isa.getAddress();
+ localPort = isa.getPort();
if (socket != null) {
socket.socketImpl().initLocalPort(localPort);
}
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 1f263a1..352a41e 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -17,6 +17,8 @@
package libcore.io;
import java.io.FileDescriptor;
+import java.net.InetAddress;
+import java.net.SocketAddress;
import java.nio.ByteBuffer;
import libcore.util.MutableInt;
import libcore.util.MutableLong;
@@ -44,6 +46,12 @@ public class ForwardingOs implements Os {
public void fsync(FileDescriptor fd) throws ErrnoException { os.fsync(fd); }
public void ftruncate(FileDescriptor fd, long length) throws ErrnoException { os.ftruncate(fd, length); }
public String getenv(String name) { return os.getenv(name); }
+ public SocketAddress getsockname(FileDescriptor fd) throws ErrnoException { return os.getsockname(fd); }
+ public int getsockoptByte(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptByte(fd, level, option); }
+ public InetAddress getsockoptInAddr(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptInAddr(fd, level, option); }
+ public int getsockoptInt(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptInt(fd, level, option); }
+ public StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptLinger(fd, level, option); }
+ public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptTimeval(fd, level, option); }
public int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException { return os.ioctlInt(fd, cmd, arg); }
public boolean isatty(FileDescriptor fd) { return os.isatty(fd); }
public void listen(FileDescriptor fd, int backlog) throws ErrnoException { os.listen(fd, backlog); }
diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java
index 4effb4b..0a4de9f 100644
--- a/luni/src/main/java/libcore/io/IoUtils.java
+++ b/luni/src/main/java/libcore/io/IoUtils.java
@@ -21,8 +21,13 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.InetSocketAddress;
import java.net.Socket;
+import java.net.SocketAddress;
import java.net.SocketException;
+import java.net.SocketOptions;
import java.util.Arrays;
import libcore.io.ErrnoException;
import libcore.io.Libcore;
@@ -225,6 +230,109 @@ public final class IoUtils {
}
/**
+ * java.net has its own socket options similar to the underlying Unix ones. We paper over the
+ * differences here.
+ */
+ public static Object getSocketOption(FileDescriptor fd, int option) throws SocketException {
+ try {
+ return getSocketOptionErrno(fd, option);
+ } catch (ErrnoException errnoException) {
+ throw errnoException.rethrowAsSocketException();
+ }
+ }
+
+ // Socket options used by java.net but not exposed in SocketOptions.
+ public static final int MCAST_JOIN_GROUP = 19;
+ public static final int MCAST_LEAVE_GROUP = 20;
+ public static final int IP_MULTICAST_TTL = 17;
+
+ private static Object getSocketOptionErrno(FileDescriptor fd, int option) throws SocketException {
+ switch (option) {
+ case SocketOptions.IP_MULTICAST_IF2:
+ if (boundIPv4(fd)) {
+ // The caller's asking for an interface index, but that's not how IPv4 works.
+ // Our Java should never get here, because we'll try IP_MULTICAST_IF first and
+ // that will satisfy us.
+ throw new SocketException("no interface index for IPv4");
+ } else {
+ return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF);
+ }
+ case SocketOptions.IP_MULTICAST_IF:
+ return Libcore.os.getsockoptInAddr(fd, IPPROTO_IP, IP_MULTICAST_IF);
+ case SocketOptions.IP_MULTICAST_LOOP:
+ if (boundIPv4(fd)) {
+ // Although IPv6 was cleaned up to use int, and IPv4 non-multicast TTL uses int,
+ // IPv4 multicast TTL uses a byte.
+ return booleanFromInt(Libcore.os.getsockoptByte(fd, IPPROTO_IP, IP_MULTICAST_LOOP));
+ } else {
+ return booleanFromInt(Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP));
+ }
+ case IoUtils.IP_MULTICAST_TTL:
+ if (boundIPv4(fd)) {
+ // Although IPv6 was cleaned up to use int, IPv4 multicast loopback uses a byte.
+ return Libcore.os.getsockoptByte(fd, IPPROTO_IP, IP_MULTICAST_TTL);
+ } else {
+ return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
+ }
+ case SocketOptions.IP_TOS:
+ if (boundIPv4(fd)) {
+ return Libcore.os.getsockoptInt(fd, IPPROTO_IP, IP_TOS);
+ } else {
+ return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_TCLASS);
+ }
+ case SocketOptions.SO_BROADCAST:
+ return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_BROADCAST));
+ case SocketOptions.SO_KEEPALIVE:
+ return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_KEEPALIVE));
+ case SocketOptions.SO_LINGER:
+ StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER);
+ if (!linger.isOn()) {
+ return false;
+ }
+ return linger.l_linger;
+ case SocketOptions.SO_OOBINLINE:
+ return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_OOBINLINE));
+ case SocketOptions.SO_RCVBUF:
+ return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_SNDBUF);
+ case SocketOptions.SO_REUSEADDR:
+ return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_REUSEADDR));
+ case SocketOptions.SO_SNDBUF:
+ return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_SNDBUF);
+ case SocketOptions.SO_TIMEOUT:
+ return (int) Libcore.os.getsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO).toMillis();
+ case SocketOptions.TCP_NODELAY:
+ return booleanFromInt(Libcore.os.getsockoptInt(fd, IPPROTO_TCP, TCP_NODELAY));
+ default:
+ throw new SocketException("unknown socket option " + option);
+ }
+ }
+
+ private static boolean boundIPv4(FileDescriptor fd) {
+ SocketAddress sa = Libcore.os.getsockname(fd);
+ if (!(sa instanceof InetSocketAddress)) {
+ return false;
+ }
+ InetSocketAddress isa = (InetSocketAddress) sa;
+ return (isa.getAddress() instanceof Inet4Address);
+ }
+
+ private static boolean booleanFromInt(int i) {
+ return (i != 0);
+ }
+
+ public static InetAddress getSocketLocalAddress(FileDescriptor fd) {
+ SocketAddress sa = Libcore.os.getsockname(fd);
+ InetSocketAddress isa = (InetSocketAddress) sa;
+ return isa.getAddress();
+ }
+
+ public static int getSocketLocalPort(FileDescriptor fd) {
+ SocketAddress sa = Libcore.os.getsockname(fd);
+ InetSocketAddress isa = (InetSocketAddress) sa;
+ return isa.getPort();
+ }
+
+ /**
* Returns the contents of 'path' as a byte array.
*/
public static byte[] readFileAsByteArray(String path) throws IOException {
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 0052e7a..0f10584 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -17,6 +17,8 @@
package libcore.io;
import java.io.FileDescriptor;
+import java.net.InetAddress;
+import java.net.SocketAddress;
import java.nio.ByteBuffer;
import libcore.util.MutableInt;
import libcore.util.MutableLong;
@@ -35,6 +37,12 @@ public interface Os {
public void fsync(FileDescriptor fd) throws ErrnoException;
public void ftruncate(FileDescriptor fd, long length) throws ErrnoException;
public String getenv(String name);
+ public SocketAddress getsockname(FileDescriptor fd) throws ErrnoException;
+ public int getsockoptByte(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public InetAddress getsockoptInAddr(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public int getsockoptInt(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException;
public int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException;
public boolean isatty(FileDescriptor fd);
public void listen(FileDescriptor fd, int backlog) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/OsConstants.java b/luni/src/main/java/libcore/io/OsConstants.java
index 69cb5a4..616e60a 100644
--- a/luni/src/main/java/libcore/io/OsConstants.java
+++ b/luni/src/main/java/libcore/io/OsConstants.java
@@ -155,6 +155,7 @@ public final class OsConstants {
public static final int IPV6_RECVPKTINFO = placeholder();
public static final int IPV6_RECVRTHDR = placeholder();
public static final int IPV6_RECVTCLASS = placeholder();
+ public static final int IPV6_TCLASS = placeholder();
public static final int IPV6_UNICAST_HOPS = placeholder();
public static final int IPV6_V6ONLY = placeholder();
public static final int IP_MULTICAST_IF = placeholder();
@@ -205,6 +206,7 @@ public final class OsConstants {
public static final int SOCK_RAW = placeholder();
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_BROADCAST = placeholder();
public static final int SO_DEBUG = placeholder();
public static final int SO_DONTROUTE = placeholder();
@@ -246,6 +248,7 @@ public final class OsConstants {
public static final int S_IXGRP = placeholder();
public static final int S_IXOTH = placeholder();
public static final int S_IXUSR = placeholder();
+ public static final int TCP_NODELAY = placeholder();
public static final int WCONTINUED = placeholder();
public static final int WEXITED = placeholder();
public static final int WNOHANG = placeholder();
diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java
index 77d32f0..6c49e51 100644
--- a/luni/src/main/java/libcore/io/Posix.java
+++ b/luni/src/main/java/libcore/io/Posix.java
@@ -17,6 +17,8 @@
package libcore.io;
import java.io.FileDescriptor;
+import java.net.InetAddress;
+import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.NioUtils;
import libcore.util.MutableInt;
@@ -38,6 +40,12 @@ public final class Posix implements Os {
public native void fsync(FileDescriptor fd) throws ErrnoException;
public native void ftruncate(FileDescriptor fd, long length) throws ErrnoException;
public native String getenv(String name);
+ public native SocketAddress getsockname(FileDescriptor fd) throws ErrnoException;
+ public native int getsockoptByte(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public native InetAddress getsockoptInAddr(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public native int getsockoptInt(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public native StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public native StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException;
public native int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException;
public native boolean isatty(FileDescriptor fd);
public native void listen(FileDescriptor fd, int backlog) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/StructLinger.java b/luni/src/main/java/libcore/io/StructLinger.java
new file mode 100644
index 0000000..9f149af
--- /dev/null
+++ b/luni/src/main/java/libcore/io/StructLinger.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.io;
+
+/**
+ * Corresponds to C's {@code struct linger} from
+ * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html">&lt;sys/socket.h&gt;</a>
+ */
+public final class StructLinger {
+ /** Whether or not linger is enabled. Non-zero is on. */
+ public final int l_onoff;
+
+ /** Linger time in seconds. */
+ public final int l_linger;
+
+ public StructLinger(int l_onoff, int l_linger) {
+ this.l_onoff = l_onoff;
+ this.l_linger = l_linger;
+ }
+
+ public boolean isOn() {
+ return l_onoff != 0;
+ }
+
+ @Override public String toString() {
+ return "StructLinger[l_onoff=" + l_onoff + ",l_linger=" + l_linger + "]";
+ }
+}
diff --git a/luni/src/main/java/libcore/io/StructTimeval.java b/luni/src/main/java/libcore/io/StructTimeval.java
new file mode 100644
index 0000000..0ed3509
--- /dev/null
+++ b/luni/src/main/java/libcore/io/StructTimeval.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.io;
+
+/**
+ * Corresponds to C's {@code struct timeval} from
+ * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html">&lt;sys/time.h&gt;</a>
+ */
+public final class StructTimeval {
+ /** Seconds. */
+ public final long tv_sec;
+
+ /** Microseconds. */
+ public final long tv_usec;
+
+ private StructTimeval(long tv_sec, long tv_usec) {
+ this.tv_sec = tv_sec;
+ this.tv_usec = tv_usec;
+ }
+
+ public static StructTimeval fromMillis(long millis) {
+ long tv_sec = millis / 1000;
+ long tv_usec = (millis - (tv_sec * 1000)) * 1000;
+ return new StructTimeval(tv_sec, tv_usec);
+ }
+
+ public long toMillis() {
+ return (tv_sec * 1000) + (tv_usec / 1000);
+ }
+
+ @Override public String toString() {
+ return "StructTimeval[tv_sec=" + tv_sec + ",tv_usec=" + tv_usec + "]";
+ }
+}
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 18c01dd..e5a511e 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
@@ -62,8 +62,6 @@ public interface INetworkSystem {
public void connect(FileDescriptor fd, InetAddress inetAddress, int port, int timeout)
throws SocketException;
- public InetAddress getSocketLocalAddress(FileDescriptor fd);
-
/**
* Select the given file descriptors for read and write operations.
*
@@ -99,25 +97,6 @@ public interface INetworkSystem {
throws SocketException;
/*
- * Query the IP stack for the local port to which this socket is bound.
- *
- * @param fd the socket descriptor
- * @return int the local port to which the socket is bound
- */
- public int getSocketLocalPort(FileDescriptor fd);
-
- /*
- * Query the IP stack for the nominated socket option.
- *
- * @param fd the socket descriptor @param opt the socket option type
- * @return the nominated socket option value
- *
- * @throws SocketException if the option is invalid
- */
- public Object getSocketOption(FileDescriptor fd, int opt)
- throws SocketException;
-
- /*
* Set the nominated socket option in the IP stack.
*
* @param fd the socket descriptor @param opt the option selector @param
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 930846a..3fc4ab4 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
@@ -52,12 +52,6 @@ final class OSNetworkSystem implements INetworkSystem {
public native void disconnectDatagram(FileDescriptor fd) throws SocketException;
- public native InetAddress getSocketLocalAddress(FileDescriptor fd);
-
- public native int getSocketLocalPort(FileDescriptor fd);
-
- public native Object getSocketOption(FileDescriptor fd, int opt) throws SocketException;
-
public native int read(FileDescriptor fd, byte[] data, int offset, int count)
throws IOException;
diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp
index 004eb4c..646bd3f 100644
--- a/luni/src/main/native/JniConstants.cpp
+++ b/luni/src/main/native/JniConstants.cpp
@@ -33,6 +33,7 @@ jclass JniConstants::fieldClass;
jclass JniConstants::fieldPositionIteratorClass;
jclass JniConstants::fileDescriptorClass;
jclass JniConstants::inetAddressClass;
+jclass JniConstants::inetSocketAddressClass;
jclass JniConstants::inflaterClass;
jclass JniConstants::integerClass;
jclass JniConstants::interfaceAddressClass;
@@ -50,8 +51,10 @@ jclass JniConstants::socketImplClass;
jclass JniConstants::stringArrayClass;
jclass JniConstants::stringClass;
jclass JniConstants::structFlockClass;
+jclass JniConstants::structLingerClass;
jclass JniConstants::structStatClass;
jclass JniConstants::structStatFsClass;
+jclass JniConstants::structTimevalClass;
jclass JniConstants::structUtsnameClass;
static jclass findClass(JNIEnv* env, const char* name) {
@@ -79,6 +82,7 @@ void JniConstants::init(JNIEnv* env) {
fieldPositionIteratorClass = findClass(env, "libcore/icu/NativeDecimalFormat$FieldPositionIterator");
fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
inetAddressClass = findClass(env, "java/net/InetAddress");
+ inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
inflaterClass = findClass(env, "java/util/zip/Inflater");
integerClass = findClass(env, "java/lang/Integer");
interfaceAddressClass = findClass(env, "java/net/InterfaceAddress");
@@ -96,7 +100,9 @@ void JniConstants::init(JNIEnv* env) {
stringArrayClass = findClass(env, "[Ljava/lang/String;");
stringClass = findClass(env, "java/lang/String");
structFlockClass = findClass(env, "libcore/io/StructFlock");
+ structLingerClass = findClass(env, "libcore/io/StructLinger");
structStatClass = findClass(env, "libcore/io/StructStat");
structStatFsClass = findClass(env, "libcore/io/StructStatFs");
+ structTimevalClass = findClass(env, "libcore/io/StructTimeval");
structUtsnameClass = findClass(env, "libcore/io/StructUtsname");
}
diff --git a/luni/src/main/native/JniConstants.h b/luni/src/main/native/JniConstants.h
index aa78907..2cc41a7 100644
--- a/luni/src/main/native/JniConstants.h
+++ b/luni/src/main/native/JniConstants.h
@@ -55,6 +55,7 @@ struct JniConstants {
static jclass fieldPositionIteratorClass;
static jclass fileDescriptorClass;
static jclass inetAddressClass;
+ static jclass inetSocketAddressClass;
static jclass inflaterClass;
static jclass integerClass;
static jclass interfaceAddressClass;
@@ -72,8 +73,10 @@ struct JniConstants {
static jclass stringArrayClass;
static jclass stringClass;
static jclass structFlockClass;
+ static jclass structLingerClass;
static jclass structStatClass;
static jclass structStatFsClass;
+ static jclass structTimevalClass;
static jclass structUtsnameClass;
};
diff --git a/luni/src/main/native/NetworkUtilities.cpp b/luni/src/main/native/NetworkUtilities.cpp
index 23c1edf..7628478 100644
--- a/luni/src/main/native/NetworkUtilities.cpp
+++ b/luni/src/main/native/NetworkUtilities.cpp
@@ -60,15 +60,15 @@ bool byteArrayToSocketAddress(JNIEnv* env, jclass, jbyteArray byteArray, int por
return true;
}
-jbyteArray socketAddressToByteArray(JNIEnv* env, sockaddr_storage* ss) {
- void* rawAddress;
+jbyteArray socketAddressToByteArray(JNIEnv* env, const sockaddr_storage* ss) {
+ const void* rawAddress;
size_t addressLength;
if (ss->ss_family == AF_INET) {
- sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ss);
+ const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(ss);
rawAddress = &sin->sin_addr.s_addr;
addressLength = 4;
} else if (ss->ss_family == AF_INET6) {
- sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ss);
+ const sockaddr_in6* sin6 = reinterpret_cast<const sockaddr_in6*>(ss);
rawAddress = &sin6->sin6_addr.s6_addr;
addressLength = 16;
} else {
@@ -85,7 +85,7 @@ jbyteArray socketAddressToByteArray(JNIEnv* env, sockaddr_storage* ss) {
if (byteArray == NULL) {
return NULL;
}
- env->SetByteArrayRegion(byteArray, 0, addressLength, reinterpret_cast<jbyte*>(rawAddress));
+ env->SetByteArrayRegion(byteArray, 0, addressLength, reinterpret_cast<const jbyte*>(rawAddress));
return byteArray;
}
@@ -101,7 +101,7 @@ jobject byteArrayToInetAddress(JNIEnv* env, jbyteArray byteArray) {
return env->CallStaticObjectMethod(JniConstants::inetAddressClass, getByAddressMethod, byteArray);
}
-jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* ss) {
+jobject socketAddressToInetAddress(JNIEnv* env, const sockaddr_storage* ss) {
jbyteArray byteArray = socketAddressToByteArray(env, ss);
return byteArrayToInetAddress(env, byteArray);
}
diff --git a/luni/src/main/native/NetworkUtilities.h b/luni/src/main/native/NetworkUtilities.h
index 76e622e..b2622c7 100644
--- a/luni/src/main/native/NetworkUtilities.h
+++ b/luni/src/main/native/NetworkUtilities.h
@@ -25,10 +25,10 @@ jobject byteArrayToInetAddress(JNIEnv* env, jbyteArray byteArray);
bool byteArrayToSocketAddress(JNIEnv* env, jclass, jbyteArray byteArray, int port, sockaddr_storage* ss);
// Convert from sockaddr_storage to byte[].
-jbyteArray socketAddressToByteArray(JNIEnv* env, sockaddr_storage* ss);
+jbyteArray socketAddressToByteArray(JNIEnv* env, const sockaddr_storage* ss);
// Convert from sockaddr_storage to InetAddress.
-jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* ss);
+jobject socketAddressToInetAddress(JNIEnv* env, const sockaddr_storage* ss);
diff --git a/luni/src/main/native/libcore_io_OsConstants.cpp b/luni/src/main/native/libcore_io_OsConstants.cpp
index a1bd88c..6165256 100644
--- a/luni/src/main/native/libcore_io_OsConstants.cpp
+++ b/luni/src/main/native/libcore_io_OsConstants.cpp
@@ -23,6 +23,7 @@
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -157,6 +158,7 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) {
initConstant(env, c, "IPV6_RECVPKTINFO", IPV6_RECVPKTINFO);
initConstant(env, c, "IPV6_RECVRTHDR", IPV6_RECVRTHDR);
initConstant(env, c, "IPV6_RECVTCLASS", IPV6_RECVTCLASS);
+ initConstant(env, c, "IPV6_TCLASS", IPV6_TCLASS);
initConstant(env, c, "IPV6_UNICAST_HOPS", IPV6_UNICAST_HOPS);
initConstant(env, c, "IPV6_V6ONLY", IPV6_V6ONLY);
initConstant(env, c, "IP_MULTICAST_IF", IP_MULTICAST_IF);
@@ -207,6 +209,7 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) {
initConstant(env, c, "SOCK_RAW", SOCK_RAW);
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_BROADCAST", SO_BROADCAST);
initConstant(env, c, "SO_DEBUG", SO_DEBUG);
initConstant(env, c, "SO_DONTROUTE", SO_DONTROUTE);
@@ -248,6 +251,7 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) {
initConstant(env, c, "S_IXGRP", S_IXGRP);
initConstant(env, c, "S_IXOTH", S_IXOTH);
initConstant(env, c, "S_IXUSR", S_IXUSR);
+ initConstant(env, c, "TCP_NODELAY", TCP_NODELAY);
initConstant(env, c, "WCONTINUED", WCONTINUED);
initConstant(env, c, "WEXITED", WEXITED);
initConstant(env, c, "WNOHANG", WNOHANG);
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 3feef86..447d099 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -19,6 +19,7 @@
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
+#include "NetworkUtilities.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
#include "StaticAssert.h"
@@ -26,12 +27,14 @@
#include <errno.h>
#include <fcntl.h>
+#include <netinet/in.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/utsname.h>
@@ -141,6 +144,28 @@ private:
std::vector<T*> mScopedByteArrays;
};
+static jobject makeInetSocketAddress(JNIEnv* env, const sockaddr_storage* ss, int port) {
+ jobject inetAddress = socketAddressToInetAddress(env, ss);
+ if (inetAddress == NULL) {
+ return NULL;
+ }
+ static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass, "<init>",
+ "(Ljava/net/InetAddress;I)V");
+ return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port);
+}
+
+static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage* ss) {
+ if (ss->ss_family == AF_INET) {
+ int port = ntohs(reinterpret_cast<const sockaddr_in*>(ss)->sin_port);
+ return makeInetSocketAddress(env, ss, port);
+ } else if (ss->ss_family == AF_INET6) {
+ int port = ntohs(reinterpret_cast<const sockaddr_in6*>(ss)->sin6_port);
+ return makeInetSocketAddress(env, ss, port);
+ }
+ // TODO: support AF_UNIX and AF_UNSPEC, and have some other behavior for other families
+ return NULL;
+}
+
static jobject makeStructStat(JNIEnv* env, const struct stat& sb) {
static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>",
"(JJIJIIJJJJJJJ)V");
@@ -168,6 +193,17 @@ static jobject makeStructStatFs(JNIEnv* env, const struct statfs& sb) {
static_cast<jlong>(sb.f_frsize));
}
+static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
+ static jmethodID ctor = env->GetMethodID(JniConstants::structLingerClass, "<init>", "(II)V");
+ return env->NewObject(JniConstants::structLingerClass, ctor, l.l_onoff, l.l_linger);
+}
+
+static jobject makeStructTimeval(JNIEnv* env, const struct timeval& tv) {
+ static jmethodID ctor = env->GetMethodID(JniConstants::structTimevalClass, "<init>", "(JJ)V");
+ return env->NewObject(JniConstants::structTimevalClass, ctor,
+ static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec));
+}
+
static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
#define TO_JAVA_STRING(NAME) \
jstring NAME = env->NewStringUTF(buf. NAME); \
@@ -320,6 +356,77 @@ static jstring Posix_getenv(JNIEnv* env, jobject, jstring javaName) {
return env->NewStringUTF(getenv(name.c_str()));
}
+static jobject Posix_getsockname(JNIEnv* env, jobject, jobject javaFd) {
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ sockaddr_storage ss;
+ sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
+ socklen_t byteCount = sizeof(ss);
+ memset(&ss, 0, byteCount);
+ int rc = TEMP_FAILURE_RETRY(getsockname(fd, sa, &byteCount));
+ if (rc == -1) {
+ throwErrnoException(env, "getsockname");
+ return NULL;
+ }
+ return makeSocketAddress(env, &ss);
+}
+
+static jint Posix_getsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ u_char result = 0;
+ socklen_t size = sizeof(result);
+ throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
+ return result;
+}
+
+static jobject Posix_getsockoptInAddr(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ sockaddr_storage ss;
+ memset(&ss, 0, sizeof(ss));
+ ss.ss_family = AF_INET; // This is only for the IPv4-only IP_MULTICAST_IF.
+ sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss);
+ socklen_t size = sizeof(sa->sin_addr);
+ int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &sa->sin_addr, &size));
+ if (rc == -1) {
+ throwErrnoException(env, "getsockopt");
+ return NULL;
+ }
+ return socketAddressToInetAddress(env, &ss);
+}
+
+static jint Posix_getsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ jint result = 0;
+ socklen_t size = sizeof(result);
+ throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
+ return result;
+}
+
+static jobject Posix_getsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ struct linger l;
+ socklen_t size = sizeof(l);
+ memset(&l, 0, size);
+ int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &l, &size));
+ if (rc == -1) {
+ throwErrnoException(env, "getsockopt");
+ return NULL;
+ }
+ return makeStructLinger(env, l);
+}
+
+static jobject Posix_getsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ struct timeval tv;
+ socklen_t size = sizeof(tv);
+ memset(&tv, 0, size);
+ int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &tv, &size));
+ if (rc == -1) {
+ throwErrnoException(env, "getsockopt");
+ return NULL;
+ }
+ return makeStructTimeval(env, tv);
+}
+
static jint Posix_ioctlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaArg) {
// This is complicated because ioctls may return their result by updating their argument
// or via their return value, so we need to support both.
@@ -598,6 +705,12 @@ static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"),
NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
NATIVE_METHOD(Posix, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
+ NATIVE_METHOD(Posix, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
+ NATIVE_METHOD(Posix, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"),
+ NATIVE_METHOD(Posix, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"),
+ NATIVE_METHOD(Posix, getsockoptInt, "(Ljava/io/FileDescriptor;II)I"),
+ NATIVE_METHOD(Posix, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructLinger;"),
+ NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructTimeval;"),
NATIVE_METHOD(Posix, ioctlInt, "(Ljava/io/FileDescriptor;ILlibcore/util/MutableInt;)I"),
NATIVE_METHOD(Posix, isatty, "(Ljava/io/FileDescriptor;)Z"),
NATIVE_METHOD(Posix, listen, "(Ljava/io/FileDescriptor;I)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 4bac577..9e1c4b2 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,23 +40,6 @@
#include <sys/un.h>
#include <unistd.h>
-// Temporary hack to build on systems that don't have up-to-date libc headers.
-#ifndef IPV6_TCLASS
-#ifdef __linux__
-#define IPV6_TCLASS 67 // Linux
-#else
-#define IPV6_TCLASS -1 // BSD(-like); TODO: Something better than this!
-#endif
-#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
-
#define JAVASOCKOPT_IP_MULTICAST_IF 16
#define JAVASOCKOPT_IP_MULTICAST_IF2 31
#define JAVASOCKOPT_IP_MULTICAST_LOOP 18
@@ -339,7 +322,6 @@ private:
JNIEnv* mEnv;
};
-#ifdef ENABLE_MULTICAST
static void mcastJoinLeaveGroup(JNIEnv* env, int fd, jobject javaGroupRequest, bool join) {
group_req groupRequest;
@@ -379,7 +361,6 @@ static void mcastJoinLeaveGroup(JNIEnv* env, int fd, jobject javaGroupRequest, b
return;
}
}
-#endif // def ENABLE_MULTICAST
static jint OSNetworkSystem_writeDirect(JNIEnv* env, jobject,
jobject fileDescriptor, jint address, jint offset, jint count) {
@@ -905,178 +886,6 @@ static jboolean OSNetworkSystem_selectImpl(JNIEnv* env, jclass,
translateFdSet(env, writeFDArray, countWriteC, writeFds, flagArray.get(), countReadC, SOCKET_OP_WRITE);
}
-static jobject OSNetworkSystem_getSocketLocalAddress(JNIEnv* env,
- jobject, jobject fileDescriptor) {
- NetFd fd(env, fileDescriptor);
- if (fd.isClosed()) {
- return NULL;
- }
-
- sockaddr_storage ss;
- socklen_t ssLen = sizeof(ss);
- memset(&ss, 0, ssLen);
- int rc = getsockname(fd.get(), reinterpret_cast<sockaddr*>(&ss), &ssLen);
- if (rc == -1) {
- // TODO: the public API doesn't allow failure, so this whole method
- // represents a broken design. In practice, though, getsockname can't
- // fail unless we give it invalid arguments.
- LOGE("getsockname failed: %s (errno=%i)", strerror(errno), errno);
- return NULL;
- }
- return socketAddressToInetAddress(env, &ss);
-}
-
-static jint OSNetworkSystem_getSocketLocalPort(JNIEnv* env, jobject,
- jobject fileDescriptor) {
- NetFd fd(env, fileDescriptor);
- if (fd.isClosed()) {
- return 0;
- }
-
- sockaddr_storage ss;
- socklen_t ssLen = sizeof(ss);
- memset(&ss, 0, sizeof(ss));
- int rc = getsockname(fd.get(), reinterpret_cast<sockaddr*>(&ss), &ssLen);
- if (rc == -1) {
- // TODO: the public API doesn't allow failure, so this whole method
- // represents a broken design. In practice, though, getsockname can't
- // fail unless we give it invalid arguments.
- LOGE("getsockname failed: %s (errno=%i)", strerror(errno), errno);
- return 0;
- }
- return getSocketAddressPort(&ss);
-}
-
-template <typename T>
-static bool getSocketOption(JNIEnv* env, const NetFd& fd, int level, int option, T* value) {
- socklen_t size = sizeof(*value);
- int rc = getsockopt(fd.get(), level, option, value, &size);
- if (rc == -1) {
- LOGE("getSocketOption(fd=%i, level=%i, option=%i) failed: %s (errno=%i)",
- fd.get(), level, option, strerror(errno), errno);
- jniThrowSocketException(env, errno);
- return false;
- }
- return true;
-}
-
-static jobject getSocketOption_Boolean(JNIEnv* env, const NetFd& fd, int level, int option) {
- int value;
- return getSocketOption(env, fd, level, option, &value) ? booleanValueOf(env, value) : NULL;
-}
-
-static jobject getSocketOption_Integer(JNIEnv* env, const NetFd& fd, int level, int option) {
- int value;
- return getSocketOption(env, fd, level, option, &value) ? integerValueOf(env, value) : NULL;
-}
-
-static jobject OSNetworkSystem_getSocketOption(JNIEnv* env, jobject, jobject fileDescriptor, jint option) {
- NetFd fd(env, fileDescriptor);
- if (fd.isClosed()) {
- return NULL;
- }
-
- int family = getSocketAddressFamily(fd.get());
- if (family != AF_INET && family != AF_INET6) {
- jniThrowSocketException(env, EAFNOSUPPORT);
- return NULL;
- }
-
- switch (option) {
- case JAVASOCKOPT_TCP_NODELAY:
- return getSocketOption_Boolean(env, fd, IPPROTO_TCP, TCP_NODELAY);
- case JAVASOCKOPT_SO_SNDBUF:
- return getSocketOption_Integer(env, fd, SOL_SOCKET, SO_SNDBUF);
- case JAVASOCKOPT_SO_RCVBUF:
- return getSocketOption_Integer(env, fd, SOL_SOCKET, SO_RCVBUF);
- case JAVASOCKOPT_SO_BROADCAST:
- return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_BROADCAST);
- case JAVASOCKOPT_SO_REUSEADDR:
- return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_REUSEADDR);
- case JAVASOCKOPT_SO_KEEPALIVE:
- return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_KEEPALIVE);
- case JAVASOCKOPT_SO_OOBINLINE:
- return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_OOBINLINE);
- case JAVASOCKOPT_IP_TOS:
- if (family == AF_INET) {
- return getSocketOption_Integer(env, fd, IPPROTO_IP, IP_TOS);
- } else {
- return getSocketOption_Integer(env, fd, IPPROTO_IPV6, IPV6_TCLASS);
- }
- case JAVASOCKOPT_SO_LINGER:
- {
- linger lingr;
- bool ok = getSocketOption(env, fd, SOL_SOCKET, SO_LINGER, &lingr);
- if (!ok) {
- return NULL; // We already threw.
- } else if (!lingr.l_onoff) {
- return booleanValueOf(env, false);
- } else {
- return integerValueOf(env, lingr.l_linger);
- }
- }
- case JAVASOCKOPT_SO_TIMEOUT:
- {
- timeval timeout;
- bool ok = getSocketOption(env, fd, SOL_SOCKET, SO_RCVTIMEO, &timeout);
- return ok ? integerValueOf(env, toMs(timeout)) : NULL;
- }
-#ifdef ENABLE_MULTICAST
- case JAVASOCKOPT_IP_MULTICAST_IF:
- {
- // Although setsockopt(2) can take an ip_mreqn for IP_MULTICAST_IF, getsockopt(2)
- // always returns an in_addr.
- sockaddr_storage ss;
- memset(&ss, 0, sizeof(ss));
- ss.ss_family = AF_INET; // This call is IPv4-only.
- sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss);
- if (!getSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &sa->sin_addr)) {
- return NULL;
- }
- return socketAddressToInetAddress(env, &ss);
- }
- case JAVASOCKOPT_IP_MULTICAST_IF2:
- if (family == AF_INET) {
- // The caller's asking for an interface index, but that's not how IPv4 works.
- // Our Java should never get here, because we'll try IP_MULTICAST_IF first and
- // that will satisfy us.
- jniThrowSocketException(env, EAFNOSUPPORT);
- } else {
- return getSocketOption_Integer(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF);
- }
- case JAVASOCKOPT_IP_MULTICAST_LOOP:
- if (family == AF_INET) {
- // Although IPv6 was cleaned up to use int, IPv4 multicast loopback uses a byte.
- u_char loopback;
- bool ok = getSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loopback);
- return ok ? booleanValueOf(env, loopback) : NULL;
- } else {
- return getSocketOption_Boolean(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
- }
- case JAVASOCKOPT_MULTICAST_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.
- u_char ttl;
- bool ok = getSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl);
- return ok ? integerValueOf(env, ttl) : NULL;
- } else {
- return getSocketOption_Integer(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
- }
-#else
- case JAVASOCKOPT_MULTICAST_TTL:
- case JAVASOCKOPT_IP_MULTICAST_IF:
- case JAVASOCKOPT_IP_MULTICAST_IF2:
- case JAVASOCKOPT_IP_MULTICAST_LOOP:
- jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
- return NULL;
-#endif // def ENABLE_MULTICAST
- default:
- jniThrowSocketException(env, ENOPROTOOPT);
- return NULL;
- }
-}
-
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));
@@ -1176,7 +985,6 @@ static void OSNetworkSystem_setSocketOption(JNIEnv* env, jobject, jobject fileDe
case JAVASOCKOPT_TCP_NODELAY:
setSocketOption(env, fd, IPPROTO_TCP, TCP_NODELAY, &intVal);
return;
-#ifdef ENABLE_MULTICAST
case JAVASOCKOPT_MCAST_JOIN_GROUP:
mcastJoinLeaveGroup(env, fd.get(), optVal, true);
return;
@@ -1237,16 +1045,6 @@ static void OSNetworkSystem_setSocketOption(JNIEnv* env, jobject, jobject fileDe
}
return;
}
-#else
- case JAVASOCKOPT_MULTICAST_TTL:
- case JAVASOCKOPT_MCAST_JOIN_GROUP:
- case JAVASOCKOPT_MCAST_LEAVE_GROUP:
- 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);
}
@@ -1273,9 +1071,6 @@ static JNINativeMethod gMethods[] = {
NATIVE_METHOD(OSNetworkSystem, connectNonBlocking, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)Z"),
NATIVE_METHOD(OSNetworkSystem, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;II)V"),
NATIVE_METHOD(OSNetworkSystem, disconnectDatagram, "(Ljava/io/FileDescriptor;)V"),
- NATIVE_METHOD(OSNetworkSystem, getSocketLocalAddress, "(Ljava/io/FileDescriptor;)Ljava/net/InetAddress;"),
- NATIVE_METHOD(OSNetworkSystem, getSocketLocalPort, "(Ljava/io/FileDescriptor;)I"),
- NATIVE_METHOD(OSNetworkSystem, getSocketOption, "(Ljava/io/FileDescriptor;I)Ljava/lang/Object;"),
NATIVE_METHOD(OSNetworkSystem, isConnected, "(Ljava/io/FileDescriptor;I)Z"),
NATIVE_METHOD(OSNetworkSystem, read, "(Ljava/io/FileDescriptor;[BII)I"),
NATIVE_METHOD(OSNetworkSystem, readDirect, "(Ljava/io/FileDescriptor;II)I"),