add epoll native

This commit is contained in:
Jörg Prante 2024-01-13 11:34:04 +01:00
parent 49b6c772a5
commit 3d532a821f
180 changed files with 19923 additions and 9 deletions

View file

@ -25,6 +25,7 @@ The following changes were performed on the original source code:
- removed all macos related code (including kqueue)
- removed all aarch64 related code
- removed the direct brotli4j dependency by rewriting Brotli4jOptions to not use Encoder.Parameters
- removed deprecated channel-udt (transport-udt)
Challenges for Netty build on JDK 21

View file

@ -10,13 +10,11 @@ dependencies {
test {
useJUnitPlatform()
failFast = true
failFast = false
testLogging {
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
showStandardStreams = true
}
minHeapSize = "1g" // initial heap size
maxHeapSize = "2g" // maximum heap size
jvmArgs '--add-exports=java.base/jdk.internal=ALL-UNNAMED',
'--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED',
'--add-exports=java.base/sun.nio.ch=ALL-UNNAMED',
@ -30,11 +28,6 @@ test {
'--add-opens=jdk.unsupported/sun.misc=ALL-UNNAMED',
'-Dio.netty.bootstrap.extensions=serviceload'
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
// we have remove native images, this is no longer used
systemProperty "nativeImage.handlerMetadataGroupId", "io.netty"
// we have remove native images
// we have remove native images, this is no longer used
systemProperty "nativeimage.handlerMetadataArtifactId", "netty-transport"
afterSuite { desc, result ->
if (!desc.parent) {
println "\nTest result: ${result.resultType}"

View file

@ -0,0 +1,82 @@
apply plugin: 'com.google.osdetector'
dependencies {
testImplementation project(':netty-channel-unix')
testImplementation project(':netty-channel-epoll')
testImplementation project(':netty-testsuite')
testImplementation project(':netty-handler')
testImplementation testLibs.assertj
testImplementation testLibs.rerunner.jupiter
testRuntimeOnly project(path: ':netty-tcnative-boringssl-static', configuration: osdetector.classifier)
}
task nettyEpollLinuxX8664(type: Jar) {
archiveBaseName.set('netty-channel-epoll-native')
archiveClassifier.set('linux-x86_64')
version rootProject.version
from (sourceSets.main.output) {
include 'META-INF/native/libnetty_transport_native_epoll_x86_64.so'
}
}
assemble.dependsOn(nettyEpollLinuxX8664)
configurations {
'linux-x86_64' {
canBeConsumed = true
canBeResolved = false
extendsFrom runtimeOnly
}
}
artifacts {
'linux-x86_64'(nettyEpollLinuxX8664)
}
publishing {
publications {
publishNettyEpollLinuxX8664(MavenPublication) {
groupId rootProject.group
artifactId project.name
version rootProject.version
artifact nettyEpollLinuxX8664
pom {
artifactId = project.name
name = project.name
version = project.version
description = rootProject.ext.description
url = rootProject.ext.url
inceptionYear = rootProject.ext.inceptionYear
packaging = 'jar'
organization {
name = rootProject.ext.organizationName
url = rootProject.ext.organizationUrl
}
developers {
developer {
id = 'jprante'
name = 'Jörg Prante'
email = 'joergprante@gmail.com'
url = 'https://xbib.org/joerg'
}
}
scm {
url = rootProject.ext.scmUrl
connection = rootProject.ext.scmConnection
developerConnection = rootProject.ext.scmDeveloperConnection
}
issueManagement {
system = rootProject.ext.issueManagementSystem
url = rootProject.ext.issueManagementUrl
}
licenses {
license {
name = rootProject.ext.licenseName
url = rootProject.ext.licenseUrl
distribution = 'repo'
}
}
}
}
}
}

View file

@ -0,0 +1,212 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.ServerChannel;
import io.netty.channel.SimpleChannelInboundHandler;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import static org.junit.jupiter.api.Assertions.assertEquals;
public abstract class DetectPeerCloseWithoutReadTest {
protected abstract EventLoopGroup newGroup();
protected abstract Class<? extends ServerChannel> serverChannel();
protected abstract Class<? extends Channel> clientChannel();
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void clientCloseWithoutServerReadIsDetectedNoExtraReadRequested() throws InterruptedException {
clientCloseWithoutServerReadIsDetected0(false);
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void clientCloseWithoutServerReadIsDetectedExtraReadRequested() throws InterruptedException {
clientCloseWithoutServerReadIsDetected0(true);
}
private void clientCloseWithoutServerReadIsDetected0(final boolean extraReadRequested)
throws InterruptedException {
EventLoopGroup serverGroup = null;
EventLoopGroup clientGroup = null;
Channel serverChannel = null;
try {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicInteger bytesRead = new AtomicInteger();
final int expectedBytes = 100;
serverGroup = newGroup();
clientGroup = newGroup();
ServerBootstrap sb = new ServerBootstrap();
sb.group(serverGroup);
sb.channel(serverChannel());
// Ensure we read only one message per read() call and that we need multiple read()
// calls to consume everything.
sb.childOption(ChannelOption.AUTO_READ, false);
sb.childOption(ChannelOption.MAX_MESSAGES_PER_READ, 1);
sb.childOption(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(expectedBytes / 10));
sb.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new TestHandler(bytesRead, extraReadRequested, latch));
}
});
serverChannel = sb.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
Bootstrap cb = new Bootstrap();
cb.group(serverGroup);
cb.channel(clientChannel());
cb.handler(new ChannelInboundHandlerAdapter());
Channel clientChannel = cb.connect(serverChannel.localAddress()).syncUninterruptibly().channel();
ByteBuf buf = clientChannel.alloc().buffer(expectedBytes);
buf.writerIndex(buf.writerIndex() + expectedBytes);
clientChannel.writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE);
latch.await();
assertEquals(expectedBytes, bytesRead.get());
} finally {
if (serverChannel != null) {
serverChannel.close().syncUninterruptibly();
}
if (serverGroup != null) {
serverGroup.shutdownGracefully();
}
if (clientGroup != null) {
clientGroup.shutdownGracefully();
}
}
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void serverCloseWithoutClientReadIsDetectedNoExtraReadRequested() throws InterruptedException {
serverCloseWithoutClientReadIsDetected0(false);
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void serverCloseWithoutClientReadIsDetectedExtraReadRequested() throws InterruptedException {
serverCloseWithoutClientReadIsDetected0(true);
}
private void serverCloseWithoutClientReadIsDetected0(final boolean extraReadRequested) throws InterruptedException {
EventLoopGroup serverGroup = null;
EventLoopGroup clientGroup = null;
Channel serverChannel = null;
Channel clientChannel = null;
try {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicInteger bytesRead = new AtomicInteger();
final int expectedBytes = 100;
serverGroup = newGroup();
clientGroup = newGroup();
ServerBootstrap sb = new ServerBootstrap();
sb.group(serverGroup);
sb.channel(serverChannel());
sb.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) {
ByteBuf buf = ctx.alloc().buffer(expectedBytes);
buf.writerIndex(buf.writerIndex() + expectedBytes);
ctx.writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE);
ctx.fireChannelActive();
}
});
}
});
serverChannel = sb.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
Bootstrap cb = new Bootstrap();
cb.group(serverGroup);
cb.channel(clientChannel());
// Ensure we read only one message per read() call and that we need multiple read()
// calls to consume everything.
cb.option(ChannelOption.AUTO_READ, false);
cb.option(ChannelOption.MAX_MESSAGES_PER_READ, 1);
cb.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(expectedBytes / 10));
cb.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new TestHandler(bytesRead, extraReadRequested, latch));
}
});
clientChannel = cb.connect(serverChannel.localAddress()).syncUninterruptibly().channel();
latch.await();
assertEquals(expectedBytes, bytesRead.get());
} finally {
if (serverChannel != null) {
serverChannel.close().syncUninterruptibly();
}
if (clientChannel != null) {
clientChannel.close().syncUninterruptibly();
}
if (serverGroup != null) {
serverGroup.shutdownGracefully();
}
if (clientGroup != null) {
clientGroup.shutdownGracefully();
}
}
}
private static final class TestHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final AtomicInteger bytesRead;
private final boolean extraReadRequested;
private final CountDownLatch latch;
TestHandler(AtomicInteger bytesRead, boolean extraReadRequested, CountDownLatch latch) {
this.bytesRead = bytesRead;
this.extraReadRequested = extraReadRequested;
this.latch = latch;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
bytesRead.addAndGet(msg.readableBytes());
if (extraReadRequested) {
// Because autoread is off, we call read to consume all data until we detect the close.
ctx.read();
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
latch.countDown();
ctx.fireChannelInactive();
}
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.unix.DomainSocketAddress;
import java.net.SocketAddress;
import java.util.UUID;
public class EpollAbstractDomainSocketEchoTest extends EpollDomainSocketEchoTest {
@Override
protected SocketAddress newSocketAddress() {
// these don't actually show up in the file system so creating a temp file isn't reliable
return new DomainSocketAddress("\0" + System.getProperty("java.io.tmpdir") + UUID.randomUUID());
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.ChannelException;
import io.netty.channel.unix.Buffer;
import io.netty.channel.unix.IntegerUnixChannelOption;
import io.netty.channel.unix.RawUnixChannelOption;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.fail;
public class EpollChannelConfigTest {
@Test
public void testOptionGetThrowsChannelException() throws Exception {
Epoll.ensureAvailability();
EpollSocketChannel channel = new EpollSocketChannel();
channel.config().getSoLinger();
channel.fd().close();
try {
channel.config().getSoLinger();
fail();
} catch (ChannelException e) {
// expected
}
}
@Test
public void testOptionSetThrowsChannelException() throws Exception {
Epoll.ensureAvailability();
EpollSocketChannel channel = new EpollSocketChannel();
channel.config().setKeepAlive(true);
channel.fd().close();
try {
channel.config().setKeepAlive(true);
fail();
} catch (ChannelException e) {
// expected
}
}
@Test
public void testIntegerOption() throws Exception {
Epoll.ensureAvailability();
EpollSocketChannel channel = new EpollSocketChannel();
IntegerUnixChannelOption opt = new IntegerUnixChannelOption("INT_OPT", 1, 2);
Integer zero = 0;
assertEquals(zero, channel.config().getOption(opt));
channel.config().setOption(opt, 1);
assertNotEquals(zero, channel.config().getOption(opt));
channel.fd().close();
}
@Test
public void testRawOption() throws Exception {
Epoll.ensureAvailability();
EpollSocketChannel channel = new EpollSocketChannel();
// Value for SOL_SOCKET and SO_REUSEADDR
// See https://github.com/torvalds/linux/blob/v5.17/include/uapi/asm-generic/socket.h
RawUnixChannelOption opt = new RawUnixChannelOption("RAW_OPT", 1, 2, 4);
ByteBuffer disabled = Buffer.allocateDirectWithNativeOrder(4);
disabled.putInt(0).flip();
assertEquals(disabled, channel.config().getOption(opt));
ByteBuffer enabled = Buffer.allocateDirectWithNativeOrder(4);
enabled.putInt(1).flip();
channel.config().setOption(opt, enabled);
assertNotEquals(disabled, channel.config().getOption(opt));
channel.fd().close();
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelConfig;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.CompositeBufferGatheringWriteTest;
import java.util.List;
public class EpollCompositeBufferGatheringWriteTest extends CompositeBufferGatheringWriteTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
@Override
protected void compositeBufferPartialWriteDoesNotCorruptDataInitServerConfig(ChannelConfig config,
int soSndBuf) {
if (config instanceof EpollChannelConfig) {
((EpollChannelConfig) config).setMaxBytesPerGatheringWrite(soSndBuf);
}
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollDatagramChannelConfigTest {
@Test
public void testIpFreeBind() throws Exception {
Epoll.ensureAvailability();
EpollDatagramChannel channel = new EpollDatagramChannel();
assertTrue(channel.config().setOption(EpollChannelOption.IP_FREEBIND, true));
assertTrue(channel.config().getOption(EpollChannelOption.IP_FREEBIND));
channel.fd().close();
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.unix.Socket;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import static io.netty.util.NetUtil.LOCALHOST;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollDatagramChannelTest {
@BeforeEach
public void setUp() {
Epoll.ensureAvailability();
}
@Test
public void testDefaultMaxMessagePerRead() {
EpollDatagramChannel channel = new EpollDatagramChannel();
assertEquals(16, channel.config().getMaxMessagesPerRead());
channel.unsafe().closeForcibly();
}
@Test
public void testNotActiveNoLocalRemoteAddress() throws IOException {
checkNotActiveNoLocalRemoteAddress(new EpollDatagramChannel());
checkNotActiveNoLocalRemoteAddress(new EpollDatagramChannel(InternetProtocolFamily.IPv4));
checkNotActiveNoLocalRemoteAddress(new EpollDatagramChannel(InternetProtocolFamily.IPv6));
}
@Test
public void testActiveHasLocalAddress() throws IOException {
Socket socket = Socket.newSocketDgram();
EpollDatagramChannel channel = new EpollDatagramChannel(socket.intValue());
InetSocketAddress localAddress = channel.localAddress();
assertTrue(channel.active);
assertNotNull(localAddress);
assertEquals(socket.localAddress(), localAddress);
channel.fd().close();
}
@Test
public void testLocalAddressBeforeAndAfterBind() {
EventLoopGroup group = new EpollEventLoopGroup(1);
try {
TestHandler handler = new TestHandler();
InetSocketAddress localAddressBeforeBind = new InetSocketAddress(LOCALHOST, 0);
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(EpollDatagramChannel.class)
.localAddress(localAddressBeforeBind)
.handler(handler);
ChannelFuture future = bootstrap.bind().syncUninterruptibly();
assertNull(handler.localAddress);
SocketAddress localAddressAfterBind = future.channel().localAddress();
assertNotNull(localAddressAfterBind);
assertTrue(localAddressAfterBind instanceof InetSocketAddress);
assertTrue(((InetSocketAddress) localAddressAfterBind).getPort() != 0);
future.channel().close().syncUninterruptibly();
} finally {
group.shutdownGracefully();
}
}
private static void checkNotActiveNoLocalRemoteAddress(EpollDatagramChannel channel) throws IOException {
assertFalse(channel.active);
assertNull(channel.localAddress());
assertNull(channel.remoteAddress());
channel.fd().close();
}
private static final class TestHandler extends ChannelInboundHandlerAdapter {
private volatile SocketAddress localAddress;
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
this.localAddress = ctx.channel().localAddress();
super.channelRegistered(ctx);
}
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.DatagramConnectNotExistsTest;
import java.util.List;
public class EpollDatagramConnectNotExistsTest extends DatagramConnectNotExistsTest {
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.datagramSocket();
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.DatagramMulticastIPv6Test;
import java.util.List;
public class EpollDatagramMulticastIPv6Test extends DatagramMulticastIPv6Test {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.datagram(internetProtocolFamily());
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright 2021 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.testsuite.transport.socket.DatagramMulticastTest;
public class EpollDatagramMulticastIpv6WithIpv4AddrTest extends DatagramMulticastTest {
@Override
protected InternetProtocolFamily groupInternetProtocalFamily() {
return InternetProtocolFamily.IPv4;
}
@Override
protected InternetProtocolFamily socketInternetProtocalFamily() {
return InternetProtocolFamily.IPv6;
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.DatagramMulticastTest;
import java.util.List;
public class EpollDatagramMulticastTest extends DatagramMulticastTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.datagram(internetProtocolFamily());
}
}

View file

@ -0,0 +1,307 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.AbstractDatagramTest;
import io.netty.util.internal.PlatformDependent;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class EpollDatagramScatteringReadTest extends AbstractDatagramTest {
@BeforeAll
public static void assumeRecvmmsgSupported() {
assumeTrue(Native.IS_SUPPORTING_RECVMMSG);
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.epollOnlyDatagram(internetProtocolFamily());
}
@Test
public void testScatteringReadPartial(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testScatteringReadPartial(bootstrap, bootstrap2);
}
});
}
public void testScatteringReadPartial(Bootstrap sb, Bootstrap cb) throws Throwable {
testScatteringRead(sb, cb, false, true);
}
@Test
public void testScatteringRead(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testScatteringRead(bootstrap, bootstrap2);
}
});
}
public void testScatteringRead(Bootstrap sb, Bootstrap cb) throws Throwable {
testScatteringRead(sb, cb, false, false);
}
@Test
public void testScatteringReadConnectedPartial(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testScatteringReadConnectedPartial(bootstrap, bootstrap2);
}
});
}
public void testScatteringReadConnectedPartial(Bootstrap sb, Bootstrap cb) throws Throwable {
testScatteringRead(sb, cb, true, true);
}
@Test
public void testScatteringConnectedRead(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testScatteringConnectedRead(bootstrap, bootstrap2);
}
});
}
public void testScatteringConnectedRead(Bootstrap sb, Bootstrap cb) throws Throwable {
testScatteringRead(sb, cb, true, false);
}
private void testScatteringRead(Bootstrap sb, Bootstrap cb, boolean connected, boolean partial) throws Throwable {
int packetSize = 8;
int numPackets = 4;
sb.option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(
packetSize, packetSize * (partial ? numPackets / 2 : numPackets), 64 * 1024));
// Set the MAX_DATAGRAM_PAYLOAD_SIZE to something bigger then the actual packet size.
// This will allow us to check if we correctly thread the received len.
sb.option(EpollChannelOption.MAX_DATAGRAM_PAYLOAD_SIZE, packetSize * 2);
Channel sc = null;
Channel cc = null;
try {
cb.handler(new SimpleChannelInboundHandler<Object>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msgs) throws Exception {
// Nothing will be sent.
}
});
cc = cb.bind(newSocketAddress()).sync().channel();
final SocketAddress ccAddress = cc.localAddress();
final AtomicReference<Throwable> errorRef = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(numPackets);
sb.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
private long numRead;
private int counter;
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
assertTrue(counter > 1);
counter = 0;
ctx.read();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
assertEquals(ccAddress, msg.sender());
// Each packet contains a long which represent the write iteration.
assertEquals(8, msg.content().readableBytes());
assertEquals(numRead, msg.content().readLong());
numRead++;
counter++;
latch.countDown();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
errorRef.compareAndSet(null, cause);
}
});
sb.option(ChannelOption.AUTO_READ, false);
sc = sb.bind(newSocketAddress()).sync().channel();
if (connected) {
sc.connect(cc.localAddress()).syncUninterruptibly();
}
InetSocketAddress addr = (InetSocketAddress) sc.localAddress();
List<ChannelFuture> futures = new ArrayList<ChannelFuture>(numPackets);
for (int i = 0; i < numPackets; i++) {
futures.add(cc.write(new DatagramPacket(cc.alloc().directBuffer().writeLong(i), addr)));
}
cc.flush();
for (ChannelFuture f: futures) {
f.sync();
}
// Enable autoread now which also triggers a read, this should cause scattering reads (recvmmsg) to happen.
sc.config().setAutoRead(true);
if (!latch.await(10, TimeUnit.SECONDS)) {
Throwable error = errorRef.get();
if (error != null) {
throw error;
}
fail("Timeout while waiting for packets");
}
} finally {
if (cc != null) {
cc.close().syncUninterruptibly();
}
if (sc != null) {
sc.close().syncUninterruptibly();
}
}
}
@Test
public void testScatteringReadWithSmallBuffer(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testScatteringReadWithSmallBuffer(bootstrap, bootstrap2);
}
});
}
public void testScatteringReadWithSmallBuffer(Bootstrap sb, Bootstrap cb) throws Throwable {
testScatteringReadWithSmallBuffer0(sb, cb, false);
}
@Test
public void testScatteringConnectedReadWithSmallBuffer(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testScatteringConnectedReadWithSmallBuffer(bootstrap, bootstrap2);
}
});
}
public void testScatteringConnectedReadWithSmallBuffer(Bootstrap sb, Bootstrap cb) throws Throwable {
testScatteringReadWithSmallBuffer0(sb, cb, true);
}
private void testScatteringReadWithSmallBuffer0(Bootstrap sb, Bootstrap cb, boolean connected) throws Throwable {
int packetSize = 16;
sb.option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(1400, 1400, 64 * 1024));
sb.option(EpollChannelOption.MAX_DATAGRAM_PAYLOAD_SIZE, 1400);
Channel sc = null;
Channel cc = null;
try {
cb.handler(new SimpleChannelInboundHandler<Object>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msgs) {
// Nothing will be sent.
}
});
cc = cb.bind(newSocketAddress()).sync().channel();
final SocketAddress ccAddress = cc.localAddress();
final AtomicReference<Throwable> errorRef = new AtomicReference<Throwable>();
final byte[] bytes = new byte[packetSize];
PlatformDependent.threadLocalRandom().nextBytes(bytes);
final CountDownLatch latch = new CountDownLatch(1);
sb.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
assertEquals(ccAddress, msg.sender());
assertEquals(bytes.length, msg.content().readableBytes());
byte[] receivedBytes = new byte[bytes.length];
msg.content().readBytes(receivedBytes);
assertArrayEquals(bytes, receivedBytes);
latch.countDown();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
errorRef.compareAndSet(null, cause);
}
});
sc = sb.bind(newSocketAddress()).sync().channel();
if (connected) {
sc.connect(cc.localAddress()).syncUninterruptibly();
}
InetSocketAddress addr = (InetSocketAddress) sc.localAddress();
cc.writeAndFlush(new DatagramPacket(cc.alloc().directBuffer().writeBytes(bytes), addr)).sync();
if (!latch.await(10, TimeUnit.SECONDS)) {
Throwable error = errorRef.get();
if (error != null) {
throw error;
}
fail("Timeout while waiting for packets");
}
} finally {
if (cc != null) {
cc.close().syncUninterruptibly();
}
if (sc != null) {
sc.close().syncUninterruptibly();
}
}
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapComboFactory;
import io.netty.testsuite.transport.socket.DatagramUnicastIPv6MappedTest;
import java.util.List;
public class EpollDatagramUnicastIPv6MappedTest extends DatagramUnicastIPv6MappedTest {
@Override
protected List<BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.datagram(internetProtocolFamily());
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.DatagramUnicastIPv6Test;
import java.util.List;
public class EpollDatagramUnicastIPv6Test extends DatagramUnicastIPv6Test {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.datagram(internetProtocolFamily());
}
}

