pax_global_header 0000666 0000000 0000000 00000000064 12521741417 0014516 g ustar 00root root 0000000 0000000 52 comment=2efc6ad6ae764fc715cc19330e150e56c34f9409
jnr-unixsocket-0.8/ 0000775 0000000 0000000 00000000000 12521741417 0014350 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/.gitignore 0000664 0000000 0000000 00000000073 12521741417 0016340 0 ustar 00root root 0000000 0000000 \.orig$
\.orig\..*$
\.chg\..*$
\.rej$
\.conflict\~$
target
jnr-unixsocket-0.8/.travis.yml 0000664 0000000 0000000 00000000405 12521741417 0016460 0 ustar 00root root 0000000 0000000 language: 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/LICENSE 0000664 0000000 0000000 00000001036 12521741417 0015355 0 ustar 00root root 0000000 0000000
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.md 0000664 0000000 0000000 00000000304 12521741417 0015624 0 ustar 00root root 0000000 0000000 jnr-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.xml 0000664 0000000 0000000 00000005162 12521741417 0015671 0 ustar 00root root 0000000 0000000 4.0.0org.sonatype.ossoss-parent7com.github.jnrjnr-unixsocketjar0.8jnr-unixsocketNative I/O access for javahttp://github.com/jnr/jnr-unixsocketThe Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txtreposcm:git:git@github.com:jnr/jnr-unixsocket.gitscm:git:git@github.com:jnr/jnr-unixsocket.gitgit@github.com:jnr/jnr-unixsocket.gitwmeissnerWayne Meissnerwmeissner@gmail.comjunitjunit4.8.2testcom.github.jnrjnr-ffi2.0.3compilecom.github.jnrjnr-constants0.8.7compilecom.github.jnrjnr-enxio0.9compilecom.github.jnrjnr-posix3.0.12compileorg.apache.maven.pluginsmaven-compiler-plugin2.0.21.51.5org.apache.maven.wagonwagon-webdav
jnr-unixsocket-0.8/src/ 0000775 0000000 0000000 00000000000 12521741417 0015137 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/main/ 0000775 0000000 0000000 00000000000 12521741417 0016063 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/main/java/ 0000775 0000000 0000000 00000000000 12521741417 0017004 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/main/java/jnr/ 0000775 0000000 0000000 00000000000 12521741417 0017575 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/ 0000775 0000000 0000000 00000000000 12521741417 0021771 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/main/java/jnr/unixsocket/Credentials.java 0000664 0000000 0000000 00000003067 12521741417 0025077 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000015645 12521741417 0024075 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000007515 12521741417 0025202 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000002140 12521741417 0023673 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000003565 12521741417 0026130 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000004351 12521741417 0027413 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000004353 12521741417 0024735 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000002606 12521741417 0026242 0 ustar 00root root 0000000 0000000 /*
* 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.java 0000664 0000000 0000000 00000015206 12521741417 0026225 0 ustar 00root root 0000000 0000000 /*
* 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/ 0000775 0000000 0000000 00000000000 12521741417 0016116 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/test/java/ 0000775 0000000 0000000 00000000000 12521741417 0017037 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/test/java/jnr/ 0000775 0000000 0000000 00000000000 12521741417 0017630 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/ 0000775 0000000 0000000 00000000000 12521741417 0022024 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/CredentialsFunctionalTest.java 0000664 0000000 0000000 00000010142 12521741417 0030005 0 ustar 00root root 0000000 0000000 /*
* 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/ 0000775 0000000 0000000 00000000000 12521741417 0023457 5 ustar 00root root 0000000 0000000 jnr-unixsocket-0.8/src/test/java/jnr/unixsocket/example/UnixClient.java 0000664 0000000 0000000 00000002321 12521741417 0026402 0 ustar 00root root 0000000 0000000
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.java 0000664 0000000 0000000 00000006255 12521741417 0026444 0 ustar 00root root 0000000 0000000
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;
}
}
}