,jnr.constants.platform.SocketOption> rMap = new HashMap<>();
static {
wMap.put(UnixSocketOptions.SO_RCVBUF, jnr.constants.platform.SocketOption.SO_RCVBUF);
wMap.put(UnixSocketOptions.SO_SNDBUF, jnr.constants.platform.SocketOption.SO_SNDBUF);
wMap.put(UnixSocketOptions.SO_RCVTIMEO, jnr.constants.platform.SocketOption.SO_RCVTIMEO);
wMap.put(UnixSocketOptions.SO_SNDTIMEO, jnr.constants.platform.SocketOption.SO_SNDTIMEO);
wMap.put(UnixSocketOptions.SO_KEEPALIVE, jnr.constants.platform.SocketOption.SO_KEEPALIVE);
rMap.putAll(wMap);
rMap.put(UnixSocketOptions.SO_PEERCRED, jnr.constants.platform.SocketOption.SO_PEERCRED);
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/Credentials.java 0000664 0000000 0000000 00000004742 13060565304 0030140 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2014 Greg Vanore
*
* 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;
/**
* This class represents the peer credentials, retrievable from an AF_UNIX socket.
*
* An instance of this class can be retrieved, using either the socket-level methods
* {@link UnixSocket#getCredentials} and {@link UnixDatagramSocket#getCredentials} or by specifying
* {@link UnixSocketOptions#SO_PEERCRED} as argument to one of the
* channel-level methods {@link UnixSocketChannel#getOption} and {@link UnixDatagramChannel#getOption}.
*
* See also: socket (7)
*/
public final class Credentials {
private final Ucred ucred;
Credentials(Ucred ucred) {
this.ucred = ucred;
}
/**
* Retrieves the peer's process ID.
* @return The PID.
*/
public int getPid() {
return ucred.getPidField().intValue();
}
/**
* Retrieves the peer's numeric effective user ID.
* @return The EUID.
*/
public int getUid() {
return ucred.getUidField().intValue();
}
/**
* Retrieves the peer's numeric effective group ID.
* @return The EGID.
*/
public int getGid() {
return ucred.getGidField().intValue();
}
/**
* Returns a human readable description of this instance.
*/
@Override
public java.lang.String toString() {
return java.lang.String.format("[uid=%d gid=%d pid=%d]", getUid(), getGid(), getPid());
}
static 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-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/Native.java 0000664 0000000 0000000 00000021243 13060565304 0027124 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.Errno;
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.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.ffi.types.size_t;
import jnr.ffi.types.ssize_t;
import jnr.posix.DefaultNativeTimeval;
import jnr.posix.Timeval;
class Native {
static final String[] libnames = Platform.getNativePlatform().getOS() == Platform.OS.SOLARIS
? new String[] { "socket", "nsl", Platform.getNativePlatform().getStandardCLibraryName() }
: new String[] { Platform.getNativePlatform().getStandardCLibraryName() };
public interface LibC {
int F_GETFL = jnr.constants.platform.Fcntl.F_GETFL.intValue();
int F_SETFL = jnr.constants.platform.Fcntl.F_SETFL.intValue();
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);
@ssize_t int sendto(int s, @In ByteBuffer data, @size_t long size, int flags, @In @Transient SockAddrUnix name, int namelen);
@ssize_t int recvfrom(int s, @Out ByteBuffer data, @size_t long size, int flags, @Out SockAddrUnix addr, @In @Out IntByReference len);
}
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(Runtime.getSystemRuntime()));
}
static Errno getLastError() {
return Errno.valueOf(LastError.getLastError(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 || optname == SocketOption.SO_SNDTIMEO) {
DefaultNativeTimeval t = new DefaultNativeTimeval(Runtime.getSystemRuntime());
t.setTime(new long [] {optval / 1000, ((long)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() || optname == SocketOption.SO_SNDTIMEO.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;
}
public static int sendto(int fd, ByteBuffer src, SockAddrUnix addr, int len) throws IOException {
if (src == null) {
throw new IllegalArgumentException("Source buffer cannot be null");
}
int n;
do {
n = libsocket().sendto(fd, src, src.remaining(), 0, addr, len);
} while (n < 0 && Errno.EINTR.equals(getLastError()));
if (n > 0) {
src.position(src.position() + n);
}
return n;
}
public static int recvfrom(int fd, ByteBuffer dst, SockAddrUnix addr) throws IOException {
if (dst == null) {
throw new IllegalArgumentException("Destination buffer cannot be null");
}
if (dst.isReadOnly()) {
throw new IllegalArgumentException("Read-only buffer");
}
IntByReference addrlen = (null == addr) ? null : new IntByReference(addr.getMaximumLength());
int n;
do {
n = libsocket().recvfrom(fd, dst, dst.remaining(), 0, addr, addrlen);
} while (n < 0 && Errno.EINTR.equals(getLastError()));
if (n > 0) {
dst.position(dst.position() + n);
}
return n;
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/SockAddrUnix.java 0000664 0000000 0000000 00000015253 13060565304 0030240 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 static java.nio.charset.StandardCharsets.UTF_8;
import jnr.constants.platform.ProtocolFamily;
import jnr.ffi.Platform;
import jnr.ffi.Platform.OS;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;
/**
* Native unix domain socket address structure.
*/
abstract class SockAddrUnix extends Struct {
private static transient OS currentOS = Platform.getNativePlatform().getOS();
public final static int ADDR_LENGTH = 108;
public final static int HEADER_LENGTH = 2;
protected abstract UTF8String getPathField();
protected abstract NumberField getFamilyField();
// This is important to be cached here for supporting abstract namespace on Linux
// (which starts with a NUL byte. path is NOT NUL terminated in this case!)
private java.lang.String cachedPath;
SockAddrUnix() {
super(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
*/
void setPath(java.lang.String path) {
cachedPath = path;
getPathField().set(cachedPath);
}
/**
* Updates the file system path of this socket address.
* In order to support abstract namespaces, this MUST be
* called after any native syscall that sets this
* path struct like getsockname(), getpeername(), accept().
*
* @param len the value of the addrlen var, set by the above syscalls.
*/
void updatePath(final int len) {
if (currentOS == OS.LINUX) {
// Linux always returns an accurate length in
// order to support abstract namespace, where
// path STARTS with a NUL byte.
cachedPath = len == HEADER_LENGTH ? "" : getPath(len - HEADER_LENGTH);
} else {
// All others might return a len > 0 (typically 14) AND the path is terminated
// by a NUL byte if it is shorter than sizeof(sun_path)
cachedPath = getPathField().get();
int slen = len - HEADER_LENGTH;
if (slen <= 0) {
cachedPath = "";
} else {
if (slen < getPathField().length() && slen < cachedPath.length()) {
cachedPath = cachedPath.substring(0, slen);
}
}
}
}
/**
* Gets the file system path of this socket address
*
* @return A String
*/
final java.lang.String getPath() {
if (null == cachedPath) {
cachedPath = getPathField().get();
}
return cachedPath;
}
/**
* Gets the path of this socket address, supporting abstract namespace on Linux.
*
* @param len The desired length of the string.
* If the first character of the path is NUL, then this value ist considered
* exact, otherwise it includes a trailing NUL charater and therefore the actual
* string length is len - 1.
*/
final java.lang.String getPath(int len) {
UTF8String str = getPathField();
byte [] ba = new byte[str.length()];
str.getMemory().get(str.offset(), ba, 0, len);
if (0 != ba[0]) {
len -= 1;
}
return new java.lang.String(java.util.Arrays.copyOf(ba, len), UTF_8);
}
/**
* Gets the maximum length of this address (including len/family header)
*
* @return The maximum size of the address in bytes
*/
int getMaximumLength() {
return HEADER_LENGTH + getPathField().length();
}
/**
* Gets the actual length of this address (including len/family header)
*
* @return The actual size of this address, in bytes
*/
int length() {
if (currentOS == OS.LINUX && null != cachedPath) {
return HEADER_LENGTH + cachedPath.length();
}
return HEADER_LENGTH + strlen(getPathField());
}
/**
* Gets len/family header length
*
* @return The size of header, in bytes
*/
int getHeaderLength() {
return HEADER_LENGTH;
}
/**
* 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);
@Override
public void setPath(java.lang.String path) {
super.setPath(path);
sun_len.set(path.length());
}
protected UTF8String getPathField() {
return sun_addr;
}
protected 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 UTF8String getPathField() {
return sun_addr;
}
protected NumberField getFamilyField() {
return sun_family;
}
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/Ucred.java 0000664 0000000 0000000 00000002116 13060565304 0026736 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());
}
pid_t getPidField() {
return pid;
}
uid_t getUidField() {
return uid;
}
gid_t getGidField() {
return gid;
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixDatagramChannel.java 0000664 0000000 0000000 00000021531 13060565304 0031553 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2016 Fritz Elfert
*
* 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.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
import java.nio.channels.UnsupportedAddressTypeException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketOption;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import jnr.constants.platform.ProtocolFamily;
import jnr.constants.platform.Sock;
import jnr.enxio.channels.AbstractNativeDatagramChannel;
public class UnixDatagramChannel extends AbstractNativeDatagramChannel {
static enum State {
UNINITIALIZED,
CONNECTED,
IDLE,
}
private State state;
private UnixSocketAddress remoteAddress = null;
private UnixSocketAddress localAddress = null;
private final ReadWriteLock stateLock = new ReentrantReadWriteLock();
private final BindHandler bindHandler;
public static final UnixDatagramChannel open() throws IOException {
return new UnixDatagramChannel();
}
public static final UnixDatagramChannel[] pair() throws IOException {
int[] sockets = { -1, -1 };
Native.socketpair(ProtocolFamily.PF_UNIX, Sock.SOCK_DGRAM, 0, sockets);
return new UnixDatagramChannel[] {
new UnixDatagramChannel(sockets[0], State.CONNECTED, true),
new UnixDatagramChannel(sockets[1], State.CONNECTED, true)
};
}
private UnixDatagramChannel() throws IOException {
this(Native.socket(ProtocolFamily.PF_UNIX, Sock.SOCK_DGRAM, 0));
}
UnixDatagramChannel(int fd) {
this(fd, State.IDLE, false);
}
UnixDatagramChannel(int fd, State initialState, boolean initialBoundState) {
super(fd);
stateLock.writeLock().lock();
state = initialState;
bindHandler = new BindHandler(initialBoundState);
stateLock.writeLock().unlock();
}
UnixDatagramChannel(int fd, UnixSocketAddress remote) throws IOException {
this(fd);
connect(remote);
}
@Override
public UnixDatagramChannel bind(SocketAddress local) throws IOException {
localAddress = bindHandler.bind(getFD(), local);
return this;
}
public UnixDatagramChannel connect(UnixSocketAddress remote) {
stateLock.writeLock().lock();
remoteAddress = remote;
state = State.CONNECTED;
stateLock.writeLock().unlock();
return this;
}
public UnixDatagramChannel disconnect() throws IOException {
stateLock.writeLock().lock();
remoteAddress = null;
state = State.IDLE;
stateLock.writeLock().unlock();
return this;
}
boolean isBound() {
return bindHandler.isBound();
}
public boolean isConnected() {
stateLock.readLock().lock();
boolean isConnected = state == State.CONNECTED;
stateLock.readLock().unlock();
return isConnected;
}
public final UnixSocketAddress getRemoteSocketAddress() {
if (!isConnected()) {
return null;
}
return remoteAddress != null ? remoteAddress : (remoteAddress = Common.getpeername(getFD()));
}
public final UnixSocketAddress getLocalSocketAddress() {
return localAddress != null ? localAddress : (localAddress = Common.getsockname(getFD()));
}
@Override
public UnixSocketAddress receive(ByteBuffer src) throws IOException {
UnixSocketAddress remote = new UnixSocketAddress();
int n = Native.recvfrom(getFD(), src, remote.getStruct());
if (n < 0) {
throw new IOException(Native.getLastErrorString());
}
return remote;
}
@Override
public int send(ByteBuffer src, SocketAddress target) throws IOException {
UnixSocketAddress remote = null;
if (null == target) {
if (isConnected()) {
remote = remoteAddress;
} else {
throw new IllegalArgumentException("Destination address cannot be null on unconnected datagram sockets");
}
} else {
if (!(target instanceof UnixSocketAddress)) {
throw new UnsupportedAddressTypeException();
}
remote = (UnixSocketAddress)target;
}
SockAddrUnix sa = (null == remote) ? null : remote.getStruct();
int addrlen = (null == sa) ? 0 : sa.length();
int n = Native.sendto(getFD(), src, sa, addrlen);
if (n < 0) {
throw new IOException(Native.getLastErrorString());
}
return n;
}
@Override
public DatagramChannel connect(SocketAddress remote) throws IOException {
if (remote instanceof UnixSocketAddress) {
return connect(((UnixSocketAddress) remote));
} else {
throw new UnsupportedAddressTypeException();
}
}
@Override
public UnixDatagramSocket socket() {
try {
return new UnixDatagramSocket(this);
} catch (SocketException e) {
throw new NullPointerException("Could not create UnixDatagramSocket");
}
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException {
if (state == State.CONNECTED) {
return super.write(srcs, offset, length);
} else if (state == State.IDLE) {
return 0;
} else {
throw new ClosedChannelException();
}
}
@Override
public int read(ByteBuffer dst) throws IOException {
if (state == State.CONNECTED) {
return super.read(dst);
} else if (state == State.IDLE) {
return 0;
} else {
throw new ClosedChannelException();
}
}
@Override
public int write(ByteBuffer src) throws IOException {
if (state == State.CONNECTED) {
return super.write(src);
} else if (state == State.IDLE) {
return 0;
} else {
throw new ClosedChannelException();
}
}
@Override
public SocketAddress getRemoteAddress() throws IOException {
return remoteAddress;
}
@Override
public SocketAddress getLocalAddress() throws IOException {
return localAddress;
}
private static class DefaultOptionsHolder {
static final Set> defaultOptions = defaultOptions();
private static Set> defaultOptions() {
HashSet> set = new HashSet>(5);
set.add(UnixSocketOptions.SO_SNDBUF);
set.add(UnixSocketOptions.SO_SNDTIMEO);
set.add(UnixSocketOptions.SO_RCVBUF);
set.add(UnixSocketOptions.SO_RCVTIMEO);
set.add(UnixSocketOptions.SO_PEERCRED);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set> supportedOptions() {
return DefaultOptionsHolder.defaultOptions;
}
@Override
public T getOption(SocketOption name) throws IOException {
if (!supportedOptions().contains(name)) {
throw new UnsupportedOperationException("'" + name + "' not supported");
}
return Common.getSocketOption(getFD(), name);
}
@Override
public DatagramChannel setOption(SocketOption name, T value)
throws IOException {
if (name == null) {
throw new IllegalArgumentException("name may not be null");
}
if (!supportedOptions().contains(name)) {
throw new UnsupportedOperationException("'" + name + "' not supported");
}
Common.setSocketOption(getFD(), name, value);
return this;
}
@Override
public MembershipKey join(InetAddress group, NetworkInterface interf) {
throw new UnsupportedOperationException("join is not supported");
}
@Override
public MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) {
throw new UnsupportedOperationException("join is not supported");
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixDatagramSocket.java 0000664 0000000 0000000 00000023363 13060565304 0031440 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2016 Fritz Elfert
*
* 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.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.channels.DatagramChannel;
import java.nio.channels.UnsupportedAddressTypeException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* A SOCK_DGRAM variant of an AF_UNIX socket.
* This specializaton of DatagramSocket delegates
* most of it's funtionality to the corresponding
* UnixDatagramChannel.
*/
public class UnixDatagramSocket extends DatagramSocket {
private final UnixDatagramChannel chan;
private final AtomicBoolean closed = new AtomicBoolean(false);
/**
* Constructs a new instance.
* @param channel The channel to use.
* @throws SocketException if the socket could not be created.
*/
UnixDatagramSocket(final UnixDatagramChannel channel) throws SocketException {
chan = channel;
}
/**
* Constructs a new unbound instance.
* @throws SocketException if the socket could not be created.
*/
public UnixDatagramSocket() throws SocketException {
chan = null;
}
/**
* Binds this UnixDatagramSocket to a specific AF_UNIX address.
*
* If the address is {@code null}, then on Linux, an autobind will be performed,
* which will bind this socket in Linux' abstract namespace on a unique path, chosen by
* the system. On all other platforms, A temporary path in the regular filesystem will be chosen.
*
* @param local The {@link UnixSocketAddress} to bind to.
* @throws SocketException if any error happens during the bind, or if the
* socket is already bound.
* @throws UnsupportedAddressTypeException if addr is a SocketAddress subclass
* not supported by this socket.
*/
@Override
public void bind(final SocketAddress local) throws SocketException {
if (null != chan) {
if (isClosed()) {
throw new SocketException("Socket is closed");
}
if (isBound()) {
throw new SocketException("already bound");
}
try {
chan.bind(local);
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
}
@Override
public synchronized void disconnect() {
if (isClosed()) {
return;
}
if (null != chan) {
try {
chan.disconnect();
} catch (IOException e) {
ignore();
}
}
}
@Override
public synchronized void close() {
if (null != chan && closed.compareAndSet(false, true)) {
try {
chan.close();
} catch (IOException e) {
ignore();
}
}
}
@Override
public void connect(SocketAddress addr) throws SocketException {
try {
chan.connect(addr);
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void connect(InetAddress addr, int port) {
throw new UnsupportedOperationException("connect(InetAddress, int) is not supported");
}
@Override
public DatagramChannel getChannel() {
return chan;
}
/**
* Returns the address to which this socket is connected (NOT implemented).
* Since AF_UNIX sockets can not have an InetAddress, this returns always {@code null}.
* Use {@link #getRemoteSocketAddress} instead, which always returns a {@link UnixSocketAddress}.
* @return {@code null} always.
*/
@Override
public InetAddress getInetAddress() {
return null;
}
/**
* Returns the address of the endpoint this socket is bound to.
*
* @return a {@code SocketAddress} representing the local endpoint of this
* socket, or {@code null} if it is closed or not bound.
* A non-null return value is always of type {@link UnixSocketAddress}
* @see #bind(SocketAddress)
*/
@Override
public SocketAddress getLocalSocketAddress() {
if (isClosed()) {
return null;
}
if (null == chan) {
return null;
}
return chan.getLocalSocketAddress();
}
/**
* Returns the address of the endpoint this socket is connected to, or
* {@code null} if it is unconnected.
*
* @return a {@code SocketAddress} representing the remote
* endpoint of this socket, or {@code null} if it is
* not connected.
* A non-null return value is always of type {@link UnixSocketAddress}
*/
@Override
public SocketAddress getRemoteSocketAddress() {
if (!isConnected()) {
return null;
}
return chan.getRemoteSocketAddress();
}
@Override
public boolean isBound() {
if (null == chan) {
return false;
}
return chan.isBound();
}
@Override
public boolean isClosed() {
if (null == chan) {
return false;
}
return closed.get();
}
@Override
public boolean isConnected() {
if (null == chan) {
return false;
}
return chan.isConnected();
}
/**
* 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
* @throws SocketException if fetching the socket option failed.
*
* @return the credentials of the remote; null if not connected
*/
public final Credentials getCredentials() throws SocketException {
if (!chan.isConnected()) {
return null;
}
try {
return chan.getOption(UnixSocketOptions.SO_PEERCRED);
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public int getReceiveBufferSize() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_RCVBUF).intValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public int getSendBufferSize() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_SNDBUF).intValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public int getSoTimeout() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_RCVTIMEO).intValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setReceiveBufferSize(int size) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_RCVBUF, Integer.valueOf(size));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setSendBufferSize(int size) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_SNDBUF, Integer.valueOf(size));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setSoTimeout(int timeout) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_RCVTIMEO, Integer.valueOf(timeout));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
/**
* Sends a datagram packet from this socket (NOT implemented).
* Unfortunately, {@link java.net.DatagramPacket} is final and can not deal
* with AF_UNIX addresses. Therefore, this functionality was omitted.
* @see java.net.DatagramPacket
* @see java.net.DatagramSocket#send
* @throws UnsupportedOperationException always.
*/
@Override
public void send(DatagramPacket p) throws IOException {
throw new UnsupportedOperationException("sending DatagramPackets is not supported");
}
/**
* Receives a datagram packet from this socket (NOT implemented).
* Unfortunately, {@link java.net.DatagramPacket} is final and can not deal
* with AF_UNIX addresses. Therefore, this functionality was omitted.
* @see java.net.DatagramPacket
* @see java.net.DatagramSocket#receive
* @throws UnsupportedOperationException always.
*/
@Override
public synchronized void receive(DatagramPacket p) throws IOException {
throw new UnsupportedOperationException("receiving DatagramPackets is not supported");
}
private void ignore() {
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixServerSocket.java 0000664 0000000 0000000 00000003460 13060565304 0031162 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;
import java.nio.channels.UnsupportedAddressTypeException;
public class UnixServerSocket {
final UnixServerSocketChannel channel;
final int fd;
volatile UnixSocketAddress localAddress;
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 IOException {
bind(endpoint, 128);
}
public void bind(SocketAddress endpoint, int backlog) throws IOException {
if (null != endpoint && !(endpoint instanceof UnixSocketAddress)) {
throw new UnsupportedAddressTypeException();
}
localAddress = Common.bind(fd, (UnixSocketAddress)endpoint);
if (Native.listen(fd, backlog) < 0) {
throw new IOException(Native.getLastErrorString());
}
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixServerSocketChannel.java 0000664 0000000 0000000 00000005207 13060565304 0032454 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();
int maxLength = addr.getMaximumLength();
IntByReference len = new IntByReference(maxLength);
int clientfd = Native.accept(getFD(), addr, len);
if (clientfd < 0) {
if (isBlocking()) {
throw new IOException("accept failed: " + Native.getLastErrorString());
}
return null;
}
// Handle unnamed sockets and sockets in Linux' abstract namespace
addr.updatePath(len.getValue());
// Always force the socket back to blocking mode
Native.setBlocking(clientfd, true);
return new UnixSocketChannel(clientfd);
}
public final UnixServerSocket socket() {
return socket;
}
public final UnixSocketAddress getRemoteSocketAddress() {
return null;
}
public final UnixSocketAddress getLocalSocketAddress() {
return socket.localAddress;
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixSocket.java 0000664 0000000 0000000 00000017741 13060565304 0030002 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2009 Wayne Meissner
* Copyright (C) 2016 Marcus Linke
*
* (ported from https://github.com/softprops/unisockets/blob/master/unisockets-core/src/main/scala/Socket.scala)
*
* 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.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.Channels;
import java.nio.channels.SocketChannel;
import java.util.concurrent.atomic.AtomicBoolean;
public class UnixSocket extends java.net.Socket {
private UnixSocketChannel chan;
private AtomicBoolean closed = new AtomicBoolean(false);
private AtomicBoolean indown = new AtomicBoolean(false);
private AtomicBoolean outdown = new AtomicBoolean(false);
private InputStream in;
private OutputStream out;
public UnixSocket(UnixSocketChannel chan) {
this.chan = chan;
in = Channels.newInputStream(chan);
out = Channels.newOutputStream(chan);
}
@Override
public void bind(SocketAddress local) throws IOException {
if (null != chan) {
if (isClosed()) {
throw new SocketException("Socket is closed");
}
if (isBound()) {
throw new SocketException("already bound");
}
try {
chan.bind(local);
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
}
@Override
public void close() throws IOException {
if (null != chan && closed.compareAndSet(false, true)) {
try {
chan.close();
} catch (IOException e) {
ignore();
}
}
}
@Override
public void connect(SocketAddress addr) throws IOException {
connect(addr, 0);
}
public void connect(SocketAddress addr, Integer timeout) throws IOException {
if (addr instanceof UnixSocketAddress) {
chan.connect((UnixSocketAddress) addr);
} else {
throw new IllegalArgumentException("address of type "
+ addr.getClass() + " are not supported. Use "
+ UnixSocketAddress.class + " instead");
}
}
@Override
public SocketChannel getChannel() {
return chan;
}
@Override
public InetAddress getInetAddress() {
return null;
}
public InputStream getInputStream() throws IOException {
if (chan.isConnected()) {
return in;
} else {
throw new IOException("not connected");
}
}
@Override
public SocketAddress getLocalSocketAddress() {
UnixSocketAddress address = chan.getLocalSocketAddress();
if (address != null) {
return address;
} else {
return null;
}
}
@Override
public OutputStream getOutputStream() throws IOException {
if (chan.isConnected()) {
return out;
} else {
throw new IOException("not connected");
}
}
@Override
public SocketAddress getRemoteSocketAddress() {
SocketAddress address = chan.getRemoteSocketAddress();
if (address != null) {
return address;
} else {
return null;
}
}
@Override
public boolean isBound() {
if (null == chan) {
return false;
}
return chan.isBound();
}
@Override
public boolean isClosed() {
return closed.get();
}
@Override
public boolean isConnected() {
return chan.isConnected();
}
@Override
public boolean isInputShutdown() {
return indown.get();
}
@Override
public boolean isOutputShutdown() {
return outdown.get();
}
@Override
public void shutdownInput() throws IOException {
if (indown.compareAndSet(false, true)) {
chan.shutdownInput();
}
}
@Override
public void shutdownOutput() throws IOException {
if (outdown.compareAndSet(false, true)) {
chan.shutdownOutput();
}
}
/**
* 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
* @throws SocketException if fetching the socket option failed.
*
* @return the credentials of the remote; null if not connected
*/
public final Credentials getCredentials() throws SocketException {
if (!chan.isConnected()) {
return null;
}
try {
return chan.getOption(UnixSocketOptions.SO_PEERCRED);
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public boolean getKeepAlive() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_KEEPALIVE).booleanValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public int getReceiveBufferSize() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_RCVBUF).intValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public int getSendBufferSize() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_SNDBUF).intValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public int getSoTimeout() throws SocketException {
try {
return chan.getOption(UnixSocketOptions.SO_RCVTIMEO).intValue();
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setKeepAlive(boolean on) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setReceiveBufferSize(int size) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_RCVBUF, Integer.valueOf(size));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setSendBufferSize(int size) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_SNDBUF, Integer.valueOf(size));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
@Override
public void setSoTimeout(int timeout) throws SocketException {
try {
chan.setOption(UnixSocketOptions.SO_RCVTIMEO, Integer.valueOf(timeout));
} catch (IOException e) {
throw (SocketException)new SocketException().initCause(e);
}
}
private void ignore() {
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixSocketAddress.java 0000664 0000000 0000000 00000010103 13060565304 0031271 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.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import jnr.constants.platform.ProtocolFamily;
/**
* This class represents an AF_UNIX-style socket address.
* On Linux, it supports the platform-specific abstract name space.
*
* Using an abstract name space is denoted by the socket path starting with
* a NUL byte. Sockets in abstract name space have no entry in the file system.
* When linux performs autobind, it constructs the resulting path with a
* leading NUL, followed by a unique 5-digit hexadecimal number.
*/
public class UnixSocketAddress extends java.net.SocketAddress {
private static final long serialVersionUID = 4821337010221569096L;
private transient 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.getPath());
}
public UnixSocketAddress(final String path) {
address = SockAddrUnix.create();
address.setFamily(ProtocolFamily.PF_UNIX);
address.setPath(path);
}
SockAddrUnix getStruct() {
return address;
}
int length() {
return address.length();
}
/**
* Retrieves the path.
* @return The path of this AF_UNIX address.
* Note: On Linux, can contain a leading NUL byte, if this address
* resides in abstract namespace.
*/
public String path() {
return address.getPath();
}
/**
* Returns a human readable path.
* On Linux, AF_UNIX sockets can be bound/connected in abstract namespace.
* This is denoted by a leading NUL byte in the path.
* In order to be properly displayed, this method returns a path prefixed
* by '@' like netstat, lsof an similar tools.
* @return The human readable path of this address.
*/
public String humanReadablePath() {
String ret = path();
// Handle abstract namespace like netstat: replace NUL by '@'
if (ret.indexOf('\000') == 0) {
return ret.replace('\000', '@');
}
return ret;
}
/**
* Retrieves a human readable description of this address.
* @return The human readable description of this address.
*/
@Override
public String toString() {
return "[family=" + address.getFamily() + " path=" + humanReadablePath() + "]";
}
@Override
public boolean equals(Object _other) {
if (!(_other instanceof UnixSocketAddress)) {
return false;
}
UnixSocketAddress other = (UnixSocketAddress)_other;
return address.getFamily() == other.address.getFamily() &&
path().equals(other.path());
}
@Override
public int hashCode() {
return address.hashCode();
}
// Serializable
private void writeObject(ObjectOutputStream o) throws IOException {
o.defaultWriteObject();
o.writeObject(path());
}
private void readObject(ObjectInputStream o)
throws IOException, ClassNotFoundException {
o.defaultReadObject();
String path = (String)o.readObject();
if (null == address) {
address = SockAddrUnix.create();
}
address.setPath(path);
address.setFamily(ProtocolFamily.PF_UNIX);
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixSocketChannel.java 0000664 0000000 0000000 00000023115 13060565304 0031263 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2009 Wayne Meissner
* Copyright (C) 2016 Marcus Linke
*
* 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;
import java.net.SocketOption;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnsupportedAddressTypeException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import jnr.constants.platform.Errno;
import jnr.constants.platform.ProtocolFamily;
import jnr.constants.platform.Sock;
import jnr.enxio.channels.AbstractNativeSocketChannel;
import jnr.ffi.LastError;
/**
* A {@link java.nio.channels.Channel} implementation that uses a native unix
* socket
*/
public class UnixSocketChannel extends AbstractNativeSocketChannel {
enum State {
UNINITIALIZED,
CONNECTED,
IDLE,
CONNECTING,
}
private State state;
private UnixSocketAddress remoteAddress = null;
private UnixSocketAddress localAddress = null;
private final ReadWriteLock stateLock = new ReentrantReadWriteLock();
private final BindHandler bindHandler;
public static final UnixSocketChannel open() throws IOException {
return new UnixSocketChannel();
}
public static final UnixSocketChannel open(UnixSocketAddress remote)
throws IOException {
UnixSocketChannel channel = new UnixSocketChannel();
try {
channel.connect(remote);
} catch (IOException e) {
channel.close();
throw e;
}
return channel;
}
public static final UnixSocketChannel create() throws IOException {
return new UnixSocketChannel();
}
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], State.CONNECTED, true),
new UnixSocketChannel(sockets[1], State.CONNECTED, true) };
}
/**
* Create a UnixSocketChannel to wrap an existing file descriptor
* (presumably itself a UNIX socket).
*
* @param fd
* the file descriptor to wrap
* @return the new UnixSocketChannel instance
*/
public static final UnixSocketChannel fromFD(int fd) {
return new UnixSocketChannel(fd);
}
UnixSocketChannel() throws IOException {
this(Native.socket(ProtocolFamily.PF_UNIX, Sock.SOCK_STREAM, 0));
}
UnixSocketChannel(int fd) {
this(fd, State.CONNECTED, false);
}
UnixSocketChannel(int fd, State initialState, boolean initialBoundState) {
super(fd);
stateLock.writeLock().lock();
state = initialState;
bindHandler = new BindHandler(initialBoundState);
stateLock.writeLock().unlock();
}
private 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())) {
stateLock.writeLock().lock();
state = State.CONNECTING;
stateLock.writeLock().unlock();
return false;
} else {
stateLock.writeLock().lock();
state = State.CONNECTED;
stateLock.writeLock().unlock();
return true;
}
}
boolean isBound() {
return bindHandler.isBound();
}
public boolean isConnected() {
stateLock.readLock().lock();
boolean result = state == State.CONNECTED;
stateLock.readLock().unlock();
return result;
}
private boolean isIdle() {
stateLock.readLock().lock();
boolean result = state == State.IDLE;
stateLock.readLock().unlock();
return result;
}
public boolean isConnectionPending() {
stateLock.readLock().lock();
boolean isConnectionPending = state == State.CONNECTING;
stateLock.readLock().unlock();
return isConnectionPending;
}
public boolean finishConnect() throws IOException {
stateLock.writeLock().lock();
try {
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");
}
} finally {
stateLock.writeLock().unlock();
}
}
public final UnixSocketAddress getRemoteSocketAddress() {
if (!isConnected()) {
return null;
}
if (remoteAddress != null) {
return remoteAddress;
} else {
remoteAddress = Common.getpeername(getFD());
return remoteAddress;
}
}
public final UnixSocketAddress getLocalSocketAddress() {
if (localAddress != null) {
return localAddress;
} else {
localAddress = Common.getsockname(getFD());
return localAddress;
}
}
@Override
public boolean connect(SocketAddress remote) throws IOException {
if (remote instanceof UnixSocketAddress) {
return connect(((UnixSocketAddress) remote));
} else {
throw new UnsupportedAddressTypeException();
}
}
@Override
public UnixSocket socket() {
return new UnixSocket(this);
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length)
throws IOException {
if (isConnected()) {
return super.write(srcs, offset, length);
} else if (isIdle()) {
return 0;
} else {
throw new ClosedChannelException();
}
}
@Override
public int read(ByteBuffer dst) throws IOException {
if (isConnected()) {
return super.read(dst);
} else if (isIdle()) {
return 0;
} else {
throw new ClosedChannelException();
}
}
@Override
public int write(ByteBuffer src) throws IOException {
if (isConnected()) {
return super.write(src);
} else if (isIdle()) {
return 0;
} else {
throw new ClosedChannelException();
}
}
@Override
public SocketAddress getRemoteAddress() throws IOException {
return remoteAddress;
}
@Override
public SocketAddress getLocalAddress() throws IOException {
return localAddress;
}
private static class DefaultOptionsHolder {
static final Set> defaultOptions = defaultOptions();
private static Set> defaultOptions() {
HashSet> set = new HashSet>(5);
set.add(UnixSocketOptions.SO_SNDBUF);
set.add(UnixSocketOptions.SO_SNDTIMEO);
set.add(UnixSocketOptions.SO_RCVBUF);
set.add(UnixSocketOptions.SO_RCVTIMEO);
set.add(UnixSocketOptions.SO_PEERCRED);
set.add(UnixSocketOptions.SO_KEEPALIVE);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set> supportedOptions() {
return DefaultOptionsHolder.defaultOptions;
}
@Override
public T getOption(SocketOption name) throws IOException {
if (!supportedOptions().contains(name)) {
throw new UnsupportedOperationException("'" + name
+ "' not supported");
}
return Common.getSocketOption(getFD(), name);
}
@Override
public SocketChannel setOption(SocketOption name, T value)
throws IOException {
if (name == null) {
throw new IllegalArgumentException("name may not be null");
}
if (!supportedOptions().contains(name)) {
throw new UnsupportedOperationException("'" + name
+ "' not supported");
}
Common.setSocketOption(getFD(), name, value);
return this;
}
@Override
public synchronized UnixSocketChannel bind(SocketAddress local) throws IOException {
localAddress = bindHandler.bind(getFD(), local);
return this;
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/main/java/jnr/unixsocket/UnixSocketOptions.java 0000664 0000000 0000000 00000004436 13060565304 0031353 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2016 Fritz Elfert
*
* 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.net.SocketOption;
/**
* Defines common socket options for AF_UNIX sockets.
*/
public final class UnixSocketOptions {
private static class GenericOption implements SocketOption {
private final String name;
private final Class type;
GenericOption(String name, Class type) {
this.name = name;
this.type = type;
}
@Override public String name() { return name; }
@Override public Class type() { return type; }
@Override public String toString() { return name; }
}
/**
* Get/Set size of the socket send buffer.
*/
public static final SocketOption SO_SNDBUF =
new GenericOption("SO_SNDBUF", Integer.class);
/**
* Get/Set send timeout.
*/
public static final SocketOption SO_SNDTIMEO =
new GenericOption("SO_SNDTIMEO", Integer.class);
/**
* Get/Set size of the socket receive buffer.
*/
public static final SocketOption SO_RCVBUF =
new GenericOption("SO_RCVBUF", Integer.class);
/**
* Get/Set receive timeout.
*/
public static final SocketOption SO_RCVTIMEO =
new GenericOption("SO_RCVTIMEO", Integer.class);
/**
* Keep connection alive.
*/
public static final SocketOption SO_KEEPALIVE =
new GenericOption("SO_KEEPALIVE", Boolean.class);
/**
* Fetch peer credentials.
*/
public static final SocketOption SO_PEERCRED =
new GenericOption("SO_PEERCRED", Credentials.class);
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/ 0000775 0000000 0000000 00000000000 13060565304 0021156 5 ustar 00root root 0000000 0000000 jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/ 0000775 0000000 0000000 00000000000 13060565304 0022077 5 ustar 00root root 0000000 0000000 jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/ 0000775 0000000 0000000 00000000000 13060565304 0022670 5 ustar 00root root 0000000 0000000 jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/ 0000775 0000000 0000000 00000000000 13060565304 0025064 5 ustar 00root root 0000000 0000000 jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/BasicDatagramFunctionalityTest.java 0000664 0000000 0000000 00000011730 13060565304 0034024 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2016 Fritz Elfert
*
* 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 junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.AlreadyBoundException;
import java.nio.channels.DatagramChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import jnr.ffi.Platform;
import jnr.ffi.Platform.OS;
import org.junit.Assume;
import org.junit.Test;
public class BasicDatagramFunctionalityTest {
private static final String DATA = "foo bar baz. The quick brown fox jumps over the lazy dog. ";
volatile Throwable serverException;
volatile long received = 0;
private UnixSocketAddress makeAddress() throws IOException {
File socketFile = Files.createTempFile("jnr-unixsocket-test", ".sock").toFile();
socketFile.delete();
socketFile.deleteOnExit();
return new UnixSocketAddress(socketFile);
}
private void basicOperation(final long minBytesToSend) throws Throwable {
serverException = null;
final StringBuffer rxdata = new StringBuffer();
final StringBuffer txdata = new StringBuffer();
final ByteBuffer rxbuf = ByteBuffer.allocate(1024);
final ByteBuffer txbuf = ByteBuffer.allocate(2024);
final UnixSocketAddress serverAddress = makeAddress();
Thread serverThread = new Thread("server side") {
final UnixDatagramChannel serverChannel = UnixDatagramChannel.open().bind(serverAddress);
public void run() {
while (null == serverException) {
try {
rxbuf.clear();
serverChannel.receive(rxbuf);
rxbuf.flip();
int count = rxbuf.limit();
rxdata.append(StandardCharsets.UTF_8.decode(rxbuf).toString());
received += count;;
} catch (IOException ex) {
serverException = ex;
}
}
}
};
serverThread.start();
// client logic
DatagramChannel clientChannel = UnixDatagramChannel.open();
received = 0;
long written = 0;
while (null == serverException && written < minBytesToSend) {
txbuf.put(StandardCharsets.UTF_8.encode(DATA));
txbuf.flip();
written += clientChannel.send(txbuf, serverAddress);
txbuf.compact();
txdata.append(DATA);
if (null != serverException) {
throw new Exception().initCause(serverException);
}
}
clientChannel.close();
while (null == serverException && received < written) {
Thread.sleep(100);
}
assertTrue("More than 0 bytes written", written > 0);
assertEquals("received", written, received);
assertEquals("received data", txdata.toString(), rxdata.toString());
}
@Test
public void smallBasicOperationTest() throws Throwable {
basicOperation(DATA.length());
}
@Test
public void largeBasicOperationTest() throws Throwable {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
basicOperation(1000L * DATA.length());
}
@Test
public void doubleBindTest() throws Exception {
UnixDatagramChannel ch = UnixDatagramChannel.open().bind(null);
try {
ch.bind(null);
fail("Should have thrown AlreadyBoundException");
} catch (AlreadyBoundException abx) {
try {
ch.socket().bind(null);
fail("Should have thrown SocketException");
} catch (SocketException sx) {
assertEquals("exception message", sx.getMessage(), "already bound");
}
}
}
@Test
public void pairTest() throws Exception {
UnixDatagramChannel[] sp = UnixDatagramChannel.pair();
for (final UnixDatagramChannel ch : sp) {
assertTrue("Channel is connected", ch.isConnected());
assertTrue("Channel is bound", ch.isBound());
assertFalse("Channel's socket is not closed", ch.socket().isClosed());
}
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/BasicFunctionalityTest.java 0000664 0000000 0000000 00000013272 13060565304 0032366 0 ustar 00root root 0000000 0000000
package jnr.unixsocket;
import static java.nio.charset.StandardCharsets.UTF_8;
import static junit.framework.Assert.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AlreadyBoundException;
import java.nio.channels.Channels;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Set;
import jnr.enxio.channels.NativeSelectorProvider;
import org.junit.Test;
public class BasicFunctionalityTest {
private static final File SOCKADDR = new File("/tmp/jnr-unixsocket-test" + System.currentTimeMillis() + ".sock");
static { SOCKADDR.deleteOnExit(); }
private static final UnixSocketAddress ADDRESS = new UnixSocketAddress(SOCKADDR);
private static final String DATA = "blah blah";
private Thread server;
private volatile Exception serverException;
@Test
public void doubleBindTest() throws Exception {
UnixSocketChannel ch = UnixSocketChannel.open().bind(null);
try {
ch.bind(null);
fail("Should have thrown AlreadyBoundException");
} catch (AlreadyBoundException abx) {
try {
ch.socket().bind(null);
fail("Should have thrown SocketException");
} catch (SocketException sx) {
assertEquals("exception message", sx.getMessage(), "already bound");
}
}
}
@Test
public void pairTest() throws Exception {
UnixSocketChannel[] sp = UnixSocketChannel.pair();
for (final UnixSocketChannel ch : sp) {
assertTrue("Channel is connected", ch.isConnected());
assertTrue("Channel is bound", ch.isBound());
assertFalse("Channel's socket is not closed", ch.socket().isClosed());
}
}
@Test
public void basicOperation() throws Exception {
// server logic
final UnixServerSocketChannel channel = UnixServerSocketChannel.open();
final Selector sel = NativeSelectorProvider.getInstance().openSelector();
channel.configureBlocking(false);
channel.socket().bind(ADDRESS);
channel.register(sel, SelectionKey.OP_ACCEPT, new ServerActor(channel, sel));
// TODO: This is ugly but simple enough. Many failures on server side will cause client to hang.
server = new Thread("server side") {
public void run() {
try {
while (sel.select() > 0) {
Set keys = sel.selectedKeys();
assertNotNull(keys);
assertTrue(keys.size() > 0);
for (SelectionKey k : keys) {
assertTrue(k.attachment() instanceof Actor);
Actor a = (Actor) k.attachment();
if (!a.rxready()) {
k.cancel();
}
}
}
} catch (Exception ex) {
serverException = ex;
}
}
};
server.start();
// client logic
UnixSocketChannel channel2 = UnixSocketChannel.open(ADDRESS);
assertEquals(ADDRESS, channel2.getRemoteSocketAddress());
Channels.newOutputStream(channel2).write(DATA.getBytes(UTF_8));
InputStreamReader r = new InputStreamReader(Channels.newInputStream(channel2), UTF_8);
CharBuffer result = CharBuffer.allocate(1024);
r.read(result);
assertEquals(DATA.length(), result.position());
result.flip();
assertEquals(DATA, result.toString());
if (serverException != null) throw serverException;
}
static interface Actor {
public boolean rxready();
}
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();
if (client == null) {
// nonblocking result
return false;
}
assertEquals(ADDRESS, client.getLocalSocketAddress());
assertEquals("", client.getRemoteSocketAddress().getStruct().getPath());
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ, new ClientActor(client));
return true;
} catch (IOException ex) {
return false;
}
}
}
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);
assertEquals("", channel.getRemoteSocketAddress().getStruct().getPath());
assertEquals(DATA.length(), n);
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;
}
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/ChannelOptionsTest.java 0000664 0000000 0000000 00000013163 13060565304 0031517 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2016 Fritz Elfert
*
* 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 junit.framework.Assert.*;
import jnr.ffi.Platform;
import jnr.ffi.Platform.OS;
import org.junit.Assume;
import org.junit.Test;
public class ChannelOptionsTest {
@Test
public void readonlyDatagramChannelOptionTest() throws Exception {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
UnixDatagramChannel[] sp = UnixDatagramChannel.pair();
UnixDatagramChannel ch = sp[0];
Credentials c = ch.socket().getCredentials();
try {
// SO_PEERCRED is readonly
ch.setOption(UnixSocketOptions.SO_PEERCRED, c);
fail("Should have thrown AssertionError");
} catch (AssertionError ae) {
assertEquals("exception message", ae.getMessage(), "Option not found or not writable");
}
}
@Test
public void readonlySocketChannelOptionTest() throws Exception {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
UnixSocketChannel[] sp = UnixSocketChannel.pair();
UnixSocketChannel ch = sp[0];
Credentials c = ch.socket().getCredentials();
try {
// SO_PEERCRED is readonly
ch.setOption(UnixSocketOptions.SO_PEERCRED, c);
fail("Should have thrown AssertionError");
} catch (AssertionError ae) {
assertEquals("exception message", ae.getMessage(), "Option not found or not writable");
}
}
@Test
public void unsupportedChannelOptionTest() throws Exception {
UnixDatagramChannel ch = UnixDatagramChannel.open();
try {
// SO_KEEPALIVE is suitable only for SOCK_STREAM sockets
ch.getOption(UnixSocketOptions.SO_KEEPALIVE);
fail("Should have thrown UnsupportedOperationException");
} catch (UnsupportedOperationException uoe) {
assertEquals("exception message", uoe.getMessage(), "'SO_KEEPALIVE' not supported");
}
}
@Test
public void keepaliveOptionTest() throws Exception {
UnixSocketChannel ch = UnixSocketChannel.open();
boolean origValue = ch.getOption(UnixSocketOptions.SO_KEEPALIVE).booleanValue();
assertEquals("Initial value of SO_KEEPALIVE", origValue, false);
ch.setOption(UnixSocketOptions.SO_KEEPALIVE, Boolean.TRUE);
boolean changedValue = ch.getOption(UnixSocketOptions.SO_KEEPALIVE).booleanValue();
assertEquals("Changed value of SO_KEEPALIVE", changedValue, true);
ch.setOption(UnixSocketOptions.SO_KEEPALIVE, Boolean.FALSE);
changedValue = ch.getOption(UnixSocketOptions.SO_KEEPALIVE).booleanValue();
assertEquals("Changed value of SO_KEEPALIVE", changedValue, origValue);
}
@Test
public void invalidOptionValueTest() throws Exception {
UnixSocketChannel ch = UnixSocketChannel.open();
try {
ch.setOption(UnixSocketOptions.SO_RCVTIMEO, Integer.valueOf(-1));
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException iae) {
assertEquals("exception message", iae.getMessage(), "Invalid send/receive timeout");
}
try {
ch.setOption(UnixSocketOptions.SO_SNDTIMEO, Integer.valueOf(-1));
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException iae) {
assertEquals("exception message", iae.getMessage(), "Invalid send/receive timeout");
}
try {
ch.setOption(UnixSocketOptions.SO_RCVBUF, Integer.valueOf(-1));
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException iae) {
assertEquals("exception message", iae.getMessage(), "Invalid send/receive buffer size");
}
try {
ch.setOption(UnixSocketOptions.SO_SNDBUF, Integer.valueOf(-1));
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException iae) {
assertEquals("exception message", iae.getMessage(), "Invalid send/receive buffer size");
}
}
@Test
// Linux doubles the values when setting.
// OSX keeps settings consistent but restricts possible values to a multiple of 256
// Check what other platforms do.
public void socketBufferTest() throws Exception {
UnixDatagramChannel ch = UnixDatagramChannel.open();
int rxs = ch.getOption(UnixSocketOptions.SO_RCVBUF);
int txs = ch.getOption(UnixSocketOptions.SO_SNDBUF);
assertTrue("receive buffer size >= 256", rxs >= 256);
assertTrue("send buffer size >= 256", txs >= 256);
/*
System.out.println(String.format("rxbuf=%d, txbuf=%d", rxs, txs));
ch.setOption(UnixSocketOptions.SO_RCVBUF, rxs - 100);
ch.setOption(UnixSocketOptions.SO_SNDBUF, txs - 100);
rxs = ch.getOption(UnixSocketOptions.SO_RCVBUF);
txs = ch.getOption(UnixSocketOptions.SO_SNDBUF);
System.out.println(String.format("rxbuf=%d, txbuf=%d", rxs, txs));
*/
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/CredentialsFunctionalTest.java 0000664 0000000 0000000 00000011205 13060565304 0033046 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.socket().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());
// Verify, that results from new interface are the same
Credentials newCreds = client.getOption(UnixSocketOptions.SO_PEERCRED);
assertNotNull(newCreds);
assertEquals("Current PID should match new API PID",
myPid, newCreds.getPid());
assertEquals("old/new API results (UID) should be the same",
clientCreds.getUid(), newCreds.getUid());
assertEquals("old/new API results (GID) should be the same",
clientCreds.getGid(), newCreds.getGid());
}
public int getCurrentPid() {
String[] nameParts = ManagementFactory.getRuntimeMXBean().getName().split("@", 2);
assertEquals("Cannot determine PID", 2, nameParts.length);
return Integer.parseInt(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.parseInt(uidText.toString());
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/ForFDTest.java 0000664 0000000 0000000 00000004561 13060565304 0027535 0 ustar 00root root 0000000 0000000 package jnr.unixsocket;
import jnr.constants.platform.ProtocolFamily;
import jnr.constants.platform.Sock;
import org.junit.Test;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
/**
* Created by headius on 11/24/15.
*/
public class ForFDTest {
private static final File SOCKADDR = new File("/tmp/jnr-unixsocket-forfd" + System.currentTimeMillis() + ".sock");
static { SOCKADDR.deleteOnExit(); }
private static final UnixSocketAddress ADDRESS = new UnixSocketAddress(SOCKADDR);
private static final String FOOBAR = "foobar";
private volatile Exception serverException;
@Test
public void testForFD() throws Exception {
int fd = 0;
UnixSocketChannel channel = null;
try {
final UnixServerSocketChannel server = UnixServerSocketChannel.open();
server.socket().bind(ADDRESS);
new Thread("accept thread") {
public void run() {
UnixSocketChannel channel = null;
try {
channel = server.accept();
channel.write(ByteBuffer.wrap(FOOBAR.getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
serverException = e;
} finally {
try {channel.close();} catch (Exception e) {}
}
}
}.start();
fd = Native.socket(ProtocolFamily.PF_UNIX, Sock.SOCK_STREAM, 0);
assertTrue("socket failed", fd > 0);
int ret = Native.connect(fd, ADDRESS.getStruct(), ADDRESS.getStruct().length());
assertTrue("connect failed", ret >= 0);
channel = UnixSocketChannel.fromFD(fd);
assertNotNull(channel);
ByteBuffer buf = ByteBuffer.allocate(1024);
channel.read(buf);
assertEquals(FOOBAR.length(), buf.position());
buf.flip();
String result = new String(buf.array(), buf.position(), buf.limit(), "UTF-8");
assertEquals(FOOBAR, result);
if (serverException != null) throw serverException;
} finally {
channel.close();
}
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/UnixDatagramChannelTest.java 0000664 0000000 0000000 00000004474 13060565304 0032455 0 ustar 00root root 0000000 0000000 package jnr.unixsocket;
import java.io.File;
import java.nio.file.Files;
import java.util.regex.Pattern;
import org.junit.Test;
import org.junit.Assume;
import static junit.framework.Assert.*;
import jnr.ffi.Platform;
import jnr.ffi.Platform.OS;
public class UnixDatagramChannelTest {
@Test
public void testForUnnamedSockets() throws Exception {
UnixDatagramChannel[] sp = UnixDatagramChannel.pair();
// getpeername check
assertEquals("remote socket path", "", sp[0].getRemoteSocketAddress().path());
assertEquals("remote socket path", "", sp[1].getRemoteSocketAddress().path());
// getsockname check
assertEquals("local socket path", "", sp[0].getLocalSocketAddress().path());
assertEquals("local socket path", "", sp[1].getLocalSocketAddress().path());
}
@Test
public void testAutobind() throws Exception {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
// see http://man7.org/linux/man-pages/man7/unix.7.html
final String RE = "^\\000([0-9a-f]){5}$";
UnixDatagramChannel ch = UnixDatagramChannel.open();
ch.bind(null);
UnixSocketAddress a = ch.getLocalSocketAddress();
assertTrue("socket path pattern matches " + RE, a.path().matches(RE));
}
@Test
public void testAutobindEmulation() throws Exception {
Assume.assumeTrue(OS.LINUX != Platform.getNativePlatform().getOS());
File f = Files.createTempFile("jnr-unixsocket-tmp", ".end").toFile();
f.delete();
String path = f.getPath().replaceAll("-tmp.*\\.end", "-tmp");
final String RE = "^" + Pattern.quote(path) + ".*\\.sock$";
UnixDatagramChannel ch = UnixDatagramChannel.open();
ch.bind(null);
UnixSocketAddress a = ch.getLocalSocketAddress();
assertTrue("socket path pattern matches " + RE, a.path().matches(RE));
}
@Test
public void testAbstractNamespace() throws Exception {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
final String ABSTRACT = "\000foobarbaz";
UnixSocketAddress a = new UnixSocketAddress(ABSTRACT);
UnixDatagramChannel ch = UnixDatagramChannel.open();
ch.bind(a);
assertEquals("local socket path", ABSTRACT, ch.getLocalSocketAddress().path());
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/UnixSocketChannelTest.java 0000664 0000000 0000000 00000003171 13060565304 0032156 0 ustar 00root root 0000000 0000000 package jnr.unixsocket;
import org.junit.Test;
import org.junit.Assume;
import static junit.framework.Assert.*;
import jnr.ffi.Platform;
import jnr.ffi.Platform.OS;
public class UnixSocketChannelTest {
@Test
public void testForUnnamedSockets() throws Exception {
UnixSocketChannel[] sp = UnixSocketChannel.pair();
// getpeername check
assertEquals("remote socket path", "", sp[0].getRemoteSocketAddress().path());
assertEquals("remote socket path", "", sp[1].getRemoteSocketAddress().path());
// getsockname check
assertEquals("local socket path", "", sp[0].getLocalSocketAddress().path());
assertEquals("local socket path", "", sp[1].getLocalSocketAddress().path());
}
@Test
public void testAutobind() throws Exception {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
// see http://man7.org/linux/man-pages/man7/unix.7.html
final String RE = "^\\000([0-9a-f]){5}$";
UnixSocketChannel ch = UnixSocketChannel.open();
ch.bind(null);
UnixSocketAddress a = ch.getLocalSocketAddress();
assertTrue("socket path pattern matches " + RE, a.path().matches(RE));
}
@Test
public void testAbstractNamespace() throws Exception {
Assume.assumeTrue(OS.LINUX == Platform.getNativePlatform().getOS());
final String ABSTRACT = "\000foobarbaz";
UnixSocketAddress a = new UnixSocketAddress(ABSTRACT);
UnixSocketChannel ch = UnixSocketChannel.open();
ch.bind(a);
assertEquals("local socket path", ABSTRACT, ch.getLocalSocketAddress().path());
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/example/ 0000775 0000000 0000000 00000000000 13060565304 0026517 5 ustar 00root root 0000000 0000000 jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/example/LocalSyslogClient.java 0000664 0000000 0000000 00000010567 13060565304 0032765 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.example;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import jnr.unixsocket.UnixSocketAddress;
import jnr.unixsocket.UnixDatagramChannel;
import jnr.ffi.Platform;
import jnr.ffi.Platform.OS;
import java.lang.management.ManagementFactory;
public class LocalSyslogClient {
private StringBuffer line = new StringBuffer();
private SimpleDateFormat sdf = new SimpleDateFormat("MMM dd HH:mm:ss", Locale.US);
private String formatDate() {
synchronized(this) {
return sdf.format(new Date());
}
}
private void formatLine(final int pri, final String tag, final int pid, final String[] args) {
line.setLength(0);
line.append(String.format("<%d>", pri))
.append(formatDate())
.append(" ")
.append(tag);
if (0 < pid) {
line.append(String.format("[%d]", pid));
}
line.append(":");
for (String arg : args) {
line.append(" ").append(arg);
}
}
private enum Priority {
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG;
}
private enum Facility {
LOG_KERN(0 << 3),
LOG_USER(1 << 3),
LOG_MAIL(2 << 3),
LOG_DAEMON(3 << 3),
LOG_AUTH(4 << 3),
LOG_SYSLOG(5 << 3),
LOG_LPR(6 << 3),
LOG_NEWS(7 << 3),
LOG_UUCP(8 << 3),
LOG_CRON(9 << 3),
LOG_AUTHPRIV(10 << 3),
LOG_FTP(11 << 3),
LOG_LOCAL0(16 << 3),
LOG_LOCAL1(17 << 3),
LOG_LOCAL2(18 << 3),
LOG_LOCAL3(19 << 3),
LOG_LOCAL4(20 << 3),
LOG_LOCAL5(21 << 3),
LOG_LOCAL6(22 << 3),
LOG_LOCAL7(23 << 3);
private int myValue;
Facility(int value) {
myValue = value;
}
public int getValue() {
return myValue;
}
}
private int makePri(Priority priority, Facility facility) {
return priority.ordinal() | facility.getValue();
}
private String getSocketPath() {
if (Platform.getNativePlatform().getOS() == OS.DARWIN) {
return "/var/run/syslog";
}
return "/dev/log";
}
private int getPid() {
String[] nameParts = ManagementFactory.getRuntimeMXBean().getName().split("@", 2);
if (2 == nameParts.length) {
return Integer.parseInt(nameParts[0]);
}
return 0;
}
private void doit(String[] args) throws IOException, InterruptedException {
java.io.File path = new java.io.File(getSocketPath());
if (!path.exists()) {
throw new IOException(String.format("%s does not exist", path.getAbsolutePath()));
}
UnixSocketAddress address = new UnixSocketAddress(path);
UnixDatagramChannel channel = UnixDatagramChannel.open();
int pri = makePri(Priority.LOG_WARNING, Facility.LOG_DAEMON);
int pid = getPid();
String tag = "whatever";
if (args.length > 0) {
formatLine(pri, tag, pid, args);
ByteBuffer buf = ByteBuffer.wrap(line.toString().getBytes(StandardCharsets.UTF_8));
channel.send(buf, address);
} else {
formatLine(pri, tag, pid, new String[]{"The quick brown fox jumps\nover the lazy dog"});
ByteBuffer buf = ByteBuffer.wrap(line.toString().getBytes(StandardCharsets.UTF_8));
channel.send(buf, address);
}
}
public static void main(String[] args) throws IOException, InterruptedException {
LocalSyslogClient client = new LocalSyslogClient();
client.doit(args);
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/example/UnixClient.java 0000664 0000000 0000000 00000004552 13060565304 0031452 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.example;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.CharBuffer;
import java.nio.channels.Channels;
import java.util.concurrent.TimeUnit;
import jnr.unixsocket.UnixSocketAddress;
import jnr.unixsocket.UnixSocketChannel;
public class UnixClient {
public static void main(String[] args) throws IOException, InterruptedException {
java.io.File path = new java.io.File("/tmp/fubar.sock");
int retries = 0;
while (!path.exists()) {
TimeUnit.MILLISECONDS.sleep(500L);
retries++;
if (retries > 10) {
throw new IOException(
String.format(
"File %s does not exist after retry",
path.getAbsolutePath()
)
);
}
}
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());
final int status;
if (!result.toString().equals(data)) {
System.out.println("ERROR: data mismatch");
status = -1;
} else {
System.out.println("SUCCESS");
status = 0;
}
System.exit(status);
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/java/jnr/unixsocket/example/UnixServer.java 0000664 0000000 0000000 00000010507 13060565304 0031477 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.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.Iterator;
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();
Iterator iterator = keys.iterator();
boolean running = false;
boolean cancelled = false;
while ( iterator.hasNext() ) {
SelectionKey k = iterator.next();
Actor a = (Actor) k.attachment();
if (a.rxready()) {
running = true;
} else {
k.cancel();
cancelled = true;
}
iterator.remove();
}
if (!running && cancelled) {
System.out.println("No Actors Running any more");
break;
}
}
} catch (IOException ex) {
Logger.getLogger(UnixServerSocket.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("UnixServer EXIT");
}
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;
}
}
}
jnr-unixsocket-jnr-unixsocket-0.18/src/test/resources/ 0000775 0000000 0000000 00000000000 13060565304 0023170 5 ustar 00root root 0000000 0000000 jnr-unixsocket-jnr-unixsocket-0.18/src/test/resources/background.sh 0000775 0000000 0000000 00000000054 13060565304 0025645 0 ustar 00root root 0000000 0000000 #!/bin/sh
$* > background.log 2>&1 &
exit 0