View file

@ -0,0 +1,190 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.DatagramUnicastInetTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class EpollDatagramUnicastTest extends DatagramUnicastInetTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.datagram(InternetProtocolFamily.IPv4);
}
public void testSimpleSendWithConnect(Bootstrap sb, Bootstrap cb) throws Throwable {
// Run this test with IP_RECVORIGDSTADDR option enabled
sb.option(EpollChannelOption.IP_RECVORIGDSTADDR, true);
super.testSimpleSendWithConnect(sb, cb);
sb.option(EpollChannelOption.IP_RECVORIGDSTADDR, false);
}
@Test
public void testSendSegmentedDatagramPacket(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testSendSegmentedDatagramPacket(bootstrap, bootstrap2);
}
});
}
public void testSendSegmentedDatagramPacket(Bootstrap sb, Bootstrap cb) throws Throwable {
testSegmentedDatagramPacket(sb, cb, false, false);
}
@Test
public void testSendSegmentedDatagramPacketComposite(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testSendSegmentedDatagramPacketComposite(bootstrap, bootstrap2);
}
});
}
public void testSendSegmentedDatagramPacketComposite(Bootstrap sb, Bootstrap cb) throws Throwable {
testSegmentedDatagramPacket(sb, cb, true, false);
}
@Test
public void testSendAndReceiveSegmentedDatagramPacket(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testSendAndReceiveSegmentedDatagramPacket(bootstrap, bootstrap2);
}
});
}
public void testSendAndReceiveSegmentedDatagramPacket(Bootstrap sb, Bootstrap cb) throws Throwable {
testSegmentedDatagramPacket(sb, cb, false, true);
}
@Test
public void testSendAndReceiveSegmentedDatagramPacketComposite(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testSendAndReceiveSegmentedDatagramPacketComposite(bootstrap, bootstrap2);
}
});
}
public void testSendAndReceiveSegmentedDatagramPacketComposite(Bootstrap sb, Bootstrap cb) throws Throwable {
testSegmentedDatagramPacket(sb, cb, true, true);
}
private void testSegmentedDatagramPacket(Bootstrap sb, Bootstrap cb, boolean composite, boolean gro)
throws Throwable {
if (!(cb.group() instanceof EpollEventLoopGroup)) {
// Only supported for the native epoll transport.
return;
}
if (gro && !(sb.group() instanceof EpollEventLoopGroup)) {
// Only supported for the native epoll transport.
return;
}
assumeTrue(EpollDatagramChannel.isSegmentedDatagramPacketSupported());
Channel sc = null;
Channel cc = null;
try {
cb.handler(new SimpleChannelInboundHandler<Object>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msgs) {
// Nothing will be sent.
}
});
cc = cb.bind(newSocketAddress()).sync().channel();
final int numBuffers = 16;
final int segmentSize = 512;
int bufferCapacity = numBuffers * segmentSize;
final CountDownLatch latch = new CountDownLatch(numBuffers);
AtomicReference<Throwable> errorRef = new AtomicReference<Throwable>();
if (gro) {
// Enable GRO and also ensure we can read everything with one read as otherwise
// we will drop things on the floor.
sb.option(EpollChannelOption.UDP_GRO, true);
sb.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(bufferCapacity));
}
sc = sb.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
if (packet.content().readableBytes() == segmentSize) {
latch.countDown();
}
}
}).bind(newSocketAddress()).sync().channel();
if (sc instanceof EpollDatagramChannel) {
assertEquals(gro, sc.config().getOption(EpollChannelOption.UDP_GRO));
}
InetSocketAddress addr = sendToAddress((InetSocketAddress) sc.localAddress());
final ByteBuf buffer;
if (composite) {
CompositeByteBuf compositeBuffer = Unpooled.compositeBuffer();
for (int i = 0; i < numBuffers; i++) {
compositeBuffer.addComponent(true,
Unpooled.directBuffer(segmentSize).writeZero(segmentSize));
}
buffer = compositeBuffer;
} else {
buffer = Unpooled.directBuffer(bufferCapacity).writeZero(bufferCapacity);
}
cc.writeAndFlush(new io.netty.channel.unix.SegmentedDatagramPacket(buffer, segmentSize, addr)).sync();
if (!latch.await(10, TimeUnit.SECONDS)) {
Throwable error = errorRef.get();
if (error != null) {
throw error;
}
fail();
}
} finally {
if (cc != null) {
cc.close().sync();
}
if (sc != null) {
sc.close().sync();
}
}
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
public class EpollDetectPeerCloseWithoutReadTest extends DetectPeerCloseWithoutReadTest {
@Override
protected EventLoopGroup newGroup() {
return new EpollEventLoopGroup(2);
}
@Override
protected Class<? extends ServerChannel> serverChannel() {
return EpollServerSocketChannel.class;
}
@Override
protected Class<? extends Channel> clientChannel() {
return EpollSocketChannel.class;
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2023 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EpollDomainDatagramChannelTest {
@BeforeEach
public void setUp() {
Epoll.ensureAvailability();
}
@Test
public void testDefaultMaxMessagePerRead() {
EpollDomainDatagramChannel channel = new EpollDomainDatagramChannel();
assertEquals(16, channel.config().getMaxMessagesPerRead());
channel.unsafe().closeForcibly();
}
}

View file

@ -0,0 +1,76 @@
/*
* Copyright 2021 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.unix.DomainDatagramPacket;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.AbstractClientSocketTest;
import io.netty.util.CharsetUtil;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import java.io.FileNotFoundException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
class EpollDomainDatagramPathTest extends AbstractClientSocketTest {
@Test
void testConnectPathDoesNotExist(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap>() {
@Override
public void run(Bootstrap bootstrap) {
try {
bootstrap.handler(new ChannelInboundHandlerAdapter())
.connect(EpollSocketTestPermutation.newDomainSocketAddress()).sync().channel();
fail("Expected FileNotFoundException");
} catch (Exception e) {
assertTrue(e instanceof FileNotFoundException);
}
}
});
}
@Test
void testWriteReceiverPathDoesNotExist(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap>() {
@Override
public void run(Bootstrap bootstrap) {
try {
Channel ch = bootstrap.handler(new ChannelInboundHandlerAdapter())
.bind(EpollSocketTestPermutation.newDomainSocketAddress()).sync().channel();
ch.writeAndFlush(new DomainDatagramPacket(
Unpooled.copiedBuffer("test", CharsetUtil.US_ASCII),
EpollSocketTestPermutation.newDomainSocketAddress())).sync();
fail("Expected FileNotFoundException");
} catch (Exception e) {
assertTrue(e instanceof FileNotFoundException);
}
}
});
}
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainDatagramSocket();
}
}

View file

@ -0,0 +1,168 @@
/*
* Copyright 2021 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.unix.DomainDatagramChannel;
import io.netty.channel.unix.DomainDatagramPacket;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.DatagramUnicastTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class EpollDomainDatagramUnicastTest extends DatagramUnicastTest {
@Test
void testBind(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testBind(bootstrap2);
}
});
}
private void testBind(Bootstrap cb) throws Throwable {
Channel channel = null;
try {
channel = cb.handler(new ChannelInboundHandlerAdapter())
.bind(newSocketAddress()).sync().channel();
assertThat(channel.localAddress()).isNotNull()
.isInstanceOf(DomainSocketAddress.class);
} finally {
closeChannel(channel);
}
}
@Override
protected boolean supportDisconnect() {
return false;
}
@Override
protected boolean isConnected(Channel channel) {
return ((DomainDatagramChannel) channel).isConnected();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainDatagram();
}
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected Channel setupClientChannel(Bootstrap cb, final byte[] bytes, final CountDownLatch latch,
final AtomicReference<Throwable> errorRef) throws Throwable {
cb.handler(new SimpleChannelInboundHandler<DomainDatagramPacket>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, DomainDatagramPacket msg) {
try {
ByteBuf buf = msg.content();
assertEquals(bytes.length, buf.readableBytes());
for (int i = 0; i < bytes.length; i++) {
assertEquals(bytes[i], buf.getByte(buf.readerIndex() + i));
}
assertEquals(ctx.channel().localAddress(), msg.recipient());
} finally {
latch.countDown();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
errorRef.compareAndSet(null, cause);
}
});
return cb.bind(newSocketAddress()).sync().channel();
}
@Override
protected Channel setupServerChannel(Bootstrap sb, final byte[] bytes, final SocketAddress sender,
final CountDownLatch latch, final AtomicReference<Throwable> errorRef,
final boolean echo) throws Throwable {
sb.handler(new SimpleChannelInboundHandler<DomainDatagramPacket>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, DomainDatagramPacket msg) {
try {
if (sender == null) {
assertNotNull(msg.sender());
} else {
assertEquals(sender, msg.sender());
}
ByteBuf buf = msg.content();
assertEquals(bytes.length, buf.readableBytes());
for (int i = 0; i < bytes.length; i++) {
assertEquals(bytes[i], buf.getByte(buf.readerIndex() + i));
}
assertEquals(ctx.channel().localAddress(), msg.recipient());
if (echo) {
ctx.writeAndFlush(new DomainDatagramPacket(buf.retainedDuplicate(), msg.sender()));
}
} finally {
latch.countDown();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
errorRef.compareAndSet(null, cause);
}
});
return sb.bind(newSocketAddress()).sync().channel();
}
@Override
protected ChannelFuture write(Channel cc, ByteBuf buf, SocketAddress remote, WrapType wrapType) {
switch (wrapType) {
case DUP:
return cc.write(new DomainDatagramPacket(buf.retainedDuplicate(), (DomainSocketAddress) remote));
case SLICE:
return cc.write(new DomainDatagramPacket(buf.retainedSlice(), (DomainSocketAddress) remote));
case READ_ONLY:
return cc.write(new DomainDatagramPacket(buf.retain().asReadOnly(), (DomainSocketAddress) remote));
case NONE:
return cc.write(new DomainDatagramPacket(buf.retain(), (DomainSocketAddress) remote));
default:
throw new Error("unknown wrap type: " + wrapType);
}
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright 2023 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketAddressesTest;
import java.net.SocketAddress;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class EpollDomainSocketAddressesTest extends SocketAddressesTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
@Override
protected void assertAddress(SocketAddress address) {
assertNotNull(((DomainSocketAddress) address).path());
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketDataReadInitialStateTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketDataReadInitialStateTest extends SocketDataReadInitialStateTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketEchoTest extends EpollSocketEchoTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,116 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.unix.DomainSocketReadMode;
import io.netty.channel.unix.FileDescriptor;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.AbstractSocketTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.Timeout;
import java.net.SocketAddress;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollDomainSocketFdTest extends AbstractSocketTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
@Test
@Timeout(value = 30000, unit = TimeUnit.MILLISECONDS)
public void testSendRecvFd(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<ServerBootstrap, Bootstrap>() {
@Override
public void run(ServerBootstrap serverBootstrap, Bootstrap bootstrap) throws Throwable {
testSendRecvFd(serverBootstrap, bootstrap);
}
});
}
public void testSendRecvFd(ServerBootstrap sb, Bootstrap cb) throws Throwable {
final BlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(1);
sb.childHandler(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// Create new channel and obtain a file descriptor from it.
final EpollDomainSocketChannel ch = new EpollDomainSocketChannel();
ctx.writeAndFlush(ch.fd()).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
Throwable cause = future.cause();
queue.offer(cause);
}
}
});
}
});
cb.handler(new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
FileDescriptor fd = (FileDescriptor) msg;
queue.offer(fd);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
queue.add(cause);
ctx.close();
}
});
cb.option(EpollChannelOption.DOMAIN_SOCKET_READ_MODE,
DomainSocketReadMode.FILE_DESCRIPTORS);
Channel sc = sb.bind().sync().channel();
Channel cc = cb.connect(sc.localAddress()).sync().channel();
Object received = queue.take();
cc.close().sync();
sc.close().sync();
if (received instanceof FileDescriptor) {
FileDescriptor fd = (FileDescriptor) received;
assertTrue(fd.isOpen());
fd.close();
assertFalse(fd.isOpen());
assertNull(queue.poll());
} else {
throw (Throwable) received;
}
}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketFileRegionTest extends EpollSocketFileRegionTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketFixedLengthEchoTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketFixedLengthEchoTest extends SocketFixedLengthEchoTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketGatheringWriteTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketGatheringWriteTest extends SocketGatheringWriteTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketObjectEchoTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketObjectEchoTest extends SocketObjectEchoTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.AbstractSocketReuseFdTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketReuseFdTest extends AbstractSocketReuseFdTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.unix.Buffer;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.testsuite.transport.socket.AbstractSocketShutdownOutputByPeerTest;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.List;
public class EpollDomainSocketShutdownOutputByPeerTest extends AbstractSocketShutdownOutputByPeerTest<LinuxSocket> {
@Override
protected List<BootstrapFactory<ServerBootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.serverDomainSocket();
}
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected void shutdownOutput(LinuxSocket s) throws IOException {
s.shutdown(false, true);
}
@Override
protected void connect(LinuxSocket s, SocketAddress address) throws IOException {
s.connect(address);
}
@Override
protected void close(LinuxSocket s) throws IOException {
s.close();
}
@Override
protected void write(LinuxSocket s, int data) throws IOException {
final ByteBuffer buf = Buffer.allocateDirectWithNativeOrder(4);
buf.putInt(data);
buf.flip();
s.send(buf, buf.position(), buf.limit());
Buffer.free(buf);
}
@Override
protected LinuxSocket newSocket() {
return LinuxSocket.newSocketDomain();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslClientRenegotiateTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketSslClientRenegotiateTest extends SocketSslClientRenegotiateTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslEchoTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketSslEchoTest extends SocketSslEchoTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslGreetingTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketSslGreetingTest extends SocketSslGreetingTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketStartTlsTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketStartTlsTest extends SocketStartTlsTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketStringEchoTest;
import java.net.SocketAddress;
import java.util.List;
public class EpollDomainSocketStringEchoTest extends SocketStringEchoTest {
@Override
protected SocketAddress newSocketAddress() {
return EpollSocketTestPermutation.newDomainSocketAddress();
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.domainSocket();
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketAutoReadTest;
import java.util.List;
public class EpollETSocketAutoReadTest extends SocketAutoReadTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketConditionalWritabilityTest;
import java.util.List;
public class EpollETSocketConditionalWritabilityTest extends SocketConditionalWritabilityTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketDataReadInitialStateTest;
import java.util.List;
public class EpollETSocketDataReadInitialStateTest extends SocketDataReadInitialStateTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketExceptionHandlingTest;
import java.util.List;
public class EpollETSocketExceptionHandlingTest extends SocketExceptionHandlingTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketHalfClosedTest;
import java.util.List;
public class EpollETSocketHalfClosedTest extends SocketHalfClosedTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketReadPendingTest;
import java.util.List;
public class EpollETSocketReadPendingTest extends SocketReadPendingTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
public class EpollETSocketStringEchoBusyWaitTest extends EpollSocketStringEchoBusyWaitTest {
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.EDGE_TRIGGERED);
}
}

View file

@ -0,0 +1,189 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.testsuite.transport.AbstractSingleThreadEventLoopTest;
import io.netty.channel.DefaultSelectStrategyFactory;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.unix.FileDescriptor;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.RejectedExecutionHandlers;
import io.netty.util.concurrent.ThreadPerTaskExecutor;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollEventLoopTest extends AbstractSingleThreadEventLoopTest {
@Override
protected boolean supportsChannelIteration() {
return true;
}
@Override
protected EventLoopGroup newEventLoopGroup() {
return new EpollEventLoopGroup();
}
@Override
protected ServerSocketChannel newChannel() {
return new EpollServerSocketChannel();
}
@Override
protected Class<? extends ServerChannel> serverChannelClass() {
return EpollServerSocketChannel.class;
}
@Test
public void testScheduleBigDelayNotOverflow() {
final AtomicReference<Throwable> capture = new AtomicReference<Throwable>();
final EventLoopGroup group = new EpollEventLoop(null,
new ThreadPerTaskExecutor(new DefaultThreadFactory(getClass())), 0,
DefaultSelectStrategyFactory.INSTANCE.newSelectStrategy(), RejectedExecutionHandlers.reject(),
null, null) {
@Override
void handleLoopException(Throwable t) {
capture.set(t);
super.handleLoopException(t);
}
};
try {
final EventLoop eventLoop = group.next();
Future<?> future = eventLoop.schedule(new Runnable() {
@Override
public void run() {
// NOOP
}
}, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
assertFalse(future.awaitUninterruptibly(1000));
assertTrue(future.cancel(true));
assertNull(capture.get());
} finally {
group.shutdownGracefully();
}
}
@Test
public void testEventFDETSemantics() throws Throwable {
final FileDescriptor epoll = Native.newEpollCreate();
final FileDescriptor eventFd = Native.newEventFd();
final FileDescriptor timerFd = Native.newTimerFd();
final EpollEventArray array = new EpollEventArray(1024);
try {
Native.epollCtlAdd(epoll.intValue(), eventFd.intValue(), Native.EPOLLIN | Native.EPOLLET);
final AtomicReference<Throwable> causeRef = new AtomicReference<Throwable>();
final AtomicInteger integer = new AtomicInteger();
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 2; i++) {
int ready = Native.epollWait(epoll, array, timerFd, -1, -1);
assertEquals(1, ready);
assertEquals(eventFd.intValue(), array.fd(0));
integer.incrementAndGet();
}
} catch (IOException e) {
causeRef.set(e);
}
}
});
t.start();
Native.eventFdWrite(eventFd.intValue(), 1);
// Spin until we was the wakeup.
while (integer.get() != 1) {
Thread.sleep(10);
}
// Sleep for a short moment to ensure there is not other wakeup.
Thread.sleep(1000);
assertEquals(1, integer.get());
Native.eventFdWrite(eventFd.intValue(), 1);
t.join();
Throwable cause = causeRef.get();
if (cause != null) {
throw cause;
}
assertEquals(2, integer.get());
} finally {
array.free();
epoll.close();
eventFd.close();
timerFd.close();
}
}
@Test
public void testResultNoTimeoutCorrectlyEncoded() throws Throwable {
final FileDescriptor epoll = Native.newEpollCreate();
final FileDescriptor eventFd = Native.newEventFd();
final FileDescriptor timerFd = Native.newTimerFd();
final EpollEventArray array = new EpollEventArray(1024);
try {
Native.epollCtlAdd(epoll.intValue(), eventFd.intValue(), Native.EPOLLIN | Native.EPOLLET);
final AtomicReference<Throwable> causeRef = new AtomicReference<Throwable>();
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
for (;;) {
long ready = Native.epollWait(epoll, array, timerFd, 0, 0, 10);
if (ready > 0) {
assertEquals(1, Native.epollReady(ready));
assertEquals(eventFd.intValue(), array.fd(0));
return;
}
Thread.sleep(100);
}
} catch (IOException e) {
causeRef.set(e);
} catch (InterruptedException ignore) {
// ignore
}
}
});
t.start();
Native.eventFdWrite(eventFd.intValue(), 1);
t.join();
Throwable cause = causeRef.get();
if (cause != null) {
throw cause;
}
} finally {
array.free();
epoll.close();
eventFd.close();
timerFd.close();
}
}
}

View file

@ -0,0 +1,25 @@
/*
* Copyright 2021 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import java.net.SocketAddress;
public class EpollJdkLoopbackSocketSslEchoTest extends EpollSocketSslEchoTest {
@Override
protected SocketAddress newSocketAddress() {
return UnixTestUtils.newInetLoopbackSocketAddress();
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import org.junit.jupiter.api.BeforeAll;
public class EpollKQueueIovArrayTest extends IovArrayTest {
@BeforeAll
public static void loadNative() {
Epoll.ensureAvailability();
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketAutoReadTest;
import java.util.List;
public class EpollLTSocketAutoReadTest extends SocketAutoReadTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketConditionalWritabilityTest;
import java.util.List;
public class EpollLTSocketConditionalWritabilityTest extends SocketConditionalWritabilityTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketDataReadInitialStateTest;
import java.util.List;
public class EpollLTSocketDataReadInitialStateTest extends SocketDataReadInitialStateTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketExceptionHandlingTest;
import java.util.List;
public class EpollLTSocketExceptionHandlingTest extends SocketExceptionHandlingTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketHalfClosedTest;
import java.util.List;
public class EpollLTSocketHalfClosedTest extends SocketHalfClosedTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketReadPendingTest;
import java.util.List;
public class EpollLTSocketReadPendingTest extends SocketReadPendingTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
public class EpollLTSocketStringEchoBusyWaitTest extends EpollSocketStringEchoBusyWaitTest {
@Override
protected void configure(ServerBootstrap bootstrap, Bootstrap bootstrap2, ByteBufAllocator allocator) {
super.configure(bootstrap, bootstrap2, allocator);
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED)
.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bootstrap2.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
}
}

View file

@ -0,0 +1,263 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.AbstractBootstrap;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.NetUtil;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.internal.logging.InternalLogLevel;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class EpollReuseAddrTest {
private static final InternalLogger LOGGER = InternalLoggerFactory.getInstance(EpollReuseAddrTest.class);
private static final int MAJOR;
private static final int MINOR;
private static final int BUGFIX;
static {
String kernelVersion = Native.KERNEL_VERSION;
int index = kernelVersion.indexOf('-');
if (index > -1) {
kernelVersion = kernelVersion.substring(0, index);
}
String[] versionParts = kernelVersion.split("\\.");
if (versionParts.length <= 3) {
MAJOR = Integer.parseInt(versionParts[0]);
MINOR = Integer.parseInt(versionParts[1]);
if (versionParts.length == 3) {
int bugFix;
try {
bugFix = Integer.parseInt(versionParts[2]);
} catch (NumberFormatException ignore) {
// the last part of the version may include all kind of different things. Especially when
// someone compiles his / her own kernel.
// Just ignore a parse error here and use 0.
bugFix = 0;
}
BUGFIX = bugFix;
} else {
BUGFIX = 0;
}
} else {
LOGGER.log(InternalLogLevel.INFO, "Unable to parse kernel version: " + kernelVersion);
MAJOR = 0;
MINOR = 0;
BUGFIX = 0;
}
}
@Test
public void testMultipleBindSocketChannelWithoutReusePortFails() {
assumeTrue(versionEqOrGt(3, 9, 0));
testMultipleBindDatagramChannelWithoutReusePortFails0(createServerBootstrap());
}
@Test
public void testMultipleBindDatagramChannelWithoutReusePortFails() {
assumeTrue(versionEqOrGt(3, 9, 0));
testMultipleBindDatagramChannelWithoutReusePortFails0(createBootstrap());
}
private static void testMultipleBindDatagramChannelWithoutReusePortFails0(AbstractBootstrap<?, ?> bootstrap) {
bootstrap.handler(new LoggingHandler(LogLevel.ERROR));
ChannelFuture future = bootstrap.bind().syncUninterruptibly();
try {
bootstrap.bind(future.channel().localAddress()).syncUninterruptibly();
fail();
} catch (Exception e) {
assertTrue(e instanceof IOException);
}
future.channel().close().syncUninterruptibly();
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void testMultipleBindSocketChannel() throws Exception {
assumeTrue(versionEqOrGt(3, 9, 0));
ServerBootstrap bootstrap = createServerBootstrap();
bootstrap.option(EpollChannelOption.SO_REUSEPORT, true);
final AtomicBoolean accepted1 = new AtomicBoolean();
bootstrap.childHandler(new ServerSocketTestHandler(accepted1));
ChannelFuture future = bootstrap.bind().syncUninterruptibly();
InetSocketAddress address1 = (InetSocketAddress) future.channel().localAddress();
final AtomicBoolean accepted2 = new AtomicBoolean();
bootstrap.childHandler(new ServerSocketTestHandler(accepted2));
ChannelFuture future2 = bootstrap.bind(address1).syncUninterruptibly();
InetSocketAddress address2 = (InetSocketAddress) future2.channel().localAddress();
assertEquals(address1, address2);
while (!accepted1.get() || !accepted2.get()) {
Socket socket = new Socket(address1.getAddress(), address1.getPort());
socket.setReuseAddress(true);
socket.close();
}
future.channel().close().syncUninterruptibly();
future2.channel().close().syncUninterruptibly();
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
@Disabled // TODO: Unignore after making it pass on centos6-1 and debian7-1
public void testMultipleBindDatagramChannel() throws Exception {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
assumeTrue(versionEqOrGt(3, 9, 0));
Bootstrap bootstrap = createBootstrap();
bootstrap.option(EpollChannelOption.SO_REUSEPORT, true);
final AtomicBoolean received1 = new AtomicBoolean();
bootstrap.handler(new DatagramSocketTestHandler(received1));
ChannelFuture future = bootstrap.bind().syncUninterruptibly();
final InetSocketAddress address1 = (InetSocketAddress) future.channel().localAddress();
final AtomicBoolean received2 = new AtomicBoolean();
bootstrap.handler(new DatagramSocketTestHandler(received2));
ChannelFuture future2 = bootstrap.bind(address1).syncUninterruptibly();
final InetSocketAddress address2 = (InetSocketAddress) future2.channel().localAddress();
assertEquals(address1, address2);
final byte[] bytes = "data".getBytes();
// fire up 16 Threads and send DatagramPackets to make sure we stress it enough to see DatagramPackets received
// on both sockets.
int count = 16;
final CountDownLatch latch = new CountDownLatch(count);
Runnable r = new Runnable() {
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket();
while (!received1.get() || !received2.get()) {
socket.send(new DatagramPacket(
bytes, 0, bytes.length, address1.getAddress(), address1.getPort()));
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
latch.countDown();
}
};
ExecutorService executor = Executors.newFixedThreadPool(count);
for (int i = 0 ; i < count; i++) {
executor.execute(r);
}
latch.await();
executor.shutdown();
future.channel().close().syncUninterruptibly();
future2.channel().close().syncUninterruptibly();
assertTrue(received1.get());
assertTrue(received2.get());
}
private static ServerBootstrap createServerBootstrap() {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(EpollSocketTestPermutation.EPOLL_BOSS_GROUP, EpollSocketTestPermutation.EPOLL_WORKER_GROUP);
bootstrap.channel(EpollServerSocketChannel.class);
bootstrap.childHandler(new DummyHandler());
InetSocketAddress address = new InetSocketAddress(NetUtil.LOCALHOST, 0);
bootstrap.localAddress(address);
return bootstrap;
}
private static Bootstrap createBootstrap() {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(EpollSocketTestPermutation.EPOLL_WORKER_GROUP);
bootstrap.channel(EpollDatagramChannel.class);
InetSocketAddress address = new InetSocketAddress(NetUtil.LOCALHOST, 0);
bootstrap.localAddress(address);
return bootstrap;
}
private static boolean versionEqOrGt(int major, int minor, int bugfix) {
if (MAJOR > major) {
return true;
}
if (MAJOR == major) {
if (MINOR > minor) {
return true;
} else if (MINOR == minor) {
if (BUGFIX >= bugfix) {
return true;
}
}
}
return false;
}
@ChannelHandler.Sharable
private static class ServerSocketTestHandler extends ChannelInboundHandlerAdapter {
private final AtomicBoolean accepted;
ServerSocketTestHandler(AtomicBoolean accepted) {
this.accepted = accepted;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
accepted.set(true);
ctx.close();
}
}
@ChannelHandler.Sharable
private static class DatagramSocketTestHandler extends ChannelInboundHandlerAdapter {
private final AtomicBoolean received;
DatagramSocketTestHandler(AtomicBoolean received) {
this.received = received;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ReferenceCountUtil.release(msg);
received.set(true);
}
}
@ChannelHandler.Sharable
private static final class DummyHandler extends ChannelHandlerAdapter { }
}

View file

@ -0,0 +1,103 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import java.net.InetSocketAddress;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollServerSocketChannelConfigTest {
private static EventLoopGroup group;
private static EpollServerSocketChannel ch;
@BeforeAll
public static void before() {
group = new EpollEventLoopGroup(1);
ServerBootstrap bootstrap = new ServerBootstrap();
ch = (EpollServerSocketChannel) bootstrap.group(group)
.channel(EpollServerSocketChannel.class)
.childHandler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
}
@AfterAll
public static void after() {
try {
ch.close().syncUninterruptibly();
} finally {
group.shutdownGracefully();
}
}
@Test
public void testTcpDeferAccept() {
ch.config().setTcpDeferAccept(0);
assertEquals(0, ch.config().getTcpDeferAccept());
ch.config().setTcpDeferAccept(10);
// The returned value may be bigger then what we set.
// See https://www.spinics.net/lists/netdev/msg117330.html
assertTrue(10 <= ch.config().getTcpDeferAccept());
}
@Test
public void testReusePort() {
ch.config().setReusePort(false);
assertFalse(ch.config().isReusePort());
ch.config().setReusePort(true);
assertTrue(ch.config().isReusePort());
}
@Test
public void testFreeBind() {
ch.config().setFreeBind(false);
assertFalse(ch.config().isFreeBind());
ch.config().setFreeBind(true);
assertTrue(ch.config().isFreeBind());
}
@Test
public void getGetOptions() {
Map<ChannelOption<?>, Object> map = ch.config().getOptions();
assertFalse(map.isEmpty());
}
@Test
public void testFastOpen() {
assertThrows(IllegalArgumentException.class, new Executable() {
@Override
public void execute() {
ch.config().setTcpFastopen(-1);
}
});
ch.config().setTcpFastopen(10);
assertEquals(10, ch.config().getTcpFastopen());
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright 2023 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketAddressesTest;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class EpollSocketAddressesTest extends SocketAddressesTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
@Override
protected void assertAddress(SocketAddress address) {
assertTrue(((InetSocketAddress) address).getPort() > 0);
assertFalse(((InetSocketAddress) address).getAddress().isAnyLocalAddress());
}
}

View file

@ -0,0 +1,178 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.github.artsok.RepeatedIfExceptionsTest;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import org.opentest4j.TestAbortedException;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.util.Map;
import java.util.Random;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class EpollSocketChannelConfigTest {
private static EventLoopGroup group;
private static EpollSocketChannel ch;
private static Random rand;
@BeforeAll
public static void beforeClass() {
rand = new Random();
group = new EpollEventLoopGroup(1);
}
@AfterAll
public static void afterClass() {
group.shutdownGracefully();
}
@BeforeEach
public void setup() {
Bootstrap bootstrap = new Bootstrap();
ch = (EpollSocketChannel) bootstrap.group(group)
.channel(EpollSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
}
@AfterEach
public void teardown() {
ch.close().syncUninterruptibly();
}
private static long randLong(long min, long max) {
return min + nextLong(max - min + 1);
}
private static long nextLong(long n) {
long bits, val;
do {
bits = (rand.nextLong() << 1) >>> 1;
val = bits % n;
} while (bits - val + (n - 1) < 0L);
return val;
}
@Test
public void testRandomTcpNotSentLowAt() {
final long expected = randLong(0, 0xFFFFFFFFL);
final long actual;
try {
ch.config().setTcpNotSentLowAt(expected);
actual = ch.config().getTcpNotSentLowAt();
} catch (RuntimeException e) {
throw new TestAbortedException("assumeNoException", e);
}
assertEquals(expected, actual);
}
@Test
public void testInvalidHighTcpNotSentLowAt() {
try {
final long value = 0xFFFFFFFFL + 1;
ch.config().setTcpNotSentLowAt(value);
} catch (IllegalArgumentException e) {
return;
} catch (RuntimeException e) {
throw new TestAbortedException("assumeNoException", e);
}
fail();
}
@Test
public void testInvalidLowTcpNotSentLowAt() {
try {
final long value = -1;
ch.config().setTcpNotSentLowAt(value);
} catch (IllegalArgumentException e) {
return;
} catch (RuntimeException e) {
throw new TestAbortedException("assumeNoException", e);
}
fail();
}
@Test
public void testTcpCork() {
ch.config().setTcpCork(false);
assertFalse(ch.config().isTcpCork());
ch.config().setTcpCork(true);
assertTrue(ch.config().isTcpCork());
}
@Test
public void testTcpQickAck() {
ch.config().setTcpQuickAck(false);
assertFalse(ch.config().isTcpQuickAck());
ch.config().setTcpQuickAck(true);
assertTrue(ch.config().isTcpQuickAck());
}
// For this test to pass, we are relying on the sockets file descriptor not being reused after the socket is closed.
// This is inherently racy, so we allow getSoLinger to throw ChannelException a few of times, but eventually we do
// want to see a ClosedChannelException for the test to pass.
@RepeatedIfExceptionsTest(repeats = 4)
public void testSetOptionWhenClosed() {
ch.close().syncUninterruptibly();
ChannelException e = assertThrows(ChannelException.class, new Executable() {
@Override
public void execute() throws Throwable {
ch.config().setSoLinger(0);
}
});
assertThat(e).hasCauseInstanceOf(ClosedChannelException.class);
}
// For this test to pass, we are relying on the sockets file descriptor not being reused after the socket is closed.
// This is inherently racy, so we allow getSoLinger to throw ChannelException a few of times, but eventually we do
// want to see a ClosedChannelException for the test to pass.
@RepeatedIfExceptionsTest(repeats = 4)
public void testGetOptionWhenClosed() {
ch.close().syncUninterruptibly();
ChannelException e = assertThrows(ChannelException.class, new Executable() {
@Override
public void execute() throws Throwable {
ch.config().getSoLinger();
}
});
assertThat(e).hasCauseInstanceOf(ClosedChannelException.class);
}
@Test
public void getGetOptions() {
Map<ChannelOption<?>, Object> map = ch.config().getOptions();
assertFalse(map.isEmpty());
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketChannelNotYetConnectedTest;
import java.util.List;
public class EpollSocketChannelNotYetConnectedTest extends SocketChannelNotYetConnectedTest {
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.clientSocketWithFastOpen();
}
}

View file

@ -0,0 +1,123 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import org.junit.jupiter.api.Test;
import java.net.InetSocketAddress;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollSocketChannelTest {
@Test
public void testTcpInfo() throws Exception {
EventLoopGroup group = new EpollEventLoopGroup(1);
try {
Bootstrap bootstrap = new Bootstrap();
EpollSocketChannel ch = (EpollSocketChannel) bootstrap.group(group)
.channel(EpollSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
EpollTcpInfo info = ch.tcpInfo();
assertTcpInfo0(info);
ch.close().syncUninterruptibly();
} finally {
group.shutdownGracefully();
}
}
@Test
public void testTcpInfoReuse() throws Exception {
EventLoopGroup group = new EpollEventLoopGroup(1);
try {
Bootstrap bootstrap = new Bootstrap();
EpollSocketChannel ch = (EpollSocketChannel) bootstrap.group(group)
.channel(EpollSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
EpollTcpInfo info = new EpollTcpInfo();
ch.tcpInfo(info);
assertTcpInfo0(info);
ch.close().syncUninterruptibly();
} finally {
group.shutdownGracefully();
}
}
private static void assertTcpInfo0(EpollTcpInfo info) throws Exception {
assertNotNull(info);
assertTrue(info.state() >= 0);
assertTrue(info.caState() >= 0);
assertTrue(info.retransmits() >= 0);
assertTrue(info.probes() >= 0);
assertTrue(info.backoff() >= 0);
assertTrue(info.options() >= 0);
assertTrue(info.sndWscale() >= 0);
assertTrue(info.rcvWscale() >= 0);
assertTrue(info.rto() >= 0);
assertTrue(info.ato() >= 0);
assertTrue(info.sndMss() >= 0);
assertTrue(info.rcvMss() >= 0);
assertTrue(info.unacked() >= 0);
assertTrue(info.sacked() >= 0);
assertTrue(info.lost() >= 0);
assertTrue(info.retrans() >= 0);
assertTrue(info.fackets() >= 0);
assertTrue(info.lastDataSent() >= 0);
assertTrue(info.lastAckSent() >= 0);
assertTrue(info.lastDataRecv() >= 0);
assertTrue(info.lastAckRecv() >= 0);
assertTrue(info.pmtu() >= 0);
assertTrue(info.rcvSsthresh() >= 0);
assertTrue(info.rtt() >= 0);
assertTrue(info.rttvar() >= 0);
assertTrue(info.sndSsthresh() >= 0);
assertTrue(info.sndCwnd() >= 0);
assertTrue(info.advmss() >= 0);
assertTrue(info.reordering() >= 0);
assertTrue(info.rcvRtt() >= 0);
assertTrue(info.rcvSpace() >= 0);
assertTrue(info.totalRetrans() >= 0);
}
// See https://github.com/netty/netty/issues/7159
@Test
public void testSoLingerNoAssertError() throws Exception {
EventLoopGroup group = new EpollEventLoopGroup(1);
try {
Bootstrap bootstrap = new Bootstrap();
EpollSocketChannel ch = (EpollSocketChannel) bootstrap.group(group)
.channel(EpollSocketChannel.class)
.option(ChannelOption.SO_LINGER, 10)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
ch.close().syncUninterruptibly();
} finally {
group.shutdownGracefully();
}
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2017 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketCloseForciblyTest;
import java.util.List;
public class EpollSocketCloseForciblyTest extends SocketCloseForciblyTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketConnectTest;
import java.util.List;
public class EpollSocketConnectTest extends SocketConnectTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketConnectionAttemptTest;
import java.util.List;
public class EpollSocketConnectionAttemptTest extends SocketConnectionAttemptTest {
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.clientSocket();
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketEchoTest;
import java.util.List;
public class EpollSocketEchoTest extends SocketEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketFileRegionTest;
import java.util.List;
public class EpollSocketFileRegionTest extends SocketFileRegionTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketFixedLengthEchoTest;
import java.util.List;
public class EpollSocketFixedLengthEchoTest extends SocketFixedLengthEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketGatheringWriteTest;
import java.util.List;
public class EpollSocketGatheringWriteTest extends SocketGatheringWriteTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketMultipleConnectTest;
import java.util.ArrayList;
import java.util.List;
public class EpollSocketMultipleConnectTest extends SocketMultipleConnectTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> factories
= new ArrayList<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>>();
for (TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap> comboFactory
: EpollSocketTestPermutation.INSTANCE.socketWithFastOpen()) {
EventLoopGroup group = comboFactory.newClientInstance().config().group();
if (group instanceof NioEventLoopGroup || group instanceof EpollEventLoopGroup) {
factories.add(comboFactory);
}
}
return factories;
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketObjectEchoTest;
import java.util.List;
public class EpollSocketObjectEchoTest extends SocketObjectEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.unix.Errors;
import io.netty.channel.unix.Errors.NativeIoException;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketRstTest;
import java.io.IOException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollSocketRstTest extends SocketRstTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithoutFastOpen();
}
@Override
protected void assertRstOnCloseException(IOException cause, Channel clientChannel) {
if (!AbstractEpollChannel.class.isInstance(clientChannel)) {
super.assertRstOnCloseException(cause, clientChannel);
return;
}
assertTrue(cause instanceof NativeIoException,
"actual [type, message]: [" + cause.getClass() + ", " + cause.getMessage() + "]");
assertEquals(Errors.ERRNO_ECONNRESET_NEGATIVE, ((NativeIoException) cause).expectedErr());
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketShutdownOutputByPeerTest;
import java.util.List;
public class EpollSocketShutdownOutputByPeerTest extends SocketShutdownOutputByPeerTest {
@Override
protected List<TestsuitePermutation.BootstrapFactory<ServerBootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.serverSocket();
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketShutdownOutputBySelfTest;
import java.util.List;
public class EpollSocketShutdownOutputBySelfTest extends SocketShutdownOutputBySelfTest {
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.clientSocket();
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslClientRenegotiateTest;
import java.util.List;
public class EpollSocketSslClientRenegotiateTest extends SocketSslClientRenegotiateTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslEchoTest;
import java.util.List;
public class EpollSocketSslEchoTest extends SocketSslEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslGreetingTest;
import java.util.List;
public class EpollSocketSslGreetingTest extends SocketSslGreetingTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketSslSessionReuseTest;
import java.util.List;
public class EpollSocketSslSessionReuseTest extends SocketSslSessionReuseTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketStartTlsTest;
import java.util.List;
public class EpollSocketStartTlsTest extends SocketStartTlsTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,100 @@
/*
* Copyright 2018 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SelectStrategy;
import io.netty.channel.SelectStrategyFactory;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapComboFactory;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.testsuite.transport.socket.SocketStringEchoTest;
import io.netty.util.IntSupplier;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import java.util.ArrayList;
import java.util.List;
public class EpollSocketStringEchoBusyWaitTest extends SocketStringEchoTest {
private static EventLoopGroup EPOLL_LOOP;
@BeforeAll
public static void setup() throws Exception {
EPOLL_LOOP = new EpollEventLoopGroup(2, new DefaultThreadFactory("testsuite-epoll-busy-wait", true),
new SelectStrategyFactory() {
@Override
public SelectStrategy newSelectStrategy() {
return new SelectStrategy() {
@Override
public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) {
return SelectStrategy.BUSY_WAIT;
}
};
}
});
}
@AfterAll
public static void teardown() throws Exception {
if (EPOLL_LOOP != null) {
EPOLL_LOOP.shutdownGracefully();
}
}
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> list =
new ArrayList<BootstrapComboFactory<ServerBootstrap, Bootstrap>>();
final BootstrapFactory<ServerBootstrap> sbf = serverSocket();
final BootstrapFactory<Bootstrap> cbf = clientSocket();
list.add(new BootstrapComboFactory<ServerBootstrap, Bootstrap>() {
@Override
public ServerBootstrap newServerInstance() {
return sbf.newInstance();
}
@Override
public Bootstrap newClientInstance() {
return cbf.newInstance();
}
});
return list;
}
private static BootstrapFactory<ServerBootstrap> serverSocket() {
return new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(EPOLL_LOOP, EPOLL_LOOP).channel(EpollServerSocketChannel.class);
}
};
}
private static BootstrapFactory<Bootstrap> clientSocket() {
return new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_LOOP).channel(EpollSocketChannel.class);
}
};
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.SocketStringEchoTest;
import java.util.List;
public class EpollSocketStringEchoTest extends SocketStringEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.socketWithFastOpen();
}
}

View file

@ -0,0 +1,123 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.ConnectTimeoutException;
import io.netty.channel.EventLoopGroup;
import io.netty.util.CharsetUtil;
import io.netty.util.NetUtil;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class EpollSocketTcpMd5Test {
private static final byte[] SERVER_KEY = "abc".getBytes(CharsetUtil.US_ASCII);
private static final byte[] BAD_KEY = "def".getBytes(CharsetUtil.US_ASCII);
private static EventLoopGroup GROUP;
private EpollServerSocketChannel server;
@BeforeAll
public static void beforeClass() {
GROUP = new EpollEventLoopGroup(1);
}
@AfterAll
public static void afterClass() {
GROUP.shutdownGracefully();
}
@BeforeEach
public void setup() {
Bootstrap bootstrap = new Bootstrap();
server = (EpollServerSocketChannel) bootstrap.group(GROUP)
.channel(EpollServerSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(NetUtil.LOCALHOST4, 0)).syncUninterruptibly().channel();
}
@AfterEach
public void teardown() {
server.close().syncUninterruptibly();
}
@Test
public void testServerSocketChannelOption() throws Exception {
server.config().setOption(EpollChannelOption.TCP_MD5SIG,
Collections.<InetAddress, byte[]>singletonMap(NetUtil.LOCALHOST4, SERVER_KEY));
server.config().setOption(EpollChannelOption.TCP_MD5SIG, Collections.<InetAddress, byte[]>emptyMap());
}
@Test
public void testServerOption() throws Exception {
Bootstrap bootstrap = new Bootstrap();
EpollServerSocketChannel ch = (EpollServerSocketChannel) bootstrap.group(GROUP)
.channel(EpollServerSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
ch.config().setOption(EpollChannelOption.TCP_MD5SIG,
Collections.<InetAddress, byte[]>singletonMap(NetUtil.LOCALHOST4, SERVER_KEY));
ch.config().setOption(EpollChannelOption.TCP_MD5SIG, Collections.<InetAddress, byte[]>emptyMap());
ch.close().syncUninterruptibly();
}
@Test
public void testKeyMismatch() throws Exception {
server.config().setOption(EpollChannelOption.TCP_MD5SIG,
Collections.<InetAddress, byte[]>singletonMap(NetUtil.LOCALHOST4, SERVER_KEY));
assertThrows(ConnectTimeoutException.class, new Executable() {
@Override
public void execute() throws Throwable {
EpollSocketChannel client = (EpollSocketChannel) new Bootstrap().group(GROUP)
.channel(EpollSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.option(EpollChannelOption.TCP_MD5SIG,
Collections.<InetAddress, byte[]>singletonMap(NetUtil.LOCALHOST4, BAD_KEY))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
.connect(server.localAddress()).syncUninterruptibly().channel();
client.close().syncUninterruptibly();
}
});
}
@Test
public void testKeyMatch() throws Exception {
server.config().setOption(EpollChannelOption.TCP_MD5SIG,
Collections.<InetAddress, byte[]>singletonMap(NetUtil.LOCALHOST4, SERVER_KEY));
EpollSocketChannel client = (EpollSocketChannel) new Bootstrap().group(GROUP)
.channel(EpollSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.option(EpollChannelOption.TCP_MD5SIG,
Collections.<InetAddress, byte[]>singletonMap(NetUtil.LOCALHOST4, SERVER_KEY))
.connect(server.localAddress()).syncUninterruptibly().channel();
client.close().syncUninterruptibly();
}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.channel.unix.PeerCredentials;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollSocketTest extends SocketTest<LinuxSocket> {
@BeforeAll
public static void loadJNI() {
Epoll.ensureAvailability();
}
@Test
public void testTcpCork() throws Exception {
assertFalse(socket.isTcpCork());
socket.setTcpCork(true);
assertTrue(socket.isTcpCork());
}
@Test
public void testPeerCreds() throws IOException {
LinuxSocket s1 = LinuxSocket.newSocketDomain();
LinuxSocket s2 = LinuxSocket.newSocketDomain();
try {
DomainSocketAddress dsa = UnixTestUtils.newDomainSocketAddress();
s1.bind(dsa);
s1.listen(1);
assertTrue(s2.connect(dsa));
byte [] addr = new byte[64];
s1.accept(addr);
PeerCredentials pc = s1.getPeerCredentials();
assertNotEquals(pc.uid(), -1);
} finally {
s1.close();
s2.close();
}
}
@Override
protected LinuxSocket newSocket() {
return LinuxSocket.newSocketStream();
}
@Override
protected int level() {
// Value for SOL_SOCKET
// See https://github.com/torvalds/linux/blob/v5.17/include/uapi/asm-generic/socket.h
return 1;
}
@Override
protected int optname() {
// Value for SO_REUSEADDR
// See https://github.com/torvalds/linux/blob/v5.17/include/uapi/asm-generic/socket.h
return 2;
}
}

View file

@ -0,0 +1,264 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFactory;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.testsuite.transport.socket.SocketTestPermutation;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static io.netty.channel.epoll.Native.IS_SUPPORTING_TCP_FASTOPEN_CLIENT;
import static io.netty.channel.epoll.Native.IS_SUPPORTING_TCP_FASTOPEN_SERVER;
class EpollSocketTestPermutation extends SocketTestPermutation {
static final EpollSocketTestPermutation INSTANCE = new EpollSocketTestPermutation();
static final EventLoopGroup EPOLL_BOSS_GROUP =
new EpollEventLoopGroup(BOSSES, new DefaultThreadFactory("testsuite-epoll-boss", true));
static final EventLoopGroup EPOLL_WORKER_GROUP =
new EpollEventLoopGroup(WORKERS, new DefaultThreadFactory("testsuite-epoll-worker", true));
@Override
public List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> socket() {
List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> list =
combo(serverSocket(), clientSocketWithFastOpen());
list.remove(list.size() - 1); // Exclude NIO x NIO test
return list;
}
public List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> socketWithoutFastOpen() {
List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> list =
combo(serverSocket(), clientSocket());
list.remove(list.size() - 1); // Exclude NIO x NIO test
return list;
}
@Override
public List<BootstrapFactory<ServerBootstrap>> serverSocket() {
List<BootstrapFactory<ServerBootstrap>> toReturn = new ArrayList<BootstrapFactory<ServerBootstrap>>();
toReturn.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(EPOLL_BOSS_GROUP, EPOLL_WORKER_GROUP)
.channel(EpollServerSocketChannel.class);
}
});
if (IS_SUPPORTING_TCP_FASTOPEN_SERVER) {
toReturn.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
ServerBootstrap serverBootstrap = new ServerBootstrap().group(EPOLL_BOSS_GROUP, EPOLL_WORKER_GROUP)
.channel(EpollServerSocketChannel.class);
serverBootstrap.option(ChannelOption.TCP_FASTOPEN, 5);
return serverBootstrap;
}
});
}
toReturn.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(nioBossGroup, nioWorkerGroup)
.channel(NioServerSocketChannel.class);
}
});
return toReturn;
}
@Override
public List<BootstrapFactory<Bootstrap>> clientSocket() {
List<BootstrapFactory<Bootstrap>> toReturn = new ArrayList<BootstrapFactory<Bootstrap>>();
toReturn.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channel(EpollSocketChannel.class);
}
});
toReturn.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channel(NioSocketChannel.class);
}
});
return toReturn;
}
@Override
public List<BootstrapFactory<Bootstrap>> clientSocketWithFastOpen() {
List<BootstrapFactory<Bootstrap>> factories = clientSocket();
if (IS_SUPPORTING_TCP_FASTOPEN_CLIENT) {
int insertIndex = factories.size() - 1; // Keep NIO fixture last.
factories.add(insertIndex, new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channel(EpollSocketChannel.class)
.option(ChannelOption.TCP_FASTOPEN_CONNECT, true);
}
});
}
return factories;
}
@Override
public List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> datagram(
final InternetProtocolFamily family) {
// Make the list of Bootstrap factories.
List<BootstrapFactory<Bootstrap>> bfs = Arrays.asList(
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() {
@Override
public Channel newChannel() {
return new NioDatagramChannel(family);
}
@Override
public String toString() {
return NioDatagramChannel.class.getSimpleName() + ".class";
}
});
}
},
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channelFactory(new ChannelFactory<Channel>() {
@Override
public Channel newChannel() {
return new EpollDatagramChannel(family);
}
@Override
public String toString() {
return InternetProtocolFamily.class.getSimpleName() + ".class";
}
});
}
}
);
return combo(bfs, bfs);
}
List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> epollOnlyDatagram(
final InternetProtocolFamily family) {
return combo(Collections.singletonList(datagramBootstrapFactory(family)),
Collections.singletonList(datagramBootstrapFactory(family)));
}
private static BootstrapFactory<Bootstrap> datagramBootstrapFactory(final InternetProtocolFamily family) {
return new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channelFactory(new ChannelFactory<Channel>() {
@Override
public Channel newChannel() {
return new EpollDatagramChannel(family);
}
@Override
public String toString() {
return InternetProtocolFamily.class.getSimpleName() + ".class";
}
});
}
};
}
public List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> domainSocket() {
return combo(serverDomainSocket(), clientDomainSocket());
}
public List<BootstrapFactory<ServerBootstrap>> serverDomainSocket() {
return Collections.<BootstrapFactory<ServerBootstrap>>singletonList(
new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(EPOLL_BOSS_GROUP, EPOLL_WORKER_GROUP)
.channel(EpollServerDomainSocketChannel.class);
}
}
);
}
public List<BootstrapFactory<Bootstrap>> clientDomainSocket() {
return Collections.<BootstrapFactory<Bootstrap>>singletonList(
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channel(EpollDomainSocketChannel.class);
}
}
);
}
@Override
public List<BootstrapFactory<Bootstrap>> datagramSocket() {
return Collections.<BootstrapFactory<Bootstrap>>singletonList(
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channel(EpollDatagramChannel.class);
}
}
);
}
public List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> domainDatagram() {
return combo(domainDatagramSocket(), domainDatagramSocket());
}
public List<BootstrapFactory<Bootstrap>> domainDatagramSocket() {
return Collections.<BootstrapFactory<Bootstrap>>singletonList(
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(EPOLL_WORKER_GROUP).channel(EpollDomainDatagramChannel.class);
}
}
);
}
public static DomainSocketAddress newDomainSocketAddress() {
return UnixTestUtils.newDomainSocketAddress();
}
}

View file

@ -0,0 +1,313 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.unix.FileDescriptor;
import io.netty.util.NetUtil;
import io.netty.util.internal.PlatformDependent;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EpollSpliceTest {
private static final int SPLICE_LEN = 32 * 1024;
private static final Random random = new Random();
private static final byte[] data = new byte[1048576];
static {
random.nextBytes(data);
}
@Test
public void spliceToSocket() throws Throwable {
final EchoHandler sh = new EchoHandler();
final EchoHandler ch = new EchoHandler();
EventLoopGroup group = new EpollEventLoopGroup(1);
ServerBootstrap bs = new ServerBootstrap();
bs.channel(EpollServerSocketChannel.class);
bs.group(group).childHandler(sh);
final Channel sc = bs.bind(NetUtil.LOCALHOST, 0).syncUninterruptibly().channel();
ServerBootstrap bs2 = new ServerBootstrap();
bs2.channel(EpollServerSocketChannel.class);
bs2.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bs2.group(group).childHandler(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
ctx.channel().config().setAutoRead(false);
Bootstrap bs = new Bootstrap();
bs.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bs.channel(EpollSocketChannel.class);
bs.group(ctx.channel().eventLoop()).handler(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext context) throws Exception {
final EpollSocketChannel ch = (EpollSocketChannel) ctx.channel();
final EpollSocketChannel ch2 = (EpollSocketChannel) context.channel();
// We are splicing two channels together, at this point we have a tcp proxy which handles all
// the data transfer only in kernel space!
// Integer.MAX_VALUE will splice infinitely.
ch.spliceTo(ch2, Integer.MAX_VALUE).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
future.channel().close();
}
}
});
// Trigger multiple splices to see if partial splicing works as well.
ch2.spliceTo(ch, SPLICE_LEN).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
future.channel().close();
} else {
ch2.spliceTo(ch, SPLICE_LEN).addListener(this);
}
}
});
ctx.channel().config().setAutoRead(true);
}
@Override
public void channelInactive(ChannelHandlerContext context) throws Exception {
context.close();
}
});
bs.connect(sc.localAddress()).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
ctx.close();
} else {
future.channel().closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
ctx.close();
}
});
}
}
});
}
});
Channel pc = bs2.bind(NetUtil.LOCALHOST, 0).syncUninterruptibly().channel();
Bootstrap cb = new Bootstrap();
cb.group(group);
cb.channel(EpollSocketChannel.class);
cb.handler(ch);
Channel cc = cb.connect(pc.localAddress()).syncUninterruptibly().channel();
for (int i = 0; i < data.length;) {
int length = Math.min(random.nextInt(1024 * 64), data.length - i);
ByteBuf buf = Unpooled.wrappedBuffer(data, i, length);
cc.writeAndFlush(buf);
i += length;
}
while (ch.counter < data.length) {
if (sh.exception.get() != null) {
break;
}
if (ch.exception.get() != null) {
break;
}
Thread.sleep(50);
}
while (sh.counter < data.length) {
if (sh.exception.get() != null) {
break;
}
if (ch.exception.get() != null) {
break;
}
Thread.sleep(50);
}
sh.channel.close().sync();
ch.channel.close().sync();
sc.close().sync();
pc.close().sync();
group.shutdownGracefully();
if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) {
throw sh.exception.get();
}
if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) {
throw ch.exception.get();
}
if (sh.exception.get() != null) {
throw sh.exception.get();
}
if (ch.exception.get() != null) {
throw ch.exception.get();
}
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void spliceToFile() throws Throwable {
EventLoopGroup group = new EpollEventLoopGroup(1);
File file = PlatformDependent.createTempFile("netty-splice", null, null);
file.deleteOnExit();
SpliceHandler sh = new SpliceHandler(file);
ServerBootstrap bs = new ServerBootstrap();
bs.channel(EpollServerSocketChannel.class);
bs.group(group).childHandler(sh);
bs.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
Channel sc = bs.bind(NetUtil.LOCALHOST, 0).syncUninterruptibly().channel();
Bootstrap cb = new Bootstrap();
cb.group(group);
cb.channel(EpollSocketChannel.class);
cb.handler(new ChannelInboundHandlerAdapter());
Channel cc = cb.connect(sc.localAddress()).syncUninterruptibly().channel();
for (int i = 0; i < data.length;) {
int length = Math.min(random.nextInt(1024 * 64), data.length - i);
ByteBuf buf = Unpooled.wrappedBuffer(data, i, length);
cc.writeAndFlush(buf);
i += length;
}
while (sh.future2 == null || !sh.future2.isDone() || !sh.future.isDone()) {
if (sh.exception.get() != null) {
break;
}
Thread.sleep(50);
}
sc.close().sync();
cc.close().sync();
if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) {
throw sh.exception.get();
}
byte[] written = new byte[data.length];
FileInputStream in = new FileInputStream(file);
try {
assertEquals(written.length, in.read(written));
assertArrayEquals(data, written);
} finally {
in.close();
group.shutdownGracefully();
}
}
private static class EchoHandler extends SimpleChannelInboundHandler<ByteBuf> {
volatile Channel channel;
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
volatile int counter;
@Override
public void channelActive(ChannelHandlerContext ctx)
throws Exception {
channel = ctx.channel();
}
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
byte[] actual = new byte[in.readableBytes()];
in.readBytes(actual);
int lastIdx = counter;
for (int i = 0; i < actual.length; i ++) {
assertEquals(data[i + lastIdx], actual[i]);
}
if (channel.parent() != null) {
channel.write(Unpooled.wrappedBuffer(actual));
}
counter += actual.length;
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) throws Exception {
if (exception.compareAndSet(null, cause)) {
cause.printStackTrace();
ctx.close();
}
}
}
private static class SpliceHandler extends ChannelInboundHandlerAdapter {
private final File file;
volatile ChannelFuture future;
volatile ChannelFuture future2;
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
SpliceHandler(File file) {
this.file = file;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
final EpollSocketChannel ch = (EpollSocketChannel) ctx.channel();
final FileDescriptor fd = FileDescriptor.from(file);
// splice two halves separately to test starting offset
future = ch.spliceTo(fd, 0, data.length / 2);
future2 = ch.spliceTo(fd, data.length / 2, data.length / 2);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) throws Exception {
if (exception.compareAndSet(null, cause)) {
cause.printStackTrace();
ctx.close();
}
}
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.unix.FileDescriptor;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class EpollTest {
@Test
public void testIsAvailable() {
assertTrue(Epoll.isAvailable());
}
// Testcase for https://github.com/netty/netty/issues/8444
@Test
@Timeout(value = 5000, unit = TimeUnit.MILLISECONDS)
public void testEpollWaitWithTimeOutMinusOne() throws Exception {
final EpollEventArray eventArray = new EpollEventArray(8);
try {
final FileDescriptor epoll = Native.newEpollCreate();
final FileDescriptor timerFd = Native.newTimerFd();
final FileDescriptor eventfd = Native.newEventFd();
Native.epollCtlAdd(epoll.intValue(), timerFd.intValue(), Native.EPOLLIN);
Native.epollCtlAdd(epoll.intValue(), eventfd.intValue(), Native.EPOLLIN);
final AtomicReference<Throwable> ref = new AtomicReference<Throwable>();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
assertEquals(1, Native.epollWait(epoll, eventArray, false));
// This should have been woken up because of eventfd_write.
assertEquals(eventfd.intValue(), eventArray.fd(0));
} catch (Throwable cause) {
ref.set(cause);
}
}
});
t.start();
t.join(1000);
assertTrue(t.isAlive());
Native.eventFdWrite(eventfd.intValue(), 1);
t.join();
assertNull(ref.get());
epoll.close();
timerFd.close();
eventfd.close();
} finally {
eventArray.free();
}
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2019 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.WriteBeforeRegisteredTest;
import java.util.List;
public class EpollWriteBeforeRegisteredTest extends WriteBeforeRegisteredTest {
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return EpollSocketTestPermutation.INSTANCE.clientSocketWithFastOpen();
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.buffer.UnpooledDirectByteBuf;
import io.netty.channel.unix.IovArray;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public abstract class IovArrayTest {
@Test
public void testNotFailsWihtoutMemoryAddress() {
ByteBuf buffer = new NoMemoryAddressByteBuf(128);
IovArray array = new IovArray(buffer);
ByteBuf buf = Unpooled.directBuffer().writeZero(8);
ByteBuf buf2 = new NoMemoryAddressByteBuf(8).writeZero(8);
assertTrue(array.add(buf, 0, buf.readableBytes()));
assertTrue(array.add(buf, 0, buf2.readableBytes()));
assertEquals(2, array.count());
assertEquals(16, array.size());
assertTrue(buf.release());
assertTrue(buf2.release());
assertNotEquals(-1, array.memoryAddress(0));
array.release();
assertEquals(0, buffer.refCnt());
}
private static final class NoMemoryAddressByteBuf extends UnpooledDirectByteBuf {
NoMemoryAddressByteBuf(int capacity) {
super(UnpooledByteBufAllocator.DEFAULT, capacity, Integer.MAX_VALUE);
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new UnsupportedOperationException();
}
}
}

View file

@ -0,0 +1,97 @@
/*
* Copyright 2020 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.channel.unix.Errors.NativeIoException;
import io.netty.channel.unix.Socket;
import java.util.UUID;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class LinuxSocketTest {
@BeforeAll
public static void loadJNI() {
Epoll.ensureAvailability();
}
@Test
public void testBindNonIpv6SocketToInet6AddressThrows() throws Exception {
final LinuxSocket socket = LinuxSocket.newSocketStream(false);
try {
assertThrows(IOException.class, new Executable() {
@Override
public void execute() throws Throwable {
socket.bind(new InetSocketAddress(InetAddress.getByAddress(
new byte[]{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1'}),
0));
}
});
} finally {
socket.close();
}
}
@Test
public void testConnectNonIpv6SocketToInet6AddressThrows() throws Exception {
final LinuxSocket socket = LinuxSocket.newSocketStream(false);
try {
assertThrows(IOException.class,
new Executable() {
@Override
public void execute() throws Throwable {
socket.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[]{
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1'}),
1234));
}
});
} finally {
socket.close();
}
}
@Test
public void testUnixDomainSocketTooLongPathFails() throws IOException {
// Most systems has a limit for UDS path of 108, 255 is generally too long.
StringBuilder socketPath = new StringBuilder("/tmp/");
while (socketPath.length() < 255) {
socketPath.append(UUID.randomUUID());
}
final DomainSocketAddress domainSocketAddress = new DomainSocketAddress(
socketPath.toString());
final Socket socket = Socket.newSocketDomain();
try {
Exception exception = Assertions.assertThrows(NativeIoException.class, new Executable() {
@Override
public void execute() throws Throwable {
socket.bind(domainSocketAddress);
}
});
Assertions.assertTrue(exception.getMessage().contains("too long"));
} finally {
socket.close();
}
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.util.NetUtil;
import org.junit.jupiter.api.Test;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import static io.netty.channel.unix.NativeInetAddress.address;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class NativeTest {
@Test
public void testAddressIpv4() throws Exception {
InetSocketAddress inetAddress = new InetSocketAddress(NetUtil.LOCALHOST4, 9999);
byte[] bytes = new byte[8];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.put(inetAddress.getAddress().getAddress());
buffer.putInt(inetAddress.getPort());
assertEquals(inetAddress, address(buffer.array(), 0, bytes.length));
}
@Test
public void testAddressIpv6() throws Exception {
Inet6Address address = NetUtil.LOCALHOST6;
InetSocketAddress inetAddress = new InetSocketAddress(address, 9999);
byte[] bytes = new byte[24];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.put(address.getAddress());
buffer.putInt(address.getScopeId());
buffer.putInt(inetAddress.getPort());
assertEquals(inetAddress, address(buffer.array(), 0, bytes.length));
}
}

View file

@ -0,0 +1,134 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.unix.Buffer;
import io.netty.channel.unix.Socket;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opentest4j.TestAbortedException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public abstract class SocketTest<T extends Socket> {
protected T socket;
protected abstract T newSocket();
@BeforeEach
public void setup() {
socket = newSocket();
}
@AfterEach
public void tearDown() throws IOException {
socket.close();
}
@Test
public void testKeepAlive() throws Exception {
assertFalse(socket.isKeepAlive());
socket.setKeepAlive(true);
assertTrue(socket.isKeepAlive());
}
@Test
public void testTcpNoDelay() throws Exception {
assertFalse(socket.isTcpNoDelay());
socket.setTcpNoDelay(true);
assertTrue(socket.isTcpNoDelay());
}
@Test
public void testReceivedBufferSize() throws Exception {
int size = socket.getReceiveBufferSize();
int newSize = 65535;
assertTrue(size > 0);
socket.setReceiveBufferSize(newSize);
// Linux usually set it to double what is specified
assertTrue(newSize <= socket.getReceiveBufferSize());
}
@Test
public void testSendBufferSize() throws Exception {
int size = socket.getSendBufferSize();
int newSize = 65535;
assertTrue(size > 0);
socket.setSendBufferSize(newSize);
// Linux usually set it to double what is specified
assertTrue(newSize <= socket.getSendBufferSize());
}
@Test
public void testSoLinger() throws Exception {
assertEquals(-1, socket.getSoLinger());
socket.setSoLinger(10);
assertEquals(10, socket.getSoLinger());
}
@Test
public void testDoubleCloseDoesNotThrow() throws IOException {
Socket socket = Socket.newSocketStream();
socket.close();
socket.close();
}
@Test
public void testTrafficClass() throws IOException {
// IPTOS_THROUGHPUT
final int value = 0x08;
socket.setTrafficClass(value);
assertEquals(value, socket.getTrafficClass());
}
@Test
public void testIntOpt() throws IOException {
socket.setReuseAddress(false);
socket.setIntOpt(level(), optname(), 1);
// Anything which is != 0 is considered enabled
assertNotEquals(0, socket.getIntOpt(level(), optname()));
socket.setIntOpt(level(), optname(), 0);
// This should be disabled again
assertEquals(0, socket.getIntOpt(level(), optname()));
}
@Test
public void testRawOpt() throws IOException {
ByteBuffer buffer = Buffer.allocateDirectWithNativeOrder(4);
buffer.putInt(1).flip();
socket.setRawOpt(level(), optname(), buffer);
ByteBuffer out = ByteBuffer.allocate(4);
socket.getRawOpt(level(), optname(), out);
assertFalse(out.hasRemaining());
out.flip();
assertNotEquals(ByteBuffer.allocate(0), out);
}
protected int level() {
throw new TestAbortedException("Not supported");
}
protected int optname() {
throw new TestAbortedException("Not supported");
}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.epoll;
import io.netty.channel.unix.DomainSocketAddress;
import io.netty.util.internal.PlatformDependent;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
public final class UnixTestUtils {
private static final Object INET_LOOPBACK_UNAVAILABLE = new Object();
private static volatile Object inetLoopbackCache;
/**
* @deprecated Use {@link #newDomainSocketAddress()} instead.
*/
@Deprecated
public static DomainSocketAddress newSocketAddress() {
return newDomainSocketAddress();
}
public static DomainSocketAddress newDomainSocketAddress() {
try {
File file;
do {
file = PlatformDependent.createTempFile("NETTY", "UDS", null);
if (!file.delete()) {
throw new IOException("failed to delete: " + file);
}
} while (file.getAbsolutePath().length() > 128);
return new DomainSocketAddress(file);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* The JDK method may produce IPv4 loopback addresses where {@link io.netty.util.NetUtil#LOCALHOST} might be an
* IPv6 addresses.
* This difference can stress the system in different ways that are important to test.
*/
public static SocketAddress newInetLoopbackSocketAddress() {
Object loopback = inetLoopbackCache;
if (loopback == null) {
inetLoopbackCache = loopback = getLoopbackAddress();
}
assumeTrue(loopback != INET_LOOPBACK_UNAVAILABLE, "InetAddress.getLoopbackAddress() is not available");
return new InetSocketAddress((InetAddress) loopback, 0);
}
private static Object getLoopbackAddress() {
try {
Method method = InetAddress.class.getMethod("getLoopbackAddress");
return method.invoke(null);
} catch (Exception ignore) {
return INET_LOOPBACK_UNAVAILABLE;
}
}
private UnixTestUtils() { }
}

View file

@ -0,0 +1,7 @@
handlers=java.util.logging.ConsoleHandler
.level=ALL
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
jdk.event.security.level=INFO
org.junit.jupiter.engine.execution.ConditionEvaluator.level=OFF

View file

@ -0,0 +1,3 @@
dependencies {
api project(':netty-channel')
}

View file

@ -0,0 +1,245 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.util.Map;
import static io.netty.channel.ChannelOption.SO_RCVBUF;
import static io.netty.channel.ChannelOption.SO_SNDBUF;
import static io.netty.channel.sctp.SctpChannelOption.SCTP_INIT_MAXSTREAMS;
import static io.netty.channel.sctp.SctpChannelOption.SCTP_NODELAY;
/**
* The default {@link SctpChannelConfig} implementation for SCTP.
*/
public class DefaultSctpChannelConfig extends DefaultChannelConfig implements SctpChannelConfig {
private final SctpChannel javaChannel;
public DefaultSctpChannelConfig(io.netty.channel.sctp.SctpChannel channel, SctpChannel javaChannel) {
super(channel);
this.javaChannel = ObjectUtil.checkNotNull(javaChannel, "javaChannel");
// Enable TCP_NODELAY by default if possible.
if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
try {
setSctpNoDelay(true);
} catch (Exception e) {
// Ignore.
}
}
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(),
SO_RCVBUF, SO_SNDBUF, SCTP_NODELAY, SCTP_INIT_MAXSTREAMS);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(ChannelOption<T> option) {
if (option == SO_RCVBUF) {
return (T) Integer.valueOf(getReceiveBufferSize());
}
if (option == SO_SNDBUF) {
return (T) Integer.valueOf(getSendBufferSize());
}
if (option == SCTP_NODELAY) {
return (T) Boolean.valueOf(isSctpNoDelay());
}
if (option == SCTP_INIT_MAXSTREAMS) {
return (T) getInitMaxStreams();
}
return super.getOption(option);
}
@Override
public <T> boolean setOption(ChannelOption<T> option, T value) {
validate(option, value);
if (option == SO_RCVBUF) {
setReceiveBufferSize((Integer) value);
} else if (option == SO_SNDBUF) {
setSendBufferSize((Integer) value);
} else if (option == SCTP_NODELAY) {
setSctpNoDelay((Boolean) value);
} else if (option == SCTP_INIT_MAXSTREAMS) {
setInitMaxStreams((SctpStandardSocketOptions.InitMaxStreams) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public boolean isSctpNoDelay() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_NODELAY);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setSctpNoDelay(boolean sctpNoDelay) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SCTP_NODELAY, sctpNoDelay);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getSendBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setSendBufferSize(int sendBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getReceiveBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setReceiveBufferSize(int receiveBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public SctpStandardSocketOptions.InitMaxStreams getInitMaxStreams() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpChannelConfig setInitMaxStreams(SctpStandardSocketOptions.InitMaxStreams initMaxStreams) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public SctpChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
super.setConnectTimeoutMillis(connectTimeoutMillis);
return this;
}
@Override
@Deprecated
public SctpChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
super.setMaxMessagesPerRead(maxMessagesPerRead);
return this;
}
@Override
public SctpChannelConfig setWriteSpinCount(int writeSpinCount) {
super.setWriteSpinCount(writeSpinCount);
return this;
}
@Override
public SctpChannelConfig setAllocator(ByteBufAllocator allocator) {
super.setAllocator(allocator);
return this;
}
@Override
public SctpChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
super.setRecvByteBufAllocator(allocator);
return this;
}
@Override
public SctpChannelConfig setAutoRead(boolean autoRead) {
super.setAutoRead(autoRead);
return this;
}
@Override
public SctpChannelConfig setAutoClose(boolean autoClose) {
super.setAutoClose(autoClose);
return this;
}
@Override
public SctpChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
return this;
}
@Override
public SctpChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
return this;
}
@Override
public SctpChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
super.setWriteBufferWaterMark(writeBufferWaterMark);
return this;
}
@Override
public SctpChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
super.setMessageSizeEstimator(estimator);
return this;
}
}

