Skip to content

Commit

Permalink
Properly handle SO_LINGER set/get sockopt
Browse files Browse the repository at this point in the history
Fixes #4040
  • Loading branch information
etehtsea committed Sep 7, 2016
1 parent 2803ef0 commit 8cc3ddb
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 17 deletions.
28 changes: 18 additions & 10 deletions core/src/main/java/org/jruby/ext/socket/RubyBasicSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,20 @@ public IRubyObject getsockopt(ThreadContext context, IRubyObject _level, IRubyOb
}

int value = SocketType.forChannel(channel).getSocketOption(channel, opt);
ByteList packedValue = Option.packInt(value);
ByteList packedValue;

if (opt == SocketOption.SO_LINGER) {
if (value == -1) {
// Hardcode to 0, because Java Socket API drops actual value
// if lingering is disabled
packedValue = Option.packLinger(0, 0);
} else {
packedValue = Option.packLinger(1, value);
}
} else {
packedValue = Option.packInt(value);
}

return new Option(runtime, ProtocolFamily.PF_INET, level, opt, packedValue);

default:
Expand Down Expand Up @@ -307,17 +320,12 @@ public IRubyObject setsockopt(ThreadContext context, IRubyObject _level, IRubyOb
case SOL_UDP:

if (opt == SocketOption.SO_LINGER) {
if(val instanceof RubyBoolean && !val.isTrue()) {
socketType.setSoLinger(channel, false, 0);
if (val instanceof RubyString) {
int[] linger = Option.unpackLinger(val.convertToString().getByteList());
socketType.setSoLinger(channel, linger[0] != 0, linger[1]);
} else {
int num = asNumber(val);
if(num == -1) {
socketType.setSoLinger(channel, false, 0);
} else {
socketType.setSoLinger(channel, true, num);
}
throw runtime.newErrnoEINVALError("setsockopt(2)");
}

} else {
socketType.setSocketOption(channel, opt, asNumber(val));
}
Expand Down
13 changes: 6 additions & 7 deletions core/src/main/java/org/jruby/ext/socket/SocketType.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public SocketAddress getLocalSocketAddress(Channel channel) {
private DatagramSocket toSocket(Channel channel) {
return ((DatagramChannel)channel).socket();
}

public int getSoTimeout(Channel channel) throws IOException {
return toSocket(channel).getSoTimeout();
}
Expand Down Expand Up @@ -241,14 +241,14 @@ public void shutdownOutput(Channel channel) throws IOException {
},

UNKNOWN(Sock.SOCK_STREAM);

public static SocketType forChannel(Channel channel) {
if (channel instanceof SocketChannel) {
return SOCKET;

} else if (channel instanceof ServerSocketChannel) {
return SERVER;

} else if (channel instanceof DatagramChannel) {
return DATAGRAM;

Expand Down Expand Up @@ -301,7 +301,7 @@ public SocketAddress getLocalSocketAddress(Channel channel) {
public Sock getSocketType() {
return sock;
}

public int getSocketOption(Channel channel, SocketOption option) throws IOException {
switch (option) {

Expand All @@ -312,8 +312,7 @@ public int getSocketOption(Channel channel, SocketOption option) throws IOExcept
return getKeepAlive(channel) ? 1 : 0;

case SO_LINGER: {
int linger = getSoLinger(channel);
return linger < 0 ? 0 : linger;
return getSoLinger(channel);
}

case SO_OOBINLINE:
Expand Down

0 comments on commit 8cc3ddb

Please sign in to comment.