pax_global_header00006660000000000000000000000064125217414170014516gustar00rootroot0000000000000052 comment=2efc6ad6ae764fc715cc19330e150e56c34f9409 jnr-unixsocket-0.8/000077500000000000000000000000001252174141700143505ustar00rootroot00000000000000jnr-unixsocket-0.8/.gitignore000066400000000000000000000000731252174141700163400ustar00rootroot00000000000000\.orig$ \.orig\..*$ \.chg\..*$ \.rej$ \.conflict\~$ target jnr-unixsocket-0.8/.travis.yml000066400000000000000000000004051252174141700164600ustar00rootroot00000000000000language: java jdk: - oraclejdk7 - openjdk6 notifications: irc: channels: - "irc.freenode.org#jnr" on_success: change on_failure: always template: - "%{repository} (%{branch}:%{commit} by %{author}): %{message} (%{build_url})" jnr-unixsocket-0.8/LICENSE000066400000000000000000000010361252174141700153550ustar00rootroot00000000000000 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.jnr-unixsocket-0.8/README.md000066400000000000000000000003041252174141700156240ustar00rootroot00000000000000jnr-unixsocket ============== Native I/O access for java. Check out the [examples](https://github.com/jnr/jnr-unixsocket/tree/master/src/test/java/jnr/unixsocket/example) for more information. jnr-unixsocket-0.8/pom.xml000066400000000000000000000051621252174141700156710ustar00rootroot00000000000000 4.0.0 org.sonatype.oss oss-parent 7 com.github.jnr jnr-unixsocket jar 0.8 jnr-unixsocket Native I/O access for java http://github.com/jnr/jnr-unixsocket The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo scm:git:git@github.com:jnr/jnr-unixsocket.git scm:git:git@github.com:jnr/jnr-unixsocket.git git@github.com:jnr/jnr-unixsocket.git wmeissner Wayne Meissner wmeissner@gmail.com junit junit 4.8.2 test com.github.jnr jnr-ffi 2.0.3 compile com.github.jnr jnr-constants 0.8.7 compile com.github.jnr jnr-enxio 0.9 compile com.github.jnr jnr-posix 3.0.12 compile org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.5 1.5 org.apache.maven.wagon wagon-webdav jnr-unixsocket-0.8/src/000077500000000000000000000000001252174141700151375ustar00rootroot00000000000000jnr-unixsocket-0.8/src/main/000077500000000000000000000000001252174141700160635ustar00rootroot00000000000000jnr-unixsocket-0.8/src/main/java/000077500000000000000000000000001252174141700170045ustar00rootroot00000000000000jnr-unixsocket-0.8/src/main/java/jnr/000077500000000000000000000000001252174141700175755ustar00rootroot00000000000000jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/000077500000000000000000000000001252174141700217715ustar00rootroot00000000000000jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/Credentials.java000066400000000000000000000030671252174141700250770ustar00rootroot00000000000000/* * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.constants.platform.SocketLevel; import jnr.constants.platform.SocketOption; public final class Credentials { private final Ucred ucred; Credentials(Ucred ucred) { this.ucred = ucred; } public int getPid() { return ucred.getPidField().intValue(); } public int getUid() { return ucred.getUidField().intValue(); } public int getGid() { return ucred.getGidField().intValue(); } @Override public java.lang.String toString() { return java.lang.String.format("[uid=%d gid=%d pid=%d]", getUid(), getGid(), getPid()); } static final Credentials getCredentials(int fd) { Ucred c = new Ucred(); int error = Native.getsockopt(fd, SocketLevel.SOL_SOCKET, SocketOption.SO_PEERCRED, c); if (error != 0) { throw new UnsupportedOperationException(Native.getLastErrorString()); } return new Credentials(c); } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/Native.java000066400000000000000000000156451252174141700240750ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import jnr.constants.platform.ProtocolFamily; import jnr.constants.platform.Sock; import jnr.constants.platform.SocketLevel; import jnr.constants.platform.SocketOption; import jnr.ffi.LastError; import jnr.ffi.Library; import jnr.ffi.LibraryLoader; import jnr.ffi.Platform; import jnr.ffi.Pointer; import jnr.ffi.Runtime; import jnr.ffi.Struct; import jnr.ffi.annotations.In; import jnr.ffi.annotations.Out; import jnr.ffi.annotations.Transient; import jnr.ffi.byref.IntByReference; import jnr.posix.DefaultNativeTimeval; import jnr.posix.Timeval; class Native { static final String[] libnames = Platform.getNativePlatform().getOS() == Platform.OS.SOLARIS ? new String[] { "socket", "nsl", "c" } : new String[] { "c" }; public static interface LibC { public static final int F_GETFL = jnr.constants.platform.Fcntl.F_GETFL.intValue(); public static final int F_SETFL = jnr.constants.platform.Fcntl.F_SETFL.intValue(); public static final int O_NONBLOCK = jnr.constants.platform.OpenFlags.O_NONBLOCK.intValue(); int socket(int domain, int type, int protocol); int listen(int fd, int backlog); int bind(int fd, @In @Out @Transient SockAddrUnix addr, int len); int accept(int fd, @Out SockAddrUnix addr, @In @Out IntByReference len); int connect(int s, @In @Transient SockAddrUnix name, int namelen); int getsockname(int fd, @Out SockAddrUnix addr, @In @Out IntByReference len); int getpeername(int fd, @Out SockAddrUnix addr, @In @Out IntByReference len); int socketpair(int domain, int type, int protocol, @Out int[] sv); int fcntl(int fd, int cmd, int data); int getsockopt(int s, int level, int optname, @Out ByteBuffer optval, @In @Out IntByReference optlen); int getsockopt(int s, int level, int optname, @Out Timeval optval, @In @Out IntByReference optlen); int setsockopt(int s, int level, int optname, @In ByteBuffer optval, int optlen); int setsockopt(int s, int level, int optname, @In Timeval optval, int optlen); String strerror(int error); } static final LibC INSTANCE; static { LibraryLoader loader = LibraryLoader.create(LibC.class); for (String libraryName : libnames) { loader.library(libraryName); } INSTANCE = loader.load(); } static final LibC libsocket() { return INSTANCE; } static final LibC libc() { return INSTANCE; } static int socket(ProtocolFamily domain, Sock type, int protocol) throws IOException { int fd = libsocket().socket(domain.intValue(), type.intValue(), protocol); if (fd < 0) { throw new IOException(getLastErrorString()); } return fd; } static int socketpair(ProtocolFamily domain, Sock type, int protocol, int[] sv) throws IOException { if (libsocket().socketpair(domain.intValue(), type.intValue(), protocol, sv) < 0) { throw new IOException("socketpair(2) failed " + Native.getLastErrorString()); } return 0; } static int listen(int fd, int backlog) { return libsocket().listen(fd, backlog); } static int bind(int fd, SockAddrUnix addr, int len) { return libsocket().bind(fd, addr, len); } static int accept(int fd, SockAddrUnix addr, IntByReference len) { return libsocket().accept(fd, addr, len); } static int connect(int fd, SockAddrUnix addr, int len) { return libsocket().connect(fd, addr, len); } static String getLastErrorString() { return strerror(LastError.getLastError(jnr.ffi.Runtime.getSystemRuntime())); } static String strerror(int error) { return libc().strerror(error); } public static void setBlocking(int fd, boolean block) { int flags = libc().fcntl(fd, LibC.F_GETFL, 0); if (block) { flags &= ~LibC.O_NONBLOCK; } else { flags |= LibC.O_NONBLOCK; } libc().fcntl(fd, LibC.F_SETFL, flags); } public static int setsockopt(int s, SocketLevel level, SocketOption optname, boolean optval) { return setsockopt(s, level, optname, optval ? 1 : 0); } public static int setsockopt(int s, SocketLevel level, SocketOption optname, int optval) { if (optname == SocketOption.SO_RCVTIMEO) { DefaultNativeTimeval t = new DefaultNativeTimeval(Runtime.getSystemRuntime()); t.setTime(new long [] {optval / 1000, (optval % 1000) * 1000}); return libsocket().setsockopt(s, level.intValue(), optname.intValue(), t, DefaultNativeTimeval.size(t)); } else { ByteBuffer buf = ByteBuffer.allocate(4); buf.order(ByteOrder.BIG_ENDIAN); buf.putInt(optval).flip(); return libsocket().setsockopt(s, level.intValue(), optname.intValue(), buf, buf.remaining()); } } public static int getsockopt (int s, SocketLevel level, int optname) { IntByReference ref; if (optname == SocketOption.SO_RCVTIMEO.intValue()) { DefaultNativeTimeval t = new DefaultNativeTimeval(Runtime.getSystemRuntime()); ref = new IntByReference(DefaultNativeTimeval.size(t)); Native.libsocket().getsockopt(s, level.intValue(), optname, t, ref); return (t.tv_sec.intValue() * 1000) + (t.tv_usec.intValue() / 1000); } else { ByteBuffer buf = ByteBuffer.allocate(4); buf.order(ByteOrder.BIG_ENDIAN); ref = new IntByReference(4); Native.libsocket().getsockopt(s, level.intValue(), optname, buf, ref); return buf.getInt(); } } public static int getsockopt(int s, SocketLevel level, SocketOption optname, Struct data) { Pointer struct_ptr = Struct.getMemory(data); IntByReference ref = new IntByReference(Struct.size(data)); ByteBuffer buf = ByteBuffer.wrap((byte[])struct_ptr.array()); return Native.libsocket().getsockopt(s, level.intValue(), optname.intValue(), buf, ref); } public static boolean getboolsockopt (int s, SocketLevel level, int optname) { return getsockopt(s, level, optname) != 0; } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/SockAddrUnix.java000066400000000000000000000075151252174141700252020ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.constants.platform.ProtocolFamily; import jnr.ffi.*; /** * Native unix domain socket address structure. */ abstract class SockAddrUnix extends Struct { public final static int ADDR_LENGTH = 108; protected abstract UTF8String getPathField(); protected abstract NumberField getFamilyField(); SockAddrUnix() { super(jnr.ffi.Runtime.getSystemRuntime()); } /** * Sets the protocol family of this unix socket address. * * @param family The protocol family, usually {@link ProtocolFamily#PF_UNIX} */ final void setFamily(ProtocolFamily family) { getFamilyField().set(family.intValue()); } /** * Gets the protocol family of this unix socket address. * * @return The protocol family */ final ProtocolFamily getFamily() { return ProtocolFamily.valueOf(getFamilyField().intValue()); } /** * Sets the file system path of this socket address * * @param path The unix socket address */ final void setPath(java.lang.String path) { getPathField().set(path); } /** * Gets the file system path of this socket address * * @return A String */ final java.lang.String getPath() { return getPathField().get(); } /** * Gets the maximum length of this address (including len/family header) * * @return The maximum size of the address in bytes */ int getMaximumLength() { return 2 + getPathField().length(); } /** * Gets the actual length of this address (including len/family header) * * @return The actual size of this address, in bytes */ int length() { return 2 + strlen(getPathField()); } /** * Creates a new instance of SockAddrUnix * * @return An instance of SockAddrUnix */ static SockAddrUnix create() { return Platform.getNativePlatform().isBSD() ? new BSDSockAddrUnix() : new DefaultSockAddrUnix(); } private static final int strlen(UTF8String str) { int end = str.getMemory().indexOf(str.offset(), (byte) 0); return end >= 0 ? end : str.length(); } /** * An implementation of {@link SockAddrUnix} for BSD systems */ static final class BSDSockAddrUnix extends SockAddrUnix { public final Unsigned8 sun_len = new Unsigned8(); public final Unsigned8 sun_family = new Unsigned8(); public final UTF8String sun_addr = new UTF8String(ADDR_LENGTH); protected final UTF8String getPathField() { return sun_addr; } protected final NumberField getFamilyField() { return sun_family; } } /** * An implementation of {@link SockAddrUnix} for Linux, Solaris, et, al */ static final class DefaultSockAddrUnix extends SockAddrUnix { public final Unsigned16 sun_family = new Unsigned16(); public final UTF8String sun_addr = new UTF8String(ADDR_LENGTH); protected final UTF8String getPathField() { return sun_addr; } protected final NumberField getFamilyField() { return sun_family; } } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/Ucred.java000066400000000000000000000021401252174141700236730ustar00rootroot00000000000000/* * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.ffi.Struct; /** * Native structure for SCM_CREDENTIALS. See 'man 7 unix'. */ final class Ucred extends Struct { final pid_t pid = new pid_t(); final uid_t uid = new uid_t(); final gid_t gid = new gid_t(); public Ucred() { super(jnr.ffi.Runtime.getSystemRuntime()); } final pid_t getPidField() { return pid; } final uid_t getUidField() { return uid; } final gid_t getGidField() { return gid; } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/UnixServerSocket.java000066400000000000000000000035651252174141700261300ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import java.io.IOException; import java.net.SocketAddress; public class UnixServerSocket { final UnixServerSocketChannel channel; final int fd; public UnixServerSocket() throws IOException { this.channel = new UnixServerSocketChannel(this); this.fd = channel.getFD(); } UnixServerSocket(UnixServerSocketChannel channel) { this.channel = channel; this.fd = channel.getFD(); } public UnixSocket accept() throws IOException { return new UnixSocket(channel.accept()); } public void bind(SocketAddress endpoint) throws java.io.IOException { bind(endpoint, 128); } public void bind(SocketAddress endpoint, int backlog) throws java.io.IOException { if (!(endpoint instanceof UnixSocketAddress)) { throw new IOException("Invalid address"); } UnixSocketAddress addr = (UnixSocketAddress) endpoint; if (Native.bind(fd, addr.getStruct(), addr.length()) < 0) { throw new IOException("bind failed: " + Native.getLastErrorString()); } if (Native.listen(fd, backlog) < 0) { throw new IOException("listen failed: " + Native.getLastErrorString()); } } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/UnixServerSocketChannel.java000066400000000000000000000043511252174141700274130ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.constants.platform.ProtocolFamily; import jnr.constants.platform.Sock; import jnr.enxio.channels.NativeServerSocketChannel; import jnr.ffi.byref.IntByReference; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.spi.SelectorProvider; /** * */ public class UnixServerSocketChannel extends NativeServerSocketChannel { private final UnixServerSocket socket; UnixServerSocketChannel(UnixServerSocket socket) throws IOException { super(Native.socket(ProtocolFamily.PF_UNIX, Sock.SOCK_STREAM, 0)); this.socket = new UnixServerSocket(this); } UnixServerSocketChannel(SelectorProvider provider, int fd) { super(provider, fd, SelectionKey.OP_ACCEPT | SelectionKey.OP_READ); this.socket = new UnixServerSocket(this); } public static UnixServerSocketChannel open() throws IOException { return new UnixServerSocket().channel; } public UnixSocketChannel accept() throws IOException { UnixSocketAddress remote = new UnixSocketAddress(); SockAddrUnix addr = remote.getStruct(); IntByReference len = new IntByReference(addr.getMaximumLength()); int clientfd = Native.accept(getFD(), addr, len); if (clientfd < 0) { throw new IOException("accept failed: " + Native.getLastErrorString()); } // Always force the socket back to blocking mode Native.setBlocking(clientfd, true); return new UnixSocketChannel(clientfd, remote); } public final UnixServerSocket socket() { return socket; } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/UnixSocket.java000066400000000000000000000043531252174141700247350ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.constants.platform.SocketLevel; import jnr.constants.platform.SocketOption; import jnr.enxio.channels.NativeSocketChannel; import jnr.ffi.byref.IntByReference; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.Channel; public class UnixSocket { private final NativeSocketChannel channel; UnixSocket(NativeSocketChannel channel) { this.channel = channel; } public final Channel getChannel() { return channel; } public final void setKeepAlive(boolean on) { Native.setsockopt(channel.getFD(), SocketLevel.SOL_SOCKET, SocketOption.SO_KEEPALIVE, on); } public final boolean getKeepAlive() { ByteBuffer buf = ByteBuffer.allocate(4); buf.order(ByteOrder.BIG_ENDIAN); IntByReference ref = new IntByReference(4); Native.libsocket().getsockopt(channel.getFD(), SocketLevel.SOL_SOCKET.intValue(), SocketOption.SO_KEEPALIVE.intValue(), buf, ref); return buf.getInt(0) != 0; } /** * Retrieves the credentials for this UNIX socket. Clients calling this * method will receive the server's credentials, and servers will receive * the client's credentials. User ID, group ID, and PID are supplied. * * @see man unix 7; SCM_CREDENTIALS * * @throws UnsupportedOperationException if the underlying socket library * doesn't support the SO_PEERCRED option * * @return the credentials of the remote */ public final Credentials getCredentials() { return Credentials.getCredentials(channel.getFD()); } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/UnixSocketAddress.java000066400000000000000000000026061252174141700262420ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.constants.platform.ProtocolFamily; public class UnixSocketAddress extends java.net.SocketAddress { private final SockAddrUnix address; UnixSocketAddress() { address = SockAddrUnix.create(); address.setFamily(ProtocolFamily.PF_UNIX); } public UnixSocketAddress(java.io.File path) { address = SockAddrUnix.create(); address.setFamily(ProtocolFamily.PF_UNIX); address.setPath(path.getAbsolutePath()); } SockAddrUnix getStruct() { return address; } int length() { return address.length(); } @Override public String toString() { return "[family=" + address.getFamily() + " path=" + address.getPath() + "]"; } } jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/UnixSocketChannel.java000066400000000000000000000152061252174141700262250ustar00rootroot00000000000000/* * Copyright (C) 2009 Wayne Meissner * * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import jnr.constants.platform.Errno; import jnr.constants.platform.ProtocolFamily; import jnr.constants.platform.Sock; import jnr.constants.platform.SocketLevel; import jnr.constants.platform.SocketOption; import jnr.enxio.channels.NativeSocketChannel; import jnr.ffi.*; import jnr.ffi.byref.IntByReference; import java.io.IOException; import java.nio.channels.SelectionKey; /** * A {@link java.nio.channels.Channel} implementation that uses a native unix socket */ public class UnixSocketChannel extends NativeSocketChannel { static enum State { UNINITIALIZED, CONNECTED, IDLE, CONNECTING, } private volatile State state; private UnixSocketAddress remoteAddress = null; private UnixSocketAddress localAddress = null; private final Object stateLock = new Object(); public static final UnixSocketChannel open() throws IOException { return new UnixSocketChannel(); } public static final UnixSocketChannel open(UnixSocketAddress remote) throws IOException { UnixSocketChannel channel = new UnixSocketChannel(); channel.connect(remote); return channel; } public static final UnixSocketChannel[] pair() throws IOException { int[] sockets = { -1, -1 }; Native.socketpair(ProtocolFamily.PF_UNIX, Sock.SOCK_STREAM, 0, sockets); return new UnixSocketChannel[] { new UnixSocketChannel(sockets[0], SelectionKey.OP_READ | SelectionKey.OP_WRITE), new UnixSocketChannel(sockets[1], SelectionKey.OP_READ | SelectionKey.OP_WRITE) }; } private UnixSocketChannel() throws IOException { super(Native.socket(ProtocolFamily.PF_UNIX, Sock.SOCK_STREAM, 0), SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE); state = State.IDLE; } UnixSocketChannel(int fd, int ops) { super(fd, ops); state = State.CONNECTED; } UnixSocketChannel(int fd, UnixSocketAddress remote) { super(fd, SelectionKey.OP_READ | SelectionKey.OP_WRITE); state = State.CONNECTED; remoteAddress = remote; } private final boolean doConnect(SockAddrUnix remote) throws IOException { if (Native.connect(getFD(), remote, remote.length()) != 0) { Errno error = Errno.valueOf(LastError.getLastError(jnr.ffi.Runtime.getSystemRuntime())); switch (error) { case EAGAIN: case EWOULDBLOCK: return false; default: throw new IOException(error.toString()); } } return true; } public boolean connect(UnixSocketAddress remote) throws IOException { remoteAddress = remote; if (!doConnect(remoteAddress.getStruct())) { state = State.CONNECTING; return false; } else { state = State.CONNECTED; return true; } } public boolean isConnected() { return state == State.CONNECTED; } public boolean isConnectionPending() { return state == State.CONNECTING; } public boolean finishConnect() throws IOException { switch (state) { case CONNECTED: return true; case CONNECTING: if (!doConnect(remoteAddress.getStruct())) { return false; } state = State.CONNECTED; return true; default: throw new IllegalStateException("socket is not waiting for connect to complete"); } } public final UnixSocketAddress getRemoteSocketAddress() { if (state != State.CONNECTED) { return null; } return remoteAddress != null ? remoteAddress : (remoteAddress = getpeername(getFD())); } public final UnixSocketAddress getLocalSocketAddress() { if (state != State.CONNECTED) { return null; } return localAddress != null ? localAddress : (localAddress = getsockname(getFD())); } /** * Retrieves the credentials for this UNIX socket. If this socket channel * is not in a connected state, this method will return null. * * @see man unix 7; SCM_CREDENTIALS * * @throws UnsupportedOperationException if the underlying socket library * doesn't support the SO_PEERCRED option * * @return the credentials of the remote; null if not connected */ public final Credentials getCredentials() { if (state != State.CONNECTED) { return null; } return Credentials.getCredentials(getFD()); } static UnixSocketAddress getpeername(int sockfd) { UnixSocketAddress remote = new UnixSocketAddress(); IntByReference len = new IntByReference(remote.getStruct().getMaximumLength()); if (Native.libc().getpeername(sockfd, remote.getStruct(), len) < 0) { throw new Error(Native.getLastErrorString()); } return remote; } static UnixSocketAddress getsockname(int sockfd) { UnixSocketAddress remote = new UnixSocketAddress(); IntByReference len = new IntByReference(remote.getStruct().getMaximumLength()); if (Native.libc().getsockname(sockfd, remote.getStruct(), len) < 0) { throw new Error(Native.getLastErrorString()); } return remote; } public boolean getKeepAlive() { int ret = Native.getsockopt(getFD(), SocketLevel.SOL_SOCKET, SocketOption.SO_KEEPALIVE.intValue()); return (ret == 1) ? true : false; } public void setKeepAlive(boolean on) { Native.setsockopt(getFD(), SocketLevel.SOL_SOCKET, SocketOption.SO_KEEPALIVE, on); } public int getSoTimeout() { return Native.getsockopt(getFD(), SocketLevel.SOL_SOCKET, SocketOption.SO_RCVTIMEO.intValue()); } public void setSoTimeout(int timeout) { Native.setsockopt(getFD(), SocketLevel.SOL_SOCKET, SocketOption.SO_RCVTIMEO, timeout); } } jnr-unixsocket-0.8/src/test/000077500000000000000000000000001252174141700161165ustar00rootroot00000000000000jnr-unixsocket-0.8/src/test/java/000077500000000000000000000000001252174141700170375ustar00rootroot00000000000000jnr-unixsocket-0.8/src/test/java/jnr/000077500000000000000000000000001252174141700176305ustar00rootroot00000000000000jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/000077500000000000000000000000001252174141700220245ustar00rootroot00000000000000jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/CredentialsFunctionalTest.java000066400000000000000000000101421252174141700300050ustar00rootroot00000000000000/* * This file is part of the JNR project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jnr.unixsocket; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.lang.management.ManagementFactory; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import jnr.ffi.Platform; import jnr.ffi.Platform.OS; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; public class CredentialsFunctionalTest { @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); private File serverSocket; private ExecutorService async = Executors.newSingleThreadExecutor(); @Before public void createSockets() throws IOException { Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS()); serverSocket = tempFolder.newFile("serverSocket"); serverSocket.delete(); //JUnit is "helpful" and creates it for us } @Test(timeout=30000) public void credentials() throws IOException, ExecutionException, InterruptedException { UnixSocketAddress address = new UnixSocketAddress(serverSocket); final UnixServerSocket socket = new UnixServerSocket(); socket.bind(address); Future socketFuture = async.submit(new Callable() { public UnixSocket call() throws Exception { return socket.accept(); } }); UnixSocketChannel client = UnixSocketChannel.open(address); UnixSocket server = socketFuture.get(); assertNotNull("Client socket must be non-null.", client); assertNotNull("Server socket must be non-null.", server); Credentials clientCreds = client.getCredentials(); Credentials serverCreds = server.getCredentials(); int myPid = getCurrentPid(); assertEquals("Current PID should match client credentials", myPid, clientCreds.getPid()); assertEquals("Current PID should match server credentials", myPid, serverCreds.getPid()); assertEquals("Client/server running in same process, UID should be the same", clientCreds.getUid(), serverCreds.getUid()); //don't have an easy way of getting effective GID, but they should be the same assertEquals("Client/server running in same process, GID should be the same", clientCreds.getGid(), serverCreds.getGid()); } public int getCurrentPid() { String[] nameParts = ManagementFactory.getRuntimeMXBean().getName().split("@", 2); assertEquals("Cannot determine PID", 2, nameParts.length); return Integer.valueOf(nameParts[0]); } /* * A Linux-only utility method. */ public int getLoginUid() throws IOException { FileReader fr = null; StringBuilder uidText = new StringBuilder(); try { fr = new FileReader("/proc/self/loginuid"); char[] buf = new char[16]; int read = -1; while ((read = fr.read(buf)) > -1) { uidText.append(buf, 0, read); } } catch (IOException ioe) { fail("Unable to determine login uid: " + ioe.getMessage()); } finally { fr.close(); } return Integer.valueOf(uidText.toString()); } } jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/example/000077500000000000000000000000001252174141700234575ustar00rootroot00000000000000jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/example/UnixClient.java000066400000000000000000000023211252174141700264020ustar00rootroot00000000000000 package jnr.unixsocket.example; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.nio.CharBuffer; import java.nio.channels.Channels; import jnr.unixsocket.UnixSocketAddress; import jnr.unixsocket.UnixSocketChannel; public class UnixClient { public static void main(String[] args) throws IOException { java.io.File path = new java.io.File("/tmp/fubar.sock"); String data = "blah blah"; UnixSocketAddress address = new UnixSocketAddress(path); UnixSocketChannel channel = UnixSocketChannel.open(address); System.out.println("connected to " + channel.getRemoteSocketAddress()); PrintWriter w = new PrintWriter(Channels.newOutputStream(channel)); w.print(data); w.flush(); InputStreamReader r = new InputStreamReader(Channels.newInputStream(channel)); CharBuffer result = CharBuffer.allocate(1024); r.read(result); result.flip(); System.out.println("read from server: " + result.toString()); if (!result.toString().equals(data)) { System.out.println("ERROR: data mismatch"); } else { System.out.println("SUCCESS"); } } } jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/example/UnixServer.java000066400000000000000000000062551252174141700264440ustar00rootroot00000000000000 package jnr.unixsocket.example; import jnr.enxio.channels.NativeSelectorProvider; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import jnr.unixsocket.UnixServerSocket; import jnr.unixsocket.UnixServerSocketChannel; import jnr.unixsocket.UnixSocketAddress; import jnr.unixsocket.UnixSocketChannel; public class UnixServer { public static void main(String[] args) throws IOException { java.io.File path = new java.io.File("/tmp/fubar.sock"); path.deleteOnExit(); UnixSocketAddress address = new UnixSocketAddress(path); UnixServerSocketChannel channel = UnixServerSocketChannel.open(); try { Selector sel = NativeSelectorProvider.getInstance().openSelector(); channel.configureBlocking(false); channel.socket().bind(address); channel.register(sel, SelectionKey.OP_ACCEPT, new ServerActor(channel, sel)); while (sel.select() > 0) { Set keys = sel.selectedKeys(); for (SelectionKey k : keys) { Actor a = (Actor) k.attachment(); if (!a.rxready()) { k.cancel(); } } } } catch (IOException ex) { Logger.getLogger(UnixServerSocket.class.getName()).log(Level.SEVERE, null, ex); } } static interface Actor { public boolean rxready(); } static final class ServerActor implements Actor { private final UnixServerSocketChannel channel; private final Selector selector; public ServerActor(UnixServerSocketChannel channel, Selector selector) { this.channel = channel; this.selector = selector; } public final boolean rxready() { try { UnixSocketChannel client = channel.accept(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ, new ClientActor(client)); return true; } catch (IOException ex) { return false; } } } static final class ClientActor implements Actor { private final UnixSocketChannel channel; public ClientActor(UnixSocketChannel channel) { this.channel = channel; } public final boolean rxready() { try { ByteBuffer buf = ByteBuffer.allocate(1024); int n = channel.read(buf); UnixSocketAddress remote = channel.getRemoteSocketAddress(); System.out.printf("Read in %d bytes from %s\n", n, remote); if (n > 0) { buf.flip(); channel.write(buf); return true; } else if (n < 0) { return false; } } catch (IOException ex) { ex.printStackTrace(); return false; } return true; } } }