am 761e39e1: Merge "Switch to using android.system.Os for more calls"
* commit '761e39e18990b657c488c78a6c048f625bd6b74a': Switch to using android.system.Os for more calls
This commit is contained in:
@@ -25,6 +25,8 @@ import java.net.SocketOptions;
|
|||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
|
import android.system.StructLinger;
|
||||||
|
import android.system.StructTimeval;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket implementation used for android.net.LocalSocket and
|
* Socket implementation used for android.net.LocalSocket and
|
||||||
@@ -184,13 +186,6 @@ class LocalSocketImpl
|
|||||||
private native void shutdown(FileDescriptor fd, boolean shutdownInput);
|
private native void shutdown(FileDescriptor fd, boolean shutdownInput);
|
||||||
private native Credentials getPeerCredentials_native(
|
private native Credentials getPeerCredentials_native(
|
||||||
FileDescriptor fd) throws IOException;
|
FileDescriptor fd) throws IOException;
|
||||||
private native int getOption_native(FileDescriptor fd, int optID)
|
|
||||||
throws IOException;
|
|
||||||
private native void setOption_native(FileDescriptor fd, int optID,
|
|
||||||
int b, int value) throws IOException;
|
|
||||||
|
|
||||||
// private native LocalSocketAddress getSockName_native
|
|
||||||
// (FileDescriptor fd) throws IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts a connection on a server socket.
|
* Accepts a connection on a server socket.
|
||||||
@@ -232,7 +227,7 @@ class LocalSocketImpl
|
|||||||
* or {@link LocalSocket#SOCKET_SEQPACKET}
|
* or {@link LocalSocket#SOCKET_SEQPACKET}
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void create (int sockType) throws IOException {
|
public void create(int sockType) throws IOException {
|
||||||
// no error if socket already created
|
// no error if socket already created
|
||||||
// need this for LocalServerSocket.accept()
|
// need this for LocalServerSocket.accept()
|
||||||
if (fd == null) {
|
if (fd == null) {
|
||||||
@@ -434,24 +429,49 @@ class LocalSocketImpl
|
|||||||
throw new IOException("socket not created");
|
throw new IOException("socket not created");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optID == SocketOptions.SO_TIMEOUT) {
|
try {
|
||||||
return 0;
|
Object toReturn;
|
||||||
}
|
switch (optID) {
|
||||||
|
case SocketOptions.SO_TIMEOUT:
|
||||||
int value = getOption_native(fd, optID);
|
StructTimeval timeval = Os.getsockoptTimeval(fd, OsConstants.SOL_SOCKET,
|
||||||
switch (optID)
|
OsConstants.SO_SNDTIMEO);
|
||||||
{
|
toReturn = (int) timeval.toMillis();
|
||||||
case SocketOptions.SO_RCVBUF:
|
break;
|
||||||
case SocketOptions.SO_SNDBUF:
|
case SocketOptions.SO_RCVBUF:
|
||||||
return value;
|
case SocketOptions.SO_SNDBUF:
|
||||||
case SocketOptions.SO_REUSEADDR:
|
case SocketOptions.SO_REUSEADDR:
|
||||||
default:
|
int osOpt = javaSoToOsOpt(optID);
|
||||||
return value;
|
toReturn = Os.getsockoptInt(fd, OsConstants.SOL_SOCKET, osOpt);
|
||||||
|
break;
|
||||||
|
case SocketOptions.SO_LINGER:
|
||||||
|
StructLinger linger=
|
||||||
|
Os.getsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER);
|
||||||
|
if (!linger.isOn()) {
|
||||||
|
toReturn = -1;
|
||||||
|
} else {
|
||||||
|
toReturn = linger.l_linger;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SocketOptions.TCP_NODELAY:
|
||||||
|
toReturn = Os.getsockoptInt(fd, OsConstants.IPPROTO_TCP,
|
||||||
|
OsConstants.TCP_NODELAY);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException("Unknown option: " + optID);
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
} catch (ErrnoException e) {
|
||||||
|
throw e.rethrowAsIOException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOption(int optID, Object value)
|
public void setOption(int optID, Object value)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
|
if (fd == null) {
|
||||||
|
throw new IOException("socket not created");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Boolean.FALSE is used to disable some options, so it
|
* Boolean.FALSE is used to disable some options, so it
|
||||||
* is important to distinguish between FALSE and unset.
|
* is important to distinguish between FALSE and unset.
|
||||||
@@ -460,11 +480,6 @@ class LocalSocketImpl
|
|||||||
*/
|
*/
|
||||||
int boolValue = -1;
|
int boolValue = -1;
|
||||||
int intValue = 0;
|
int intValue = 0;
|
||||||
|
|
||||||
if (fd == null) {
|
|
||||||
throw new IOException("socket not created");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value instanceof Integer) {
|
if (value instanceof Integer) {
|
||||||
intValue = (Integer)value;
|
intValue = (Integer)value;
|
||||||
} else if (value instanceof Boolean) {
|
} else if (value instanceof Boolean) {
|
||||||
@@ -473,7 +488,39 @@ class LocalSocketImpl
|
|||||||
throw new IOException("bad value: " + value);
|
throw new IOException("bad value: " + value);
|
||||||
}
|
}
|
||||||
|
|
||||||
setOption_native(fd, optID, boolValue, intValue);
|
try {
|
||||||
|
switch (optID) {
|
||||||
|
case SocketOptions.SO_LINGER:
|
||||||
|
StructLinger linger = new StructLinger(boolValue, intValue);
|
||||||
|
Os.setsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER, linger);
|
||||||
|
break;
|
||||||
|
case SocketOptions.SO_TIMEOUT:
|
||||||
|
/*
|
||||||
|
* SO_TIMEOUT from the core library gets converted to
|
||||||
|
* SO_SNDTIMEO, but the option is supposed to set both
|
||||||
|
* send and receive timeouts. Note: The incoming timeout
|
||||||
|
* value is in milliseconds.
|
||||||
|
*/
|
||||||
|
StructTimeval timeval = StructTimeval.fromMillis(intValue);
|
||||||
|
Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_SNDTIMEO,
|
||||||
|
timeval);
|
||||||
|
break;
|
||||||
|
case SocketOptions.SO_RCVBUF:
|
||||||
|
case SocketOptions.SO_SNDBUF:
|
||||||
|
case SocketOptions.SO_REUSEADDR:
|
||||||
|
int osOpt = javaSoToOsOpt(optID);
|
||||||
|
Os.setsockoptInt(fd, OsConstants.SOL_SOCKET, osOpt, intValue);
|
||||||
|
break;
|
||||||
|
case SocketOptions.TCP_NODELAY:
|
||||||
|
Os.setsockoptInt(fd, OsConstants.IPPROTO_TCP, OsConstants.TCP_NODELAY,
|
||||||
|
intValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IOException("Unknown option: " + optID);
|
||||||
|
}
|
||||||
|
} catch (ErrnoException e) {
|
||||||
|
throw e.rethrowAsIOException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -517,8 +564,7 @@ class LocalSocketImpl
|
|||||||
* @return non-null; peer credentials
|
* @return non-null; peer credentials
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public Credentials getPeerCredentials() throws IOException
|
public Credentials getPeerCredentials() throws IOException {
|
||||||
{
|
|
||||||
return getPeerCredentials_native(fd);
|
return getPeerCredentials_native(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,15 +574,26 @@ class LocalSocketImpl
|
|||||||
* @return non-null; socket name
|
* @return non-null; socket name
|
||||||
* @throws IOException on failure
|
* @throws IOException on failure
|
||||||
*/
|
*/
|
||||||
public LocalSocketAddress getSockAddress() throws IOException
|
public LocalSocketAddress getSockAddress() throws IOException {
|
||||||
{
|
// This method has never been implemented.
|
||||||
return null;
|
return null;
|
||||||
//TODO implement this
|
|
||||||
//return getSockName_native(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws IOException {
|
protected void finalize() throws IOException {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int javaSoToOsOpt(int optID) {
|
||||||
|
switch (optID) {
|
||||||
|
case SocketOptions.SO_SNDBUF:
|
||||||
|
return OsConstants.SO_SNDBUF;
|
||||||
|
case SocketOptions.SO_RCVBUF:
|
||||||
|
return OsConstants.SO_RCVBUF;
|
||||||
|
case SocketOptions.SO_REUSEADDR:
|
||||||
|
return OsConstants.SO_REUSEADDR;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unknown option: " + optID);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,156 +199,6 @@ socket_shutdown (JNIEnv *env, jobject object, jobject fileDescriptor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
java_opt_to_real(int optID, int* opt, int* level)
|
|
||||||
{
|
|
||||||
switch (optID)
|
|
||||||
{
|
|
||||||
case 4098:
|
|
||||||
*opt = SO_RCVBUF;
|
|
||||||
*level = SOL_SOCKET;
|
|
||||||
return true;
|
|
||||||
case 4097:
|
|
||||||
*opt = SO_SNDBUF;
|
|
||||||
*level = SOL_SOCKET;
|
|
||||||
return true;
|
|
||||||
case 4102:
|
|
||||||
*opt = SO_SNDTIMEO;
|
|
||||||
*level = SOL_SOCKET;
|
|
||||||
return true;
|
|
||||||
case 128:
|
|
||||||
*opt = SO_LINGER;
|
|
||||||
*level = SOL_SOCKET;
|
|
||||||
return true;
|
|
||||||
case 1:
|
|
||||||
*opt = TCP_NODELAY;
|
|
||||||
*level = IPPROTO_TCP;
|
|
||||||
return true;
|
|
||||||
case 4:
|
|
||||||
*opt = SO_REUSEADDR;
|
|
||||||
*level = SOL_SOCKET;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint
|
|
||||||
socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, jint optID)
|
|
||||||
{
|
|
||||||
int ret, value;
|
|
||||||
int opt, level;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
socklen_t size = sizeof(int);
|
|
||||||
|
|
||||||
if (!java_opt_to_real(optID, &opt, &level)) {
|
|
||||||
jniThrowIOException(env, -1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
|
|
||||||
|
|
||||||
if (env->ExceptionCheck()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case SO_LINGER:
|
|
||||||
{
|
|
||||||
struct linger lingr;
|
|
||||||
size = sizeof(lingr);
|
|
||||||
ret = getsockopt(fd, level, opt, &lingr, &size);
|
|
||||||
if (!lingr.l_onoff) {
|
|
||||||
value = -1;
|
|
||||||
} else {
|
|
||||||
value = lingr.l_linger;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
ret = getsockopt(fd, level, opt, &value, &size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
jniThrowIOException(env, errno);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void socket_setOption(
|
|
||||||
JNIEnv *env, jobject object, jobject fileDescriptor, jint optID,
|
|
||||||
jint boolValue, jint intValue) {
|
|
||||||
int ret;
|
|
||||||
int optname;
|
|
||||||
int level;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (!java_opt_to_real(optID, &optname, &level)) {
|
|
||||||
jniThrowIOException(env, -1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
|
|
||||||
|
|
||||||
if (env->ExceptionCheck()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (optname) {
|
|
||||||
case SO_LINGER: {
|
|
||||||
/*
|
|
||||||
* SO_LINGER is special because it needs to use a special
|
|
||||||
* "linger" struct as well as use the incoming boolean
|
|
||||||
* argument specially.
|
|
||||||
*/
|
|
||||||
struct linger lingr;
|
|
||||||
lingr.l_onoff = boolValue ? 1 : 0; // Force it to be 0 or 1.
|
|
||||||
lingr.l_linger = intValue;
|
|
||||||
ret = setsockopt(fd, level, optname, &lingr, sizeof(lingr));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SO_SNDTIMEO: {
|
|
||||||
/*
|
|
||||||
* SO_TIMEOUT from the core library gets converted to
|
|
||||||
* SO_SNDTIMEO, but the option is supposed to set both
|
|
||||||
* send and receive timeouts. Note: The incoming timeout
|
|
||||||
* value is in milliseconds.
|
|
||||||
*/
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = intValue / 1000;
|
|
||||||
timeout.tv_usec = (intValue % 1000) * 1000;
|
|
||||||
|
|
||||||
ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
|
|
||||||
(void *)&timeout, sizeof(timeout));
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
|
|
||||||
(void *)&timeout, sizeof(timeout));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
/*
|
|
||||||
* In all other cases, the translated option level and
|
|
||||||
* optname may be used directly for a call to setsockopt().
|
|
||||||
*/
|
|
||||||
ret = setsockopt(fd, level, optname, &intValue, sizeof(intValue));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
jniThrowIOException(env, errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static jint socket_pending (JNIEnv *env, jobject object,
|
static jint socket_pending (JNIEnv *env, jobject object,
|
||||||
jobject fileDescriptor)
|
jobject fileDescriptor)
|
||||||
{
|
{
|
||||||
@@ -803,64 +653,11 @@ static jobject socket_get_peer_credentials(JNIEnv *env,
|
|||||||
creds.pid, creds.uid, creds.gid);
|
creds.pid, creds.uid, creds.gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
//TODO change this to return an instance of LocalSocketAddress
|
|
||||||
static jobject socket_getSockName(JNIEnv *env,
|
|
||||||
jobject object, jobject fileDescriptor)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (fileDescriptor == NULL) {
|
|
||||||
jniThrowNullPointerException(env, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
|
|
||||||
|
|
||||||
if (env->ExceptionCheck()) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct sockaddr address;
|
|
||||||
struct sockaddr_un un_address;
|
|
||||||
} sa;
|
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
|
|
||||||
socklen_t namelen = sizeof(sa);
|
|
||||||
err = getsockname(fd, &(sa.address), &namelen);
|
|
||||||
|
|
||||||
if (err < 0) {
|
|
||||||
jniThrowIOException(env, errno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa.address.sa_family != AF_UNIX) {
|
|
||||||
// We think we're an impl only for AF_UNIX, so this should never happen.
|
|
||||||
|
|
||||||
jniThrowIOException(env, EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa.un_address.sun_path[0] == '\0') {
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JNI registration.
|
* JNI registration.
|
||||||
*/
|
*/
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
/* name, signature, funcPtr */
|
/* name, signature, funcPtr */
|
||||||
{"getOption_native", "(Ljava/io/FileDescriptor;I)I", (void*)socket_getOption},
|
|
||||||
{"setOption_native", "(Ljava/io/FileDescriptor;III)V", (void*)socket_setOption},
|
|
||||||
{"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V",
|
{"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V",
|
||||||
(void*)socket_connect_local},
|
(void*)socket_connect_local},
|
||||||
{"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local},
|
{"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local},
|
||||||
@@ -876,9 +673,6 @@ static JNINativeMethod gMethods[] = {
|
|||||||
{"getPeerCredentials_native",
|
{"getPeerCredentials_native",
|
||||||
"(Ljava/io/FileDescriptor;)Landroid/net/Credentials;",
|
"(Ljava/io/FileDescriptor;)Landroid/net/Credentials;",
|
||||||
(void*) socket_get_peer_credentials}
|
(void*) socket_get_peer_credentials}
|
||||||
//,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;",
|
|
||||||
// (void *) socket_getSockName}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_android_net_LocalSocketImpl(JNIEnv *env)
|
int register_android_net_LocalSocketImpl(JNIEnv *env)
|
||||||
|
|||||||
Reference in New Issue
Block a user