View file

@ -0,0 +1,227 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.SctpStandardSocketOptions;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.ServerChannelRecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.util.NetUtil;
import io.netty.util.internal.ObjectUtil;
import java.io.IOException;
import java.util.Map;
/**
* The default {@link SctpServerChannelConfig} implementation for SCTP.
*/
public class DefaultSctpServerChannelConfig extends DefaultChannelConfig implements SctpServerChannelConfig {
private final SctpServerChannel javaChannel;
private volatile int backlog = NetUtil.SOMAXCONN;
/**
* Creates a new instance.
*/
public DefaultSctpServerChannelConfig(
io.netty.channel.sctp.SctpServerChannel channel, SctpServerChannel javaChannel) {
super(channel, new ServerChannelRecvByteBufAllocator());
this.javaChannel = ObjectUtil.checkNotNull(javaChannel, "javaChannel");
}
@Override
public Map<ChannelOption<?>, Object> getOptions() {
return getOptions(
super.getOptions(),
ChannelOption.SO_RCVBUF, ChannelOption.SO_SNDBUF, SctpChannelOption.SCTP_INIT_MAXSTREAMS);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getOption(ChannelOption<T> option) {
if (option == ChannelOption.SO_RCVBUF) {
return (T) Integer.valueOf(getReceiveBufferSize());
}
if (option == ChannelOption.SO_SNDBUF) {
return (T) Integer.valueOf(getSendBufferSize());
}
if (option == SctpChannelOption.SCTP_INIT_MAXSTREAMS) {
return (T) getInitMaxStreams();
}
return super.getOption(option);
}
@Override
public <T> boolean setOption(ChannelOption<T> option, T value) {
validate(option, value);
if (option == ChannelOption.SO_RCVBUF) {
setReceiveBufferSize((Integer) value);
} else if (option == ChannelOption.SO_SNDBUF) {
setSendBufferSize((Integer) value);
} else if (option == SctpChannelOption.SCTP_INIT_MAXSTREAMS) {
setInitMaxStreams((SctpStandardSocketOptions.InitMaxStreams) value);
} else {
return super.setOption(option, value);
}
return true;
}
@Override
public int getSendBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_SNDBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpServerChannelConfig setSendBufferSize(int sendBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_SNDBUF, sendBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getReceiveBufferSize() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SO_RCVBUF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpServerChannelConfig setReceiveBufferSize(int receiveBufferSize) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SO_RCVBUF, receiveBufferSize);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public SctpStandardSocketOptions.InitMaxStreams getInitMaxStreams() {
try {
return javaChannel.getOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
public SctpServerChannelConfig setInitMaxStreams(SctpStandardSocketOptions.InitMaxStreams initMaxStreams) {
try {
javaChannel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, initMaxStreams);
} catch (IOException e) {
throw new ChannelException(e);
}
return this;
}
@Override
public int getBacklog() {
return backlog;
}
@Override
public SctpServerChannelConfig setBacklog(int backlog) {
checkPositiveOrZero(backlog, "backlog");
this.backlog = backlog;
return this;
}
@Override
@Deprecated
public SctpServerChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
super.setMaxMessagesPerRead(maxMessagesPerRead);
return this;
}
@Override
public SctpServerChannelConfig setWriteSpinCount(int writeSpinCount) {
super.setWriteSpinCount(writeSpinCount);
return this;
}
@Override
public SctpServerChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
super.setConnectTimeoutMillis(connectTimeoutMillis);
return this;
}
@Override
public SctpServerChannelConfig setAllocator(ByteBufAllocator allocator) {
super.setAllocator(allocator);
return this;
}
@Override
public SctpServerChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
super.setRecvByteBufAllocator(allocator);
return this;
}
@Override
public SctpServerChannelConfig setAutoRead(boolean autoRead) {
super.setAutoRead(autoRead);
return this;
}
@Override
public SctpServerChannelConfig setAutoClose(boolean autoClose) {
super.setAutoClose(autoClose);
return this;
}
@Override
public SctpServerChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
return this;
}
@Override
public SctpServerChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
return this;
}
@Override
public SctpServerChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
super.setWriteBufferWaterMark(writeBufferWaterMark);
return this;
}
@Override
public SctpServerChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
super.setMessageSizeEstimator(estimator);
return this;
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import com.sun.nio.sctp.Association;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelPromise;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Set;
/**
* A SCTP/IP {@link Channel} interface for single SCTP association.
*
* <p>
* The SctpChannel is a message-oriented, connected transport which supports multi-streaming and multi-homing.
* </p>
*/
public interface SctpChannel extends Channel {
@Override
SctpServerChannel parent();
/**
* Returns the underlying SCTP association.
*/
Association association();
/**
* Return the (primary) local address of the SCTP channel.
*
* Please note that, this return the first local address in the underlying SCTP Channel's
* local address iterator to support Netty Channel API. In other words, its the application's
* responsibility to keep track of it's local primary address.
*
* (To set a local address as primary, the application can request by calling local SCTP stack,
* with SctpStandardSocketOption.SCTP_PRIMARY_ADDR option).
*/
@Override
InetSocketAddress localAddress();
/**
* Return all local addresses of the SCTP channel.
* Please note that, it will return more than one address if this channel is using multi-homing
*/
Set<InetSocketAddress> allLocalAddresses();
/**
* Returns the {@link SctpChannelConfig} configuration of the channel.
*/
@Override
SctpChannelConfig config();
/**
* Return the (primary) remote address of the SCTP channel.
*
* Please note that, this return the first remote address in the underlying SCTP Channel's
* remote address iterator to support Netty Channel API. In other words, its the application's
* responsibility to keep track of it's peer's primary address.
*
* (The application can request it's remote peer to set a specific address as primary by
* calling the local SCTP stack with SctpStandardSocketOption.SCTP_SET_PEER_PRIMARY_ADDR option)
*/
@Override
InetSocketAddress remoteAddress();
/**
* Return all remote addresses of the SCTP server channel.
* Please note that, it will return more than one address if the remote is using multi-homing.
*/
Set<InetSocketAddress> allRemoteAddresses();
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel bust be bound and yet to be connected.
*/
ChannelFuture bindAddress(InetAddress localAddress);
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel bust be bound and yet to be connected.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture bindAddress(InetAddress localAddress, ChannelPromise promise);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*/
ChannelFuture unbindAddress(InetAddress localAddress);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture unbindAddress(InetAddress localAddress, ChannelPromise promise);
}

