Skip to content

Commit

Permalink
Issue 20: Socket timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
phejl committed Feb 3, 2016
1 parent 8f72cb3 commit 2f91940
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 88 deletions.
7 changes: 6 additions & 1 deletion README.md
Expand Up @@ -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.
Expand Down
23 changes: 12 additions & 11 deletions com/etsy/net/UnixDomainSocket.c
Expand Up @@ -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);
Expand All @@ -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 */
Expand Down Expand Up @@ -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,
Expand Down
100 changes: 25 additions & 75 deletions com/etsy/net/UnixDomainSocket.java
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
}
}
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -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])

Expand Down

0 comments on commit 2f91940

Please sign in to comment.