ChannelConfig operations should wrap ClosedChannelException if Channel was closed before.

Motivation:

To be consistent with the JDK we should ensure our native methods throw a ClosedChannelException if the Channel was previously closed. This will then be wrapped in a ChannelException as usual. For all other errors we continue to just throw a ChannelException directly.

Modifications:

Ensure getsockopt and setsockopt will throw a ClosedChannelException if the channel was closed before, on other errors we throw a ChannelException as before diretly.

Result:

Consistent with the NIO Channel implementations.
This commit is contained in:
Norman Maurer 2016-03-15 10:38:25 +01:00
parent dcf553f1aa
commit 1090d7200d
11 changed files with 385 additions and 126 deletions

View File

@ -296,7 +296,12 @@ static jobject _recvFrom(JNIEnv* env, jint fd, void* buffer, jint pos, jint limi
int netty_unix_socket_getOption(JNIEnv* env, jint fd, int level, int optname, void* optval, socklen_t optlen) { int netty_unix_socket_getOption(JNIEnv* env, jint fd, int level, int optname, void* optval, socklen_t optlen) {
int rc = getsockopt(fd, level, optname, optval, &optlen); int rc = getsockopt(fd, level, optname, optval, &optlen);
if (rc < 0) { if (rc < 0) {
netty_unix_errors_throwChannelExceptionErrorNo(env, "getsockopt() failed: ", errno); int err = errno;
if (err == EBADF) {
netty_unix_errors_throwClosedChannelException(env);
} else {
netty_unix_errors_throwChannelExceptionErrorNo(env, "setsockopt() failed: ", err);
}
} }
return rc; return rc;
} }
@ -304,7 +309,12 @@ int netty_unix_socket_getOption(JNIEnv* env, jint fd, int level, int optname, vo
int netty_unix_socket_setOption(JNIEnv* env, jint fd, int level, int optname, const void* optval, socklen_t len) { int netty_unix_socket_setOption(JNIEnv* env, jint fd, int level, int optname, const void* optval, socklen_t len) {
int rc = setsockopt(fd, level, optname, optval, len); int rc = setsockopt(fd, level, optname, optval, len);
if (rc < 0) { if (rc < 0) {
netty_unix_errors_throwChannelExceptionErrorNo(env, "setsockopt() failed: ", errno); int err = errno;
if (err == EBADF) {
netty_unix_errors_throwClosedChannelException(env);
} else {
netty_unix_errors_throwChannelExceptionErrorNo(env, "setsockopt() failed: ", err);
}
} }
return rc; return rc;
} }

View File

@ -16,12 +16,14 @@
package io.netty.channel.epoll; package io.netty.channel.epoll;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator; import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.MessageSizeEstimator; import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramChannelConfig;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.util.Map; import java.util.Map;
@ -191,57 +193,97 @@ public final class EpollDatagramChannelConfig extends EpollChannelConfig impleme
@Override @Override
public int getSendBufferSize() { public int getSendBufferSize() {
return datagramChannel.fd().getSendBufferSize(); try {
return datagramChannel.fd().getSendBufferSize();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollDatagramChannelConfig setSendBufferSize(int sendBufferSize) { public EpollDatagramChannelConfig setSendBufferSize(int sendBufferSize) {
datagramChannel.fd().setSendBufferSize(sendBufferSize); try {
return this; datagramChannel.fd().setSendBufferSize(sendBufferSize);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public int getReceiveBufferSize() { public int getReceiveBufferSize() {
return datagramChannel.fd().getReceiveBufferSize(); try {
return datagramChannel.fd().getReceiveBufferSize();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) { public EpollDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) {
datagramChannel.fd().setReceiveBufferSize(receiveBufferSize); try {
return this; datagramChannel.fd().setReceiveBufferSize(receiveBufferSize);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public int getTrafficClass() { public int getTrafficClass() {
return Native.getTrafficClass(datagramChannel.fd().intValue()); try {
return Native.getTrafficClass(datagramChannel.fd().intValue());
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollDatagramChannelConfig setTrafficClass(int trafficClass) { public EpollDatagramChannelConfig setTrafficClass(int trafficClass) {
Native.setTrafficClass(datagramChannel.fd().intValue(), trafficClass); try {
return this; Native.setTrafficClass(datagramChannel.fd().intValue(), trafficClass);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public boolean isReuseAddress() { public boolean isReuseAddress() {
return Native.isReuseAddress(datagramChannel.fd().intValue()) == 1; try {
return Native.isReuseAddress(datagramChannel.fd().intValue()) == 1;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollDatagramChannelConfig setReuseAddress(boolean reuseAddress) { public EpollDatagramChannelConfig setReuseAddress(boolean reuseAddress) {
Native.setReuseAddress(datagramChannel.fd().intValue(), reuseAddress ? 1 : 0); try {
return this; Native.setReuseAddress(datagramChannel.fd().intValue(), reuseAddress ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public boolean isBroadcast() { public boolean isBroadcast() {
return Native.isBroadcast(datagramChannel.fd().intValue()) == 1; try {
return Native.isBroadcast(datagramChannel.fd().intValue()) == 1;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollDatagramChannelConfig setBroadcast(boolean broadcast) { public EpollDatagramChannelConfig setBroadcast(boolean broadcast) {
Native.setBroadcast(datagramChannel.fd().intValue(), broadcast ? 1 : 0); try {
return this; Native.setBroadcast(datagramChannel.fd().intValue(), broadcast ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
@ -294,7 +336,11 @@ public final class EpollDatagramChannelConfig extends EpollChannelConfig impleme
* Returns {@code true} if the SO_REUSEPORT option is set. * Returns {@code true} if the SO_REUSEPORT option is set.
*/ */
public boolean isReusePort() { public boolean isReusePort() {
return Native.isReusePort(datagramChannel.fd().intValue()) == 1; try {
return Native.isReusePort(datagramChannel.fd().intValue()) == 1;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -305,7 +351,11 @@ public final class EpollDatagramChannelConfig extends EpollChannelConfig impleme
* any affect. * any affect.
*/ */
public EpollDatagramChannelConfig setReusePort(boolean reusePort) { public EpollDatagramChannelConfig setReusePort(boolean reusePort) {
Native.setReusePort(datagramChannel.fd().intValue(), reusePort ? 1 : 0); try {
return this; Native.setReusePort(datagramChannel.fd().intValue(), reusePort ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
} }

View File

@ -16,11 +16,13 @@
package io.netty.channel.epoll; package io.netty.channel.epoll;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator; import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.util.NetUtil; import io.netty.util.NetUtil;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import static io.netty.channel.ChannelOption.SO_BACKLOG; import static io.netty.channel.ChannelOption.SO_BACKLOG;
@ -80,21 +82,37 @@ public class EpollServerChannelConfig extends EpollChannelConfig {
} }
public boolean isReuseAddress() { public boolean isReuseAddress() {
return Native.isReuseAddress(channel.fd().intValue()) == 1; try {
return Native.isReuseAddress(channel.fd().intValue()) == 1;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
public EpollServerChannelConfig setReuseAddress(boolean reuseAddress) { public EpollServerChannelConfig setReuseAddress(boolean reuseAddress) {
Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0); try {
return this; Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
public int getReceiveBufferSize() { public int getReceiveBufferSize() {
return channel.fd().getReceiveBufferSize(); try {
return channel.fd().getReceiveBufferSize();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
public EpollServerChannelConfig setReceiveBufferSize(int receiveBufferSize) { public EpollServerChannelConfig setReceiveBufferSize(int receiveBufferSize) {
channel.fd().setReceiveBufferSize(receiveBufferSize); try {
return this; channel.fd().setReceiveBufferSize(receiveBufferSize);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
public int getBacklog() { public int getBacklog() {

View File

@ -21,6 +21,7 @@ import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.unix.FileDescriptor; import io.netty.channel.unix.FileDescriptor;
import io.netty.channel.unix.Socket; import io.netty.channel.unix.Socket;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -125,7 +126,7 @@ public final class EpollServerSocketChannel extends AbstractEpollServerChannel i
return tcpMd5SigAddresses; return tcpMd5SigAddresses;
} }
void setTcpMd5Sig(Map<InetAddress, byte[]> keys) { void setTcpMd5Sig(Map<InetAddress, byte[]> keys) throws IOException {
this.tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys); this.tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys);
} }
} }

View File

@ -16,11 +16,13 @@
package io.netty.channel.epoll; package io.netty.channel.epoll;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator; import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.socket.ServerSocketChannelConfig; import io.netty.channel.socket.ServerSocketChannelConfig;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Map; import java.util.Map;
@ -161,15 +163,23 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf
* Allowing them being read would mean anyone with access to the channel could get them. * Allowing them being read would mean anyone with access to the channel could get them.
*/ */
public EpollServerSocketChannelConfig setTcpMd5Sig(Map<InetAddress, byte[]> keys) { public EpollServerSocketChannelConfig setTcpMd5Sig(Map<InetAddress, byte[]> keys) {
((EpollServerSocketChannel) channel).setTcpMd5Sig(keys); try {
return this; ((EpollServerSocketChannel) channel).setTcpMd5Sig(keys);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Returns {@code true} if the SO_REUSEPORT option is set. * Returns {@code true} if the SO_REUSEPORT option is set.
*/ */
public boolean isReusePort() { public boolean isReusePort() {
return Native.isReusePort(channel.fd().intValue()) == 1; try {
return Native.isReusePort(channel.fd().intValue()) == 1;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -180,8 +190,12 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf
* any affect. * any affect.
*/ */
public EpollServerSocketChannelConfig setReusePort(boolean reusePort) { public EpollServerSocketChannelConfig setReusePort(boolean reusePort) {
Native.setReusePort(channel.fd().intValue(), reusePort ? 1 : 0); try {
return this; Native.setReusePort(channel.fd().intValue(), reusePort ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -189,7 +203,11 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf
* {@code false} otherwise. * {@code false} otherwise.
*/ */
public boolean isFreeBind() { public boolean isFreeBind() {
return Native.isIpFreeBind(channel.fd().intValue()) != 0; try {
return Native.isIpFreeBind(channel.fd().intValue()) != 0;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -197,22 +215,34 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf
* {@code false} for disable it. Default is disabled. * {@code false} for disable it. Default is disabled.
*/ */
public EpollServerSocketChannelConfig setFreeBind(boolean freeBind) { public EpollServerSocketChannelConfig setFreeBind(boolean freeBind) {
Native.setIpFreeBind(channel.fd().intValue(), freeBind ? 1: 0); try {
return this; Native.setIpFreeBind(channel.fd().intValue(), freeBind ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Set the {@code TCP_DEFER_ACCEPT} option on the socket. See {@code man 7 tcp} for more details. * Set the {@code TCP_DEFER_ACCEPT} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public EpollServerSocketChannelConfig setTcpDeferAccept(int deferAccept) { public EpollServerSocketChannelConfig setTcpDeferAccept(int deferAccept) {
channel.fd().setTcpDeferAccept(deferAccept); try {
return this; channel.fd().setTcpDeferAccept(deferAccept);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Returns a positive value if <a href="http://linux.die.net/man/7/tcp">TCP_DEFER_ACCEPT</a> is enabled. * Returns a positive value if <a href="http://linux.die.net/man/7/tcp">TCP_DEFER_ACCEPT</a> is enabled.
*/ */
public int getTcpDeferAccept() { public int getTcpDeferAccept() {
return channel.fd().getTcpDeferAccept(); try {
return channel.fd().getTcpDeferAccept();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
} }

View File

@ -16,6 +16,7 @@
package io.netty.channel.epoll; package io.netty.channel.epoll;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import io.netty.channel.unix.FileDescriptor; import io.netty.channel.unix.FileDescriptor;
@ -23,6 +24,7 @@ import io.netty.channel.unix.Socket;
import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -103,8 +105,12 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme
* See <a href="http://linux.die.net/man/7/tcp">man 7 tcp</a>. * See <a href="http://linux.die.net/man/7/tcp">man 7 tcp</a>.
*/ */
public EpollTcpInfo tcpInfo(EpollTcpInfo info) { public EpollTcpInfo tcpInfo(EpollTcpInfo info) {
Native.tcpInfo(fd().intValue(), info); try {
return info; Native.tcpInfo(fd().intValue(), info);
return info;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
@ -223,7 +229,7 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme
} }
} }
void setTcpMd5Sig(Map<InetAddress, byte[]> keys) { void setTcpMd5Sig(Map<InetAddress, byte[]> keys) throws IOException {
this.tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys); this.tcpMd5SigAddresses = TcpMd5Util.newTcpMd5Sigs(this, tcpMd5SigAddresses, keys);
} }
} }

View File

@ -16,12 +16,14 @@
package io.netty.channel.epoll; package io.netty.channel.epoll;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator; import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator; import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.socket.SocketChannelConfig; import io.netty.channel.socket.SocketChannelConfig;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Map; import java.util.Map;
@ -152,44 +154,76 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
@Override @Override
public int getReceiveBufferSize() { public int getReceiveBufferSize() {
return channel.fd().getReceiveBufferSize(); try {
return channel.fd().getReceiveBufferSize();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public int getSendBufferSize() { public int getSendBufferSize() {
return channel.fd().getSendBufferSize(); try {
return channel.fd().getSendBufferSize();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public int getSoLinger() { public int getSoLinger() {
return channel.fd().getSoLinger(); try {
return channel.fd().getSoLinger();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public int getTrafficClass() { public int getTrafficClass() {
return Native.getTrafficClass(channel.fd().intValue()); try {
return Native.getTrafficClass(channel.fd().intValue());
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public boolean isKeepAlive() { public boolean isKeepAlive() {
return channel.fd().isKeepAlive(); try {
return channel.fd().isKeepAlive();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public boolean isReuseAddress() { public boolean isReuseAddress() {
return Native.isReuseAddress(channel.fd().intValue()) == 1; try {
return Native.isReuseAddress(channel.fd().intValue()) == 1;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public boolean isTcpNoDelay() { public boolean isTcpNoDelay() {
return channel.fd().isTcpNoDelay(); try {
return channel.fd().isTcpNoDelay();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Get the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details. * Get the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public boolean isTcpCork() { public boolean isTcpCork() {
return channel.fd().isTcpCork(); try {
return channel.fd().isTcpCork();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -197,41 +231,65 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
* @return value is a uint32_t * @return value is a uint32_t
*/ */
public long getTcpNotSentLowAt() { public long getTcpNotSentLowAt() {
return Native.getTcpNotSentLowAt(channel.fd().intValue()) & MAX_UINT32_T; try {
return Native.getTcpNotSentLowAt(channel.fd().intValue()) & MAX_UINT32_T;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Get the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details. * Get the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public int getTcpKeepIdle() { public int getTcpKeepIdle() {
return Native.getTcpKeepIdle(channel.fd().intValue()); try {
return Native.getTcpKeepIdle(channel.fd().intValue());
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Get the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details. * Get the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public int getTcpKeepIntvl() { public int getTcpKeepIntvl() {
return Native.getTcpKeepIntvl(channel.fd().intValue()); try {
return Native.getTcpKeepIntvl(channel.fd().intValue());
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Get the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details. * Get the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public int getTcpKeepCnt() { public int getTcpKeepCnt() {
return Native.getTcpKeepCnt(channel.fd().intValue()); try {
return Native.getTcpKeepCnt(channel.fd().intValue());
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Get the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details. * Get the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public int getTcpUserTimeout() { public int getTcpUserTimeout() {
try {
return Native.getTcpUserTimeout(channel.fd().intValue()); return Native.getTcpUserTimeout(channel.fd().intValue());
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) { public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) {
channel.fd().setKeepAlive(keepAlive); try {
return this; channel.fd().setKeepAlive(keepAlive);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
@ -242,40 +300,64 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
@Override @Override
public EpollSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) { public EpollSocketChannelConfig setReceiveBufferSize(int receiveBufferSize) {
channel.fd().setReceiveBufferSize(receiveBufferSize); try {
return this; channel.fd().setReceiveBufferSize(receiveBufferSize);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollSocketChannelConfig setReuseAddress(boolean reuseAddress) { public EpollSocketChannelConfig setReuseAddress(boolean reuseAddress) {
Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0); try {
return this; Native.setReuseAddress(channel.fd().intValue(), reuseAddress ? 1 : 0);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollSocketChannelConfig setSendBufferSize(int sendBufferSize) { public EpollSocketChannelConfig setSendBufferSize(int sendBufferSize) {
channel.fd().setSendBufferSize(sendBufferSize); try {
return this; channel.fd().setSendBufferSize(sendBufferSize);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollSocketChannelConfig setSoLinger(int soLinger) { public EpollSocketChannelConfig setSoLinger(int soLinger) {
channel.fd().setSoLinger(soLinger); try {
return this; channel.fd().setSoLinger(soLinger);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) { public EpollSocketChannelConfig setTcpNoDelay(boolean tcpNoDelay) {
channel.fd().setTcpNoDelay(tcpNoDelay); try {
return this; channel.fd().setTcpNoDelay(tcpNoDelay);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Set the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details. * Set the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public EpollSocketChannelConfig setTcpCork(boolean tcpCork) { public EpollSocketChannelConfig setTcpCork(boolean tcpCork) {
channel.fd().setTcpCork(tcpCork); try {
return this; channel.fd().setTcpCork(tcpCork);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -286,46 +368,70 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) { if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) {
throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t"); throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t");
} }
Native.setTcpNotSentLowAt(channel.fd().intValue(), (int) tcpNotSentLowAt); try {
return this; Native.setTcpNotSentLowAt(channel.fd().intValue(), (int) tcpNotSentLowAt);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override
public EpollSocketChannelConfig setTrafficClass(int trafficClass) { public EpollSocketChannelConfig setTrafficClass(int trafficClass) {
Native.setTrafficClass(channel.fd().intValue(), trafficClass); try {
return this; Native.setTrafficClass(channel.fd().intValue(), trafficClass);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Set the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details. * Set the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public EpollSocketChannelConfig setTcpKeepIdle(int seconds) { public EpollSocketChannelConfig setTcpKeepIdle(int seconds) {
Native.setTcpKeepIdle(channel.fd().intValue(), seconds); try {
return this; Native.setTcpKeepIdle(channel.fd().intValue(), seconds);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Set the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details. * Set the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public EpollSocketChannelConfig setTcpKeepIntvl(int seconds) { public EpollSocketChannelConfig setTcpKeepIntvl(int seconds) {
Native.setTcpKeepIntvl(channel.fd().intValue(), seconds); try {
return this; Native.setTcpKeepIntvl(channel.fd().intValue(), seconds);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Set the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details. * Set the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public EpollSocketChannelConfig setTcpKeepCntl(int probes) { public EpollSocketChannelConfig setTcpKeepCntl(int probes) {
Native.setTcpKeepCnt(channel.fd().intValue(), probes); try {
return this; Native.setTcpKeepCnt(channel.fd().intValue(), probes);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
* Set the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details. * Set the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details.
*/ */
public EpollSocketChannelConfig setTcpUserTimeout(int milliseconds) { public EpollSocketChannelConfig setTcpUserTimeout(int milliseconds) {
Native.setTcpUserTimeout(channel.fd().intValue(), milliseconds); try {
return this; Native.setTcpUserTimeout(channel.fd().intValue(), milliseconds);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -334,8 +440,12 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
* Allowing them being read would mean anyone with access to the channel could get them. * Allowing them being read would mean anyone with access to the channel could get them.
*/ */
public EpollSocketChannelConfig setTcpMd5Sig(Map<InetAddress, byte[]> keys) { public EpollSocketChannelConfig setTcpMd5Sig(Map<InetAddress, byte[]> keys) {
channel.setTcpMd5Sig(keys); try {
return this; channel.setTcpMd5Sig(keys);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -343,8 +453,12 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
* for more details. * for more details.
*/ */
public EpollSocketChannelConfig setTcpQuickAck(boolean quickAck) { public EpollSocketChannelConfig setTcpQuickAck(boolean quickAck) {
channel.fd().setTcpQuickAck(quickAck); try {
return this; channel.fd().setTcpQuickAck(quickAck);
return this;
} catch (IOException e) {
throw new ChannelException(e);
}
} }
/** /**
@ -352,7 +466,11 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
* {@code false} otherwise. * {@code false} otherwise.
*/ */
public boolean isTcpQuickAck() { public boolean isTcpQuickAck() {
return channel.fd().isTcpQuickAck(); try {
return channel.fd().isTcpQuickAck();
} catch (IOException e) {
throw new ChannelException(e);
}
} }
@Override @Override

View File

@ -208,40 +208,40 @@ public final class Native {
private static native int sendFd0(int socketFd, int fd); private static native int sendFd0(int socketFd, int fd);
// Socket option operations // Socket option operations
public static native int isReuseAddress(int fd); public static native int isReuseAddress(int fd) throws IOException;
public static native int isReusePort(int fd); public static native int isReusePort(int fd) throws IOException;
public static native int getTcpNotSentLowAt(int fd); public static native int getTcpNotSentLowAt(int fd) throws IOException;
public static native int getTrafficClass(int fd); public static native int getTrafficClass(int fd) throws IOException;
public static native int isBroadcast(int fd); public static native int isBroadcast(int fd) throws IOException;
public static native int getTcpKeepIdle(int fd); public static native int getTcpKeepIdle(int fd) throws IOException;
public static native int getTcpKeepIntvl(int fd); public static native int getTcpKeepIntvl(int fd) throws IOException;
public static native int getTcpKeepCnt(int fd); public static native int getTcpKeepCnt(int fd) throws IOException;
public static native int getTcpUserTimeout(int milliseconds); public static native int getTcpUserTimeout(int milliseconds) throws IOException;
public static native int isIpFreeBind(int fd); public static native int isIpFreeBind(int fd)throws IOException;
public static native void setReuseAddress(int fd, int reuseAddress); public static native void setReuseAddress(int fd, int reuseAddress) throws IOException;
public static native void setReusePort(int fd, int reuseAddress); public static native void setReusePort(int fd, int reuseAddress) throws IOException;
public static native void setTcpFastopen(int fd, int tcpFastopenBacklog); public static native void setTcpFastopen(int fd, int tcpFastopenBacklog) throws IOException;
public static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt); public static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt) throws IOException;
public static native void setTrafficClass(int fd, int tcpNoDelay); public static native void setTrafficClass(int fd, int tcpNoDelay) throws IOException;
public static native void setBroadcast(int fd, int broadcast); public static native void setBroadcast(int fd, int broadcast) throws IOException;
public static native void setTcpKeepIdle(int fd, int seconds); public static native void setTcpKeepIdle(int fd, int seconds) throws IOException;
public static native void setTcpKeepIntvl(int fd, int seconds); public static native void setTcpKeepIntvl(int fd, int seconds) throws IOException;
public static native void setTcpKeepCnt(int fd, int probes); public static native void setTcpKeepCnt(int fd, int probes) throws IOException;
public static native void setTcpUserTimeout(int fd, int milliseconds); public static native void setTcpUserTimeout(int fd, int milliseconds)throws IOException;
public static native void setIpFreeBind(int fd, int freeBind); public static native void setIpFreeBind(int fd, int freeBind) throws IOException;
public static void tcpInfo(int fd, EpollTcpInfo info) { public static void tcpInfo(int fd, EpollTcpInfo info) throws IOException {
tcpInfo0(fd, info.info); tcpInfo0(fd, info.info);
} }
private static native void tcpInfo0(int fd, int[] array); private static native void tcpInfo0(int fd, int[] array) throws IOException;
public static void setTcpMd5Sig(int fd, InetAddress address, byte[] key) { public static void setTcpMd5Sig(int fd, InetAddress address, byte[] key) throws IOException {
final NativeInetAddress a = NativeInetAddress.newInstance(address); final NativeInetAddress a = NativeInetAddress.newInstance(address);
setTcpMd5Sig0(fd, a.address(), a.scopeId(), key); setTcpMd5Sig0(fd, a.address(), a.scopeId(), key);
} }
private static native void setTcpMd5Sig0(int fd, byte[] address, int scopeId, byte[] key); private static native void setTcpMd5Sig0(int fd, byte[] address, int scopeId, byte[] key) throws IOException;
// epoll_event related // epoll_event related
public static native int sizeofEpollEvent(); public static native int sizeofEpollEvent();

View File

@ -16,6 +16,8 @@
package io.netty.channel.epoll; package io.netty.channel.epoll;
import io.netty.util.internal.ObjectUtil; import io.netty.util.internal.ObjectUtil;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -26,7 +28,7 @@ import java.util.Map.Entry;
final class TcpMd5Util { final class TcpMd5Util {
static Collection<InetAddress> newTcpMd5Sigs(AbstractEpollChannel channel, Collection<InetAddress> current, static Collection<InetAddress> newTcpMd5Sigs(AbstractEpollChannel channel, Collection<InetAddress> current,
Map<InetAddress, byte[]> newKeys) { Map<InetAddress, byte[]> newKeys) throws IOException {
ObjectUtil.checkNotNull(channel, "channel"); ObjectUtil.checkNotNull(channel, "channel");
ObjectUtil.checkNotNull(current, "current"); ObjectUtil.checkNotNull(current, "current");
ObjectUtil.checkNotNull(newKeys, "newKeys"); ObjectUtil.checkNotNull(newKeys, "newKeys");

View File

@ -239,35 +239,35 @@ public final class Socket extends FileDescriptor {
return address(addr, 0, addr.length); return address(addr, 0, addr.length);
} }
public int getReceiveBufferSize() { public int getReceiveBufferSize() throws IOException {
return getReceiveBufferSize(intValue()); return getReceiveBufferSize(intValue());
} }
public int getSendBufferSize() { public int getSendBufferSize() throws IOException {
return getSendBufferSize(intValue()); return getSendBufferSize(intValue());
} }
public boolean isKeepAlive() { public boolean isKeepAlive() throws IOException {
return isKeepAlive(intValue()) != 0; return isKeepAlive(intValue()) != 0;
} }
public boolean isTcpNoDelay() { public boolean isTcpNoDelay() throws IOException {
return isTcpNoDelay(intValue()) != 0; return isTcpNoDelay(intValue()) != 0;
} }
public boolean isTcpCork() { public boolean isTcpCork() throws IOException {
return isTcpCork(intValue()) != 0; return isTcpCork(intValue()) != 0;
} }
public int getSoLinger() { public int getSoLinger() throws IOException {
return getSoLinger(intValue()); return getSoLinger(intValue());
} }
public int getTcpDeferAccept() { public int getTcpDeferAccept() throws IOException {
return getTcpDeferAccept(intValue()); return getTcpDeferAccept(intValue());
} }
public boolean isTcpQuickAck() { public boolean isTcpQuickAck() throws IOException {
return isTcpQuickAck(intValue()) != 0; return isTcpQuickAck(intValue()) != 0;
} }
@ -275,35 +275,35 @@ public final class Socket extends FileDescriptor {
return getSoError(intValue()); return getSoError(intValue());
} }
public void setKeepAlive(boolean keepAlive) { public void setKeepAlive(boolean keepAlive) throws IOException {
setKeepAlive(intValue(), keepAlive ? 1 : 0); setKeepAlive(intValue(), keepAlive ? 1 : 0);
} }
public void setReceiveBufferSize(int receiveBufferSize) { public void setReceiveBufferSize(int receiveBufferSize) throws IOException {
setReceiveBufferSize(intValue(), receiveBufferSize); setReceiveBufferSize(intValue(), receiveBufferSize);
} }
public void setSendBufferSize(int sendBufferSize) { public void setSendBufferSize(int sendBufferSize) throws IOException {
setSendBufferSize(intValue(), sendBufferSize); setSendBufferSize(intValue(), sendBufferSize);
} }
public void setTcpNoDelay(boolean tcpNoDelay) { public void setTcpNoDelay(boolean tcpNoDelay) throws IOException {
setTcpNoDelay(intValue(), tcpNoDelay ? 1 : 0); setTcpNoDelay(intValue(), tcpNoDelay ? 1 : 0);
} }
public void setTcpCork(boolean tcpCork) { public void setTcpCork(boolean tcpCork) throws IOException {
setTcpCork(intValue(), tcpCork ? 1 : 0); setTcpCork(intValue(), tcpCork ? 1 : 0);
} }
public void setSoLinger(int soLinger) { public void setSoLinger(int soLinger) throws IOException {
setSoLinger(intValue(), soLinger); setSoLinger(intValue(), soLinger);
} }
public void setTcpDeferAccept(int deferAccept) { public void setTcpDeferAccept(int deferAccept) throws IOException {
setTcpDeferAccept(intValue(), deferAccept); setTcpDeferAccept(intValue(), deferAccept);
} }
public void setTcpQuickAck(boolean quickAck) { public void setTcpQuickAck(boolean quickAck) throws IOException {
setTcpQuickAck(intValue(), quickAck ? 1 : 0); setTcpQuickAck(intValue(), quickAck ? 1 : 0);
} }

View File

@ -18,10 +18,12 @@ package io.netty.channel.epoll;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.junit.Assume.*; import static org.junit.Assume.*;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.util.Random; import java.util.Random;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -122,4 +124,26 @@ public class EpollSocketChannelConfigTest {
ch.config().setTcpQuickAck(true); ch.config().setTcpQuickAck(true);
assertTrue(ch.config().isTcpQuickAck()); assertTrue(ch.config().isTcpQuickAck());
} }
@Test
public void testSetOptionWhenClosed() {
ch.close().syncUninterruptibly();
try {
ch.config().setSoLinger(0);
fail();
} catch (ChannelException e) {
assertTrue(e.getCause() instanceof ClosedChannelException);
}
}
@Test
public void testGetOptionWhenClosed() {
ch.close().syncUninterruptibly();
try {
ch.config().getSoLinger();
fail();
} catch (ChannelException e) {
assertTrue(e.getCause() instanceof ClosedChannelException);
}
}
} }