View file

@ -0,0 +1,135 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelOption;
import io.netty.channel.MessageSizeEstimator;
import io.netty.channel.RecvByteBufAllocator;
import io.netty.channel.WriteBufferWaterMark;
/**
* A {@link ChannelConfig} for a {@link SctpChannel}.
* <p/>
* <h3>Available options</h3>
* <p/>
* In addition to the options provided by {@link ChannelConfig},
* {@link SctpChannelConfig} allows the following options in the option map:
* <p/>
* <table border="1" cellspacing="0" cellpadding="6">
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@link ChannelOption#SO_RCVBUF}</td><td>{@link #setReceiveBufferSize(int)}</td>
* </tr><tr>
* <td>{@link ChannelOption#SO_SNDBUF}</td><td>{@link #setSendBufferSize(int)}</td>
* </tr><tr>
* <td>{@link SctpChannelOption#SCTP_NODELAY}</td><td>{@link #setSctpNoDelay(boolean)}}</td>
* </tr><tr>
* <td>{@link SctpChannelOption#SCTP_INIT_MAXSTREAMS}</td><td>{@link #setInitMaxStreams(InitMaxStreams)}</td>
* </tr>
* </table>
*/
public interface SctpChannelConfig extends ChannelConfig {
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option. Please note that the default value of this option is {@code true} unlike the
* operating system default ({@code false}). However, for some buggy platforms, such as Android, that shows erratic
* behavior with Nagle's algorithm disabled, the default value remains to be {@code false}.
*/
boolean isSctpNoDelay();
/**
* Sets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option. Please note that the default value of this option is {@code true} unlike the
* operating system default ({@code false}). However, for some buggy platforms, such as Android, that shows erratic
* behavior with Nagle's algorithm disabled, the default value remains to be {@code false}.
*/
SctpChannelConfig setSctpNoDelay(boolean sctpNoDelay);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
int getSendBufferSize();
/**
* Sets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_SNDBUF}</a> option.
*/
SctpChannelConfig setSendBufferSize(int sendBufferSize);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
int getReceiveBufferSize();
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SO_RCVBUF}</a> option.
*/
SctpChannelConfig setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
InitMaxStreams getInitMaxStreams();
/**
* Gets the <a href="https://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_INIT_MAXSTREAMS}</a> option.
*/
SctpChannelConfig setInitMaxStreams(InitMaxStreams initMaxStreams);
@Override
SctpChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis);
@Override
@Deprecated
SctpChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead);
@Override
SctpChannelConfig setWriteSpinCount(int writeSpinCount);
@Override
SctpChannelConfig setAllocator(ByteBufAllocator allocator);
@Override
SctpChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator);
@Override
SctpChannelConfig setAutoRead(boolean autoRead);
@Override
SctpChannelConfig setAutoClose(boolean autoClose);
@Override
SctpChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark);
@Override
SctpChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark);
@Override
SctpChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark);
@Override
SctpChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator);
}

