Loading core/java/android/net/LocalSocketImpl.java +90 −33 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import java.net.SocketOptions; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructLinger; import android.system.StructTimeval; /** * Socket implementation used for android.net.LocalSocket and Loading Loading @@ -184,13 +186,6 @@ class LocalSocketImpl private native void shutdown(FileDescriptor fd, boolean shutdownInput); private native Credentials getPeerCredentials_native( 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. Loading Loading @@ -434,24 +429,49 @@ class LocalSocketImpl throw new IOException("socket not created"); } if (optID == SocketOptions.SO_TIMEOUT) { return 0; } int value = getOption_native(fd, optID); switch (optID) { try { Object toReturn; switch (optID) { case SocketOptions.SO_TIMEOUT: StructTimeval timeval = Os.getsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_SNDTIMEO); toReturn = (int) timeval.toMillis(); break; case SocketOptions.SO_RCVBUF: case SocketOptions.SO_SNDBUF: return value; case SocketOptions.SO_REUSEADDR: int osOpt = javaSoToOsOpt(optID); 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: return value; throw new IOException("Unknown option: " + optID); } return toReturn; } catch (ErrnoException e) { throw e.rethrowAsIOException(); } } public void setOption(int optID, Object value) throws IOException { if (fd == null) { throw new IOException("socket not created"); } /* * Boolean.FALSE is used to disable some options, so it * is important to distinguish between FALSE and unset. Loading @@ -460,11 +480,6 @@ class LocalSocketImpl */ int boolValue = -1; int intValue = 0; if (fd == null) { throw new IOException("socket not created"); } if (value instanceof Integer) { intValue = (Integer)value; } else if (value instanceof Boolean) { Loading @@ -473,7 +488,39 @@ class LocalSocketImpl 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(); } } /** Loading Loading @@ -517,8 +564,7 @@ class LocalSocketImpl * @return non-null; peer credentials * @throws IOException */ public Credentials getPeerCredentials() throws IOException { public Credentials getPeerCredentials() throws IOException { return getPeerCredentials_native(fd); } Loading @@ -528,15 +574,26 @@ class LocalSocketImpl * @return non-null; socket name * @throws IOException on failure */ public LocalSocketAddress getSockAddress() throws IOException { public LocalSocketAddress getSockAddress() throws IOException { // This method has never been implemented. return null; //TODO implement this //return getSockName_native(fd); } @Override protected void finalize() throws IOException { 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); } } } core/jni/android_net_LocalSocketImpl.cpp +0 −206 Original line number Diff line number Diff line Loading @@ -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, jobject fileDescriptor) { Loading Loading @@ -803,64 +653,11 @@ static jobject socket_get_peer_credentials(JNIEnv *env, 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. */ static JNINativeMethod gMethods[] = { /* 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", (void*)socket_connect_local}, {"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local}, Loading @@ -876,9 +673,6 @@ static JNINativeMethod gMethods[] = { {"getPeerCredentials_native", "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", (void*) socket_get_peer_credentials} //,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;", // (void *) socket_getSockName} }; int register_android_net_LocalSocketImpl(JNIEnv *env) Loading Loading
core/java/android/net/LocalSocketImpl.java +90 −33 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import java.net.SocketOptions; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructLinger; import android.system.StructTimeval; /** * Socket implementation used for android.net.LocalSocket and Loading Loading @@ -184,13 +186,6 @@ class LocalSocketImpl private native void shutdown(FileDescriptor fd, boolean shutdownInput); private native Credentials getPeerCredentials_native( 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. Loading Loading @@ -434,24 +429,49 @@ class LocalSocketImpl throw new IOException("socket not created"); } if (optID == SocketOptions.SO_TIMEOUT) { return 0; } int value = getOption_native(fd, optID); switch (optID) { try { Object toReturn; switch (optID) { case SocketOptions.SO_TIMEOUT: StructTimeval timeval = Os.getsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_SNDTIMEO); toReturn = (int) timeval.toMillis(); break; case SocketOptions.SO_RCVBUF: case SocketOptions.SO_SNDBUF: return value; case SocketOptions.SO_REUSEADDR: int osOpt = javaSoToOsOpt(optID); 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: return value; throw new IOException("Unknown option: " + optID); } return toReturn; } catch (ErrnoException e) { throw e.rethrowAsIOException(); } } public void setOption(int optID, Object value) throws IOException { if (fd == null) { throw new IOException("socket not created"); } /* * Boolean.FALSE is used to disable some options, so it * is important to distinguish between FALSE and unset. Loading @@ -460,11 +480,6 @@ class LocalSocketImpl */ int boolValue = -1; int intValue = 0; if (fd == null) { throw new IOException("socket not created"); } if (value instanceof Integer) { intValue = (Integer)value; } else if (value instanceof Boolean) { Loading @@ -473,7 +488,39 @@ class LocalSocketImpl 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(); } } /** Loading Loading @@ -517,8 +564,7 @@ class LocalSocketImpl * @return non-null; peer credentials * @throws IOException */ public Credentials getPeerCredentials() throws IOException { public Credentials getPeerCredentials() throws IOException { return getPeerCredentials_native(fd); } Loading @@ -528,15 +574,26 @@ class LocalSocketImpl * @return non-null; socket name * @throws IOException on failure */ public LocalSocketAddress getSockAddress() throws IOException { public LocalSocketAddress getSockAddress() throws IOException { // This method has never been implemented. return null; //TODO implement this //return getSockName_native(fd); } @Override protected void finalize() throws IOException { 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); } } }
core/jni/android_net_LocalSocketImpl.cpp +0 −206 Original line number Diff line number Diff line Loading @@ -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, jobject fileDescriptor) { Loading Loading @@ -803,64 +653,11 @@ static jobject socket_get_peer_credentials(JNIEnv *env, 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. */ static JNINativeMethod gMethods[] = { /* 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", (void*)socket_connect_local}, {"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local}, Loading @@ -876,9 +673,6 @@ static JNINativeMethod gMethods[] = { {"getPeerCredentials_native", "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", (void*) socket_get_peer_credentials} //,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;", // (void *) socket_getSockName} }; int register_android_net_LocalSocketImpl(JNIEnv *env) Loading