Skip to content

Commit

Permalink
Fix unnamed sockets support
Browse files Browse the repository at this point in the history
getsockname/getpeername/accept shouldn't inspect path for unnamed
sockets. See https://linux.die.net/man/7/unix
Fixes jruby/jruby#4247
  • Loading branch information
etehtsea committed Oct 26, 2016
1 parent 21d10a0 commit 12447d3
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 15 deletions.
16 changes: 13 additions & 3 deletions src/main/java/jnr/unixsocket/SockAddrUnix.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
*/
abstract class SockAddrUnix extends Struct {
public final static int ADDR_LENGTH = 108;

public final static int HEADER_LENGTH = 2;

protected abstract UTF8String getPathField();
protected abstract NumberField getFamilyField();

Expand Down Expand Up @@ -77,7 +78,7 @@ final java.lang.String getPath() {
* @return The maximum size of the address in bytes
*/
int getMaximumLength() {
return 2 + getPathField().length();
return HEADER_LENGTH + getPathField().length();
}

/**
Expand All @@ -86,7 +87,16 @@ int getMaximumLength() {
* @return The actual size of this address, in bytes
*/
int length() {
return 2 + strlen(getPathField());
return HEADER_LENGTH + strlen(getPathField());
}

/**
* Gets len/family header length
*
* @return The size of header, in bytes
*/
int getHeaderLength() {
return HEADER_LENGTH;
}


Expand Down
3 changes: 3 additions & 0 deletions src/main/java/jnr/unixsocket/UnixServerSocketChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ public UnixSocketChannel accept() throws IOException {
return null;
}

// Handle unnamed sockets
if (len.getValue() == addr.getHeaderLength()) addr.setPath("");

// Always force the socket back to blocking mode
Native.setBlocking(clientfd, true);

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/jnr/unixsocket/UnixSocketAddress.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public String path() {

@Override
public String toString() {
return "[family=" + address.getFamily() + " path=" + address.getPath() + "]";
return "[family=" + address.getFamily() + " path=" + path() + "]";
}

@Override
Expand All @@ -58,6 +58,6 @@ public boolean equals(Object _other) {
UnixSocketAddress other = (UnixSocketAddress)_other;

return address.getFamily() == other.address.getFamily() &&
address.getPath().equals(other.address.getPath());
path().equals(other.path());
}
}
16 changes: 12 additions & 4 deletions src/main/java/jnr/unixsocket/UnixSocketChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,23 +221,31 @@ public final Credentials getCredentials() {

static UnixSocketAddress getpeername(int sockfd) {
UnixSocketAddress remote = new UnixSocketAddress();
IntByReference len = new IntByReference(remote.getStruct().getMaximumLength());
SockAddrUnix addr = remote.getStruct();
IntByReference len = new IntByReference(addr.getMaximumLength());

if (Native.libc().getpeername(sockfd, remote.getStruct(), len) < 0) {
if (Native.libc().getpeername(sockfd, addr, len) < 0) {
throw new Error(Native.getLastErrorString());
}

// Handle unnamed sockets
if (len.getValue() == addr.getHeaderLength()) addr.setPath("");

return remote;
}

static UnixSocketAddress getsockname(int sockfd) {
UnixSocketAddress remote = new UnixSocketAddress();
IntByReference len = new IntByReference(remote.getStruct().getMaximumLength());
SockAddrUnix addr = remote.getStruct();
IntByReference len = new IntByReference(addr.getMaximumLength());

if (Native.libc().getsockname(sockfd, remote.getStruct(), len) < 0) {
if (Native.libc().getsockname(sockfd, addr, len) < 0) {
throw new Error(Native.getLastErrorString());
}

// Handle unnamed sockets
if (len.getValue() == addr.getHeaderLength()) addr.setPath("");

return remote;
}

Expand Down
10 changes: 4 additions & 6 deletions src/test/java/jnr/unixsocket/BasicFunctionalityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,8 @@ public final boolean rxready() {
// nonblocking result
return false;
}
// TODO: This doesn't work for some reason.
// assertEquals(ADDRESS, client.getLocalSocketAddress());
// assertEquals("", client.getRemoteSocketAddress().getStruct().getPath());
assertEquals(ADDRESS, client.getLocalSocketAddress());
assertEquals("", client.getRemoteSocketAddress().getStruct().getPath());

client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ, new ClientActor(client));
Expand All @@ -130,11 +129,10 @@ public final boolean rxready() {
try {
ByteBuffer buf = ByteBuffer.allocate(1024);
int n = channel.read(buf);
// TODO: This doesn't work for some reason.
// assertEquals(ADDRESS, channel.getRemoteSocketAddress());
assertEquals("", channel.getRemoteSocketAddress().getStruct().getPath());

assertEquals(DATA.length(), n);

if (n > 0) {
buf.flip();
channel.write(buf);
Expand Down
20 changes: 20 additions & 0 deletions src/test/java/jnr/unixsocket/UnixSocketChannelTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package jnr.unixsocket;

import org.junit.Test;

import static junit.framework.Assert.*;

public class UnixSocketChannelTest {
@Test
public void testForUnnamedSockets() throws Exception {
UnixSocketChannel[] sp = UnixSocketChannel.pair();

// getpeername check
assertEquals(sp[0].getRemoteSocketAddress().path(), "");
assertEquals(sp[1].getRemoteSocketAddress().path(), "");

// getsockname check
assertEquals(sp[0].getLocalSocketAddress().path(), "");
assertEquals(sp[1].getLocalSocketAddress().path(), "");
}
}

0 comments on commit 12447d3

Please sign in to comment.