diff --git a/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c b/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c index e522896ec8..5ffa19e956 100644 --- a/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c +++ b/transport-native-kqueue/src/main/c/netty_kqueue_bsdsocket.c @@ -159,8 +159,16 @@ static jobject netty_kqueue_bsdsocket_getPeerCredentials(JNIEnv *env, jclass cla (*env)->SetIntArrayRegion(env, gids, 0, 1, (jint*) &credentials.cr_gid); } - // TODO: getting the PID may require reading/sending "ancillary data" via SCM_CREDENTIALS which is not desirable. - return (*env)->NewObject(env, peerCredentialsClass, peerCredentialsMethodId, 0, credentials.cr_uid, gids); + pid_t pid = 0; +#ifdef LOCAL_PEERPID + socklen_t len = sizeof(pid); + // Getting the LOCAL_PEERPID is expected to return error in some cases (e.g. server socket FDs) - just return 0. + if (netty_unix_socket_getOption0(fd, SOCK_STREAM, LOCAL_PEERPID, &pid, len) < 0) { + pid = 0; + } +#endif + + return (*env)->NewObject(env, peerCredentialsClass, peerCredentialsMethodId, pid, credentials.cr_uid, gids); } // JNI Registered Methods End diff --git a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java index 38f09c00fd..201fa9edbc 100644 --- a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java +++ b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java @@ -24,8 +24,7 @@ import org.junit.Test; import java.io.IOException; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.junit.Assume.assumeTrue; public class KQueueSocketTest extends SocketTest { @@ -55,6 +54,33 @@ public class KQueueSocketTest extends SocketTest { } } + @Test + public void testPeerPID() throws IOException { + BsdSocket s1 = BsdSocket.newSocketDomain(); + BsdSocket s2 = BsdSocket.newSocketDomain(); + + try { + DomainSocketAddress dsa = UnixTestUtils.newSocketAddress(); + s1.bind(dsa); + s1.listen(1); + + // PID of client socket is expected to be 0 before connection + assertEquals(0, s2.getPeerCredentials().pid()); + assertTrue(s2.connect(dsa)); + byte [] addr = new byte[64]; + int clientFd = s1.accept(addr); + assertNotEquals(-1, clientFd); + PeerCredentials pc = new BsdSocket(clientFd).getPeerCredentials(); + assertNotEquals(0, pc.pid()); + assertNotEquals(0, s2.getPeerCredentials().pid()); + // Server socket FDs should not have pid field set: + assertEquals(0, s1.getPeerCredentials().pid()); + } finally { + s1.close(); + s2.close(); + } + } + @Override protected BsdSocket newSocket() { return BsdSocket.newSocketStream();