View file

@ -0,0 +1,48 @@
/*
* Copyright 2013 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;
import io.netty.channel.ChannelOption;
import java.net.SocketAddress;
/**
* Option for configuring the SCTP transport
*/
public final class SctpChannelOption<T> extends ChannelOption<T> {
public static final ChannelOption<Boolean> SCTP_DISABLE_FRAGMENTS =
valueOf(SctpChannelOption.class, "SCTP_DISABLE_FRAGMENTS");
public static final ChannelOption<Boolean> SCTP_EXPLICIT_COMPLETE =
valueOf(SctpChannelOption.class, "SCTP_EXPLICIT_COMPLETE");
public static final ChannelOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
valueOf(SctpChannelOption.class, "SCTP_FRAGMENT_INTERLEAVE");
public static final ChannelOption<InitMaxStreams> SCTP_INIT_MAXSTREAMS =
valueOf(SctpChannelOption.class, "SCTP_INIT_MAXSTREAMS");
public static final ChannelOption<Boolean> SCTP_NODELAY =
valueOf(SctpChannelOption.class, "SCTP_NODELAY");
public static final ChannelOption<SocketAddress> SCTP_PRIMARY_ADDR =
valueOf(SctpChannelOption.class, "SCTP_PRIMARY_ADDR");
public static final ChannelOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
valueOf(SctpChannelOption.class, "SCTP_SET_PEER_PRIMARY_ADDR");
@SuppressWarnings({ "unused", "deprecation" })
private SctpChannelOption() {
super(null);
}
}

