diff --git a/README.md b/README.md index 7497b41..838ee06 100644 --- a/README.md +++ b/README.md @@ -47,12 +47,17 @@ an independent socket for each new incoming connection. VERSION ======= -Version 0.94 - 2010-04-30 +Version 0.95 - 2016-02-04 VERSION HISTORY =============== +Version 0.95 - 2016-02-04 + - Socket timeout. + - Possibility to specify a folder for unpacked native library. + - Minor bug fixes. + Version 0.94 - 2010-04-30 - Now builds on OSX. - Build system switched to autoconf. diff --git a/com/etsy/net/UnixDomainSocket.c b/com/etsy/net/UnixDomainSocket.c index 7da4a36..1576d6f 100644 --- a/com/etsy/net/UnixDomainSocket.c +++ b/com/etsy/net/UnixDomainSocket.c @@ -131,7 +131,6 @@ Java_com_etsy_net_UnixDomainSocket_nativeOpen(JNIEnv * jEnv, { int s; /* socket file handle */ struct sockaddr_un sa; - struct timeval timeout; const char *socketFile = (*jEnv)->GetStringUTFChars(jEnv, jSocketFile, NULL); socklen_t salen = sockaddr_init(socketFile, &sa); @@ -145,16 +144,6 @@ Java_com_etsy_net_UnixDomainSocket_nativeOpen(JNIEnv * jEnv, return -1; } - timeout.tv_sec = 10; - timeout.tv_usec = 0; - if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { - perror("nativeOpen: setsockopt SO_RCVTIMEO failed"); - } - - if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { - perror("nativeOpen: setsockopt SO_SNDTIMEO failed"); - } - (*jEnv)->ReleaseStringUTFChars(jEnv, jSocketFile, socketFile); /* return the socket file handle */ @@ -208,6 +197,18 @@ Java_com_etsy_net_UnixDomainSocket_nativeWrite(JNIEnv * jEnv, return count; } +JNIEXPORT jint JNICALL +Java_com_etsy_net_UnixDomainSocket_nativeTimeout(JNIEnv * jEnv, + jclass jClass, + jint jSocketFileHandle, + jint milis) +{ + struct timeval timeout; + timeout.tv_sec = milis / 1000; + timeout.tv_usec = (milis % 1000) * 1000; + return setsockopt(jSocketFileHandle, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); +} + JNIEXPORT jint JNICALL Java_com_etsy_net_UnixDomainSocket_nativeClose(JNIEnv * jEnv, jclass jClass, diff --git a/com/etsy/net/UnixDomainSocket.java b/com/etsy/net/UnixDomainSocket.java index 64f05e9..d4ae5fe 100644 --- a/com/etsy/net/UnixDomainSocket.java +++ b/com/etsy/net/UnixDomainSocket.java @@ -199,6 +199,8 @@ protected native static int nativeRead(int nativeSocketFileHandle, protected native static int nativeWrite(int nativeSocketFileHandle, byte[] b, int off, int len); + protected native static int nativeTimeout(int nativeSocketFileHandle, int milis); + protected native static int nativeClose(int nativeSocketFileHandle); protected native static int nativeCloseInput(int nativeSocketFileHandle); @@ -252,11 +254,27 @@ public OutputStream getOutputStream() { * @param timeout * The specified timeout, in milliseconds. */ + @Deprecated public void setTimeout(int timeout) { - this.timeout = timeout; + try { + setSoTimeout(timeout); + } catch (IOException ex) { + throw new RuntimeException(ex); + } } + @Deprecated public int getTimeout() { + return getSoTimeout(); + } + + public void setSoTimeout(int timeout) throws IOException { + if(nativeTimeout(nativeSocketFileHandle, timeout) == -1) + throw new IOException("Unable to configure socket timeout"); + this.timeout = timeout; + } + + public int getSoTimeout() { return timeout; } @@ -281,33 +299,9 @@ protected class UnixDomainSocketInputStream extends InputStream { @Override public int read() throws IOException { byte[] b = new byte[1]; - int count; - // If a timeout is set, then use a read thread - if (timeout > 0) { - // Create a thread to read the byte - UnixDomainSocketReadThread thread = new UnixDomainSocketReadThread( - b, 0, 1); - thread.setDaemon(true); - thread.start(); - try { - // Wait up until the specified timeout for the thread to - // complete - thread.join(timeout); - } catch (InterruptedException e) { - } - // If the thread is still alive the read() call has - // blocked longer than the specified timeout - if (thread.isAlive()) { - throw new InterruptedIOException( - "Unix domain socket read() call timed out"); - } else { - count = thread.getData(); - } - } else { - count = nativeRead(nativeSocketFileHandle, b, 0, 1); - if (count == -1) - throw new IOException(); - } + int count = nativeRead(nativeSocketFileHandle, b, 0, 1); + if (count == -1) + throw new IOException(); return count > 0 ? (int) b[0] & 0xff : -1; } @@ -321,33 +315,9 @@ public int read(byte[] b, int off, int len) throws IOException { return 0; } - int count; - // If a timeout is set, then use a read thread - if (timeout > 0) { - // Create a thread to read the byte - UnixDomainSocketReadThread thread = new UnixDomainSocketReadThread( - b, off, len); - thread.setDaemon(true); - thread.start(); - try { - // Wait up until the specified timeout for the thread to - // complete - thread.join(timeout); - } catch (InterruptedException e) { - } - // If the thread is still alive the read() call has - // blocked longer than the specified timeout - if (thread.isAlive()) { - throw new InterruptedIOException( - "Unix domain socket read() call timed out"); - } else { - count = thread.getData(); - } - } else { - count = nativeRead(nativeSocketFileHandle, b, off, len); - if (count == -1) - throw new IOException(); - } + int count = nativeRead(nativeSocketFileHandle, b, off, len); + if (count == -1) + throw new IOException(); return count; } @@ -385,24 +355,4 @@ public void close() throws IOException { nativeCloseOutput(nativeSocketFileHandle); } } - - protected class UnixDomainSocketReadThread extends Thread { - private int count, off, len; - - private byte[] b; - - public UnixDomainSocketReadThread(byte[] b, int off, int len) { - this.b = b; - this.off = off; - this.len = len; - } - - public void run() { - count = nativeRead(nativeSocketFileHandle, b, off, len); - } - - public int getData() { - return count; - } - } } diff --git a/configure.ac b/configure.ac index 991f58f..22f83a5 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT(JUDS, 0.94, klaus.trainer@web.de) +AC_INIT(JUDS, 0.95, klaus.trainer@web.de) AC_CONFIG_SRCDIR([com/etsy/net/UnixDomainSocket.c]) AC_CONFIG_HEADER([config.h])