Add support to wrap an existing filedescriptor when using native kqueue transport

Motivation:

The native epoll transport allows to wrap an existing filedescriptor, we should support the same in the native kqueue transport.

Modifications:

Add constructors that allow to wrap and existing filedescriptor.

Result:

Featureset of native transports more on par.
This commit is contained in:
Norman Maurer 2017-05-19 08:07:33 +02:00
parent 201d9b6536
commit 61b1165136
8 changed files with 53 additions and 0 deletions

View File

@ -22,6 +22,7 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.AbstractChannel;
import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelMetadata;
import io.netty.channel.EventLoop;
import io.netty.channel.RecvByteBufAllocator;
@ -68,6 +69,14 @@ abstract class AbstractKQueueChannel extends AbstractChannel implements UnixChan
this.writeFilterEnabled = writeFilterEnabled;
}
static boolean isSoErrorZero(BsdSocket fd) {
try {
return fd.getSoError() == 0;
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public final FileDescriptor fd() {
return socket;

View File

@ -32,6 +32,10 @@ import java.net.SocketAddress;
public abstract class AbstractKQueueServerChannel extends AbstractKQueueChannel implements ServerChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
AbstractKQueueServerChannel(BsdSocket fd) {
this(fd, isSoErrorZero(fd));
}
AbstractKQueueServerChannel(BsdSocket fd, boolean active) {
super(null, fd, active);
}

View File

@ -68,6 +68,10 @@ public abstract class AbstractKQueueStreamChannel extends AbstractKQueueChannel
super(parent, fd, active, true);
}
AbstractKQueueStreamChannel(BsdSocket fd) {
this(null, fd, isSoErrorZero(fd));
}
@Override
protected AbstractKQueueUnsafe newUnsafe() {
return new KQueueStreamUnsafe();

View File

@ -68,6 +68,10 @@ public final class KQueueDatagramChannel extends AbstractKQueueChannel implement
config = new KQueueDatagramChannelConfig(this);
}
public KQueueDatagramChannel(int fd) {
this(new BsdSocket(fd), true);
}
KQueueDatagramChannel(BsdSocket socket, boolean active) {
super(null, socket, active);
config = new KQueueDatagramChannelConfig(this);

View File

@ -41,6 +41,10 @@ public final class KQueueDomainSocketChannel extends AbstractKQueueStreamChannel
super(null, newSocketDomain(), false);
}
public KQueueDomainSocketChannel(int fd) {
this(null, new BsdSocket(fd));
}
KQueueDomainSocketChannel(Channel parent, BsdSocket fd) {
super(parent, fd, true);
}

View File

@ -40,6 +40,10 @@ public final class KQueueServerDomainSocketChannel extends AbstractKQueueServerC
super(newSocketDomain(), false);
}
public KQueueServerDomainSocketChannel(int fd) {
this(new BsdSocket(fd), false);
}
KQueueServerDomainSocketChannel(BsdSocket socket, boolean active) {
super(socket, active);
}

View File

@ -36,6 +36,21 @@ public final class KQueueServerSocketChannel extends AbstractKQueueServerChannel
config = new KQueueServerSocketChannelConfig(this);
}
public KQueueServerSocketChannel(int fd) {
// Must call this constructor to ensure this object's local address is configured correctly.
// The local address can only be obtained from a Socket object.
this(new BsdSocket(fd));
}
KQueueServerSocketChannel(BsdSocket fd) {
super(fd);
config = new KQueueServerSocketChannelConfig(this);
// As we create an KQueueServerSocketChannel from a FileDescriptor we should try to obtain the remote and local
// address from it. This is needed as the FileDescriptor may be bound already.
local = fd.localAddress();
}
KQueueServerSocketChannel(BsdSocket fd, boolean active) {
super(fd, active);
config = new KQueueServerSocketChannelConfig(this);

View File

@ -42,6 +42,15 @@ public final class KQueueSocketChannel extends AbstractKQueueStreamChannel imple
config = new KQueueSocketChannelConfig(this);
}
public KQueueSocketChannel(int fd) {
super(new BsdSocket(fd));
// As we create an EpollSocketChannel from a FileDescriptor we should try to obtain the remote and local
// address from it. This is needed as the FileDescriptor may be bound/connected already.
remote = socket.remoteAddress();
local = socket.localAddress();
config = new KQueueSocketChannelConfig(this);
}
KQueueSocketChannel(Channel parent, BsdSocket fd, InetSocketAddress remote) {
super(parent, fd, true);
config = new KQueueSocketChannelConfig(this);