View file

@ -0,0 +1,204 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import com.sun.nio.sctp.MessageInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DefaultByteBufHolder;
import io.netty.util.internal.ObjectUtil;
/**
* Representation of SCTP Data Chunk
*/
public final class SctpMessage extends DefaultByteBufHolder {
private final int streamIdentifier;
private final int protocolIdentifier;
private final boolean unordered;
private final MessageInfo msgInfo;
/**
* Essential data that is being carried within SCTP Data Chunk
* @param protocolIdentifier of payload
* @param streamIdentifier that you want to send the payload
* @param payloadBuffer channel buffer
*/
public SctpMessage(int protocolIdentifier, int streamIdentifier, ByteBuf payloadBuffer) {
this(protocolIdentifier, streamIdentifier, false, payloadBuffer);
}
/**
* Essential data that is being carried within SCTP Data Chunk
* @param protocolIdentifier of payload
* @param streamIdentifier that you want to send the payload
* @param unordered if {@literal true}, the SCTP Data Chunk will be sent with the U (unordered) flag set.
* @param payloadBuffer channel buffer
*/
public SctpMessage(int protocolIdentifier, int streamIdentifier, boolean unordered, ByteBuf payloadBuffer) {
super(payloadBuffer);
this.protocolIdentifier = protocolIdentifier;
this.streamIdentifier = streamIdentifier;
this.unordered = unordered;
msgInfo = null;
}
/**
* Essential data that is being carried within SCTP Data Chunk
* @param msgInfo the {@link MessageInfo}
* @param payloadBuffer channel buffer
*/
public SctpMessage(MessageInfo msgInfo, ByteBuf payloadBuffer) {
super(payloadBuffer);
this.msgInfo = ObjectUtil.checkNotNull(msgInfo, "msgInfo");
this.streamIdentifier = msgInfo.streamNumber();
this.protocolIdentifier = msgInfo.payloadProtocolID();
this.unordered = msgInfo.isUnordered();
}
/**
* Return the stream-identifier
*/
public int streamIdentifier() {
return streamIdentifier;
}
/**
* Return the protocol-identifier
*/
public int protocolIdentifier() {
return protocolIdentifier;
}
/**
* return the unordered flag
*/
public boolean isUnordered() {
return unordered;
}
/**
* Return the {@link MessageInfo} for inbound messages or {@code null} for
* outbound messages.
*/
public MessageInfo messageInfo() {
return msgInfo;
}
/**
* Return {@code true} if this message is complete.
*/
public boolean isComplete() {
if (msgInfo != null) {
return msgInfo.isComplete();
} else {
//all outbound sctp messages are complete
return true;
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SctpMessage sctpFrame = (SctpMessage) o;
if (protocolIdentifier != sctpFrame.protocolIdentifier) {
return false;
}
if (streamIdentifier != sctpFrame.streamIdentifier) {
return false;
}
if (unordered != sctpFrame.unordered) {
return false;
}
return content().equals(sctpFrame.content());
}
@Override
public int hashCode() {
int result = streamIdentifier;
result = 31 * result + protocolIdentifier;
// values 1231 and 1237 are referenced in the javadocs of Boolean#hashCode()
result = 31 * result + (unordered ? 1231 : 1237);
result = 31 * result + content().hashCode();
return result;
}
@Override
public SctpMessage copy() {
return (SctpMessage) super.copy();
}
@Override
public SctpMessage duplicate() {
return (SctpMessage) super.duplicate();
}
@Override
public SctpMessage retainedDuplicate() {
return (SctpMessage) super.retainedDuplicate();
}
@Override
public SctpMessage replace(ByteBuf content) {
if (msgInfo == null) {
return new SctpMessage(protocolIdentifier, streamIdentifier, unordered, content);
} else {
return new SctpMessage(msgInfo, content);
}
}
@Override
public SctpMessage retain() {
super.retain();
return this;
}
@Override
public SctpMessage retain(int increment) {
super.retain(increment);
return this;
}
@Override
public SctpMessage touch() {
super.touch();
return this;
}
@Override
public SctpMessage touch(Object hint) {
super.touch(hint);
return this;
}
@Override
public String toString() {
return "SctpFrame{" +
"streamIdentifier=" + streamIdentifier + ", protocolIdentifier=" + protocolIdentifier +
", unordered=" + unordered +
", data=" + contentToString() + '}';
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import com.sun.nio.sctp.AbstractNotificationHandler;
import com.sun.nio.sctp.AssociationChangeNotification;
import com.sun.nio.sctp.HandlerResult;
import com.sun.nio.sctp.Notification;
import com.sun.nio.sctp.PeerAddressChangeNotification;
import com.sun.nio.sctp.SendFailedNotification;
import com.sun.nio.sctp.ShutdownNotification;
import io.netty.channel.ChannelPipeline;
import io.netty.util.internal.ObjectUtil;
/**
* {@link AbstractNotificationHandler} implementation which will handle all {@link Notification}s by trigger a
* {@link Notification} user event in the {@link ChannelPipeline} of a {@link SctpChannel}.
*/
public final class SctpNotificationHandler extends AbstractNotificationHandler<Object> {
private final SctpChannel sctpChannel;
public SctpNotificationHandler(SctpChannel sctpChannel) {
this.sctpChannel = ObjectUtil.checkNotNull(sctpChannel, "sctpChannel");
}
@Override
public HandlerResult handleNotification(AssociationChangeNotification notification, Object o) {
fireEvent(notification);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(PeerAddressChangeNotification notification, Object o) {
fireEvent(notification);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(SendFailedNotification notification, Object o) {
fireEvent(notification);
return HandlerResult.CONTINUE;
}
@Override
public HandlerResult handleNotification(ShutdownNotification notification, Object o) {
fireEvent(notification);
sctpChannel.close();
return HandlerResult.RETURN;
}
private void fireEvent(Notification notification) {
sctpChannel.pipeline().fireUserEventTriggered(notification);
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright 2011 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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 io.netty.channel.sctp;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ServerChannel;
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.util.Set;
/**
* A SCTP/IP {@link ServerChannel} which accepts incoming SCTP/IP associations.
*
* <p>
* Multi-homing address binding/unbinding can done through bindAddress/unbindAddress methods.
* </p>
*/
public interface SctpServerChannel extends ServerChannel {
/**
* Returns the {@link SctpServerChannelConfig} configuration of the channel.
*/
@Override
SctpServerChannelConfig config();
/**
* Return the (primary) local address of the SCTP server channel.
*
* Please note that, this return the first local address in the underlying SCTP ServerChannel's
* local address iterator to support Netty Channel API. In other words, its the application's
* responsibility to keep track of it's local primary address.
*
* (To set a local address as primary, the application can request by calling local SCTP stack,
* with SctpStandardSocketOption.SCTP_PRIMARY_ADDR option).
*/
@Override
InetSocketAddress localAddress();
/**
* Return all local addresses of the SCTP server channel.
* Please note that, it will return more than one address if this channel is using multi-homing
*/
Set<InetSocketAddress> allLocalAddresses();
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel must be bound and yet to be connected.
*/
ChannelFuture bindAddress(InetAddress localAddress);
/**
* Bind a address to the already bound channel to enable multi-homing.
* The Channel must be bound and yet to be connected.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture bindAddress(InetAddress localAddress, ChannelPromise promise);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*/
ChannelFuture unbindAddress(InetAddress localAddress);
/**
* Unbind the address from channel's multi-homing address list.
* The address should be added already in multi-homing address list.
*
* Will notify the given {@link ChannelPromise} and return a {@link ChannelFuture}
*/
ChannelFuture unbindAddress(InetAddress localAddress, ChannelPromise promise);
}

Some files were not shown because too many files have changed in this diff Show more