jnr.unixsocket.Native Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jnr-unixsocket Show documentation
Show all versions of jnr-unixsocket Show documentation
UNIX socket channels for java
/*
* 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.nativeOrder());
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.nativeOrder());
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;
}
}