Compare commits
No commits in common. "52d3d16cb09bd13e93dd79e58f6481dae1d09e72" and "49b6c772a5d3b263dee40c8194021c44fe800f81" have entirely different histories.
52d3d16cb0
...
49b6c772a5
481 changed files with 2345 additions and 52890 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,6 +2,7 @@
|
||||||
/.classpath
|
/.classpath
|
||||||
/.project
|
/.project
|
||||||
/.gradle
|
/.gradle
|
||||||
|
**/data
|
||||||
**/work
|
**/work
|
||||||
**/logs
|
**/logs
|
||||||
**/.idea
|
**/.idea
|
||||||
|
@ -11,3 +12,5 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.iml
|
*.iml
|
||||||
*~
|
*~
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
|
11
NOTICE.txt
11
NOTICE.txt
|
@ -25,7 +25,6 @@ The following changes were performed on the original source code:
|
||||||
- removed all macos related code (including kqueue)
|
- removed all macos related code (including kqueue)
|
||||||
- removed all aarch64 related code
|
- removed all aarch64 related code
|
||||||
- removed the direct brotli4j dependency by rewriting Brotli4jOptions to not use Encoder.Parameters
|
- 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
|
Challenges for Netty build on JDK 21
|
||||||
|
|
||||||
|
@ -42,12 +41,12 @@ Subproject organization
|
||||||
Original netty subproject names are not related to package names. I reorganized the names to allow better assignment
|
Original netty subproject names are not related to package names. I reorganized the names to allow better assignment
|
||||||
between subproject name, package name, artifact names, and java module. The following reorgnizations were performed:
|
between subproject name, package name, artifact names, and java module. The following reorgnizations were performed:
|
||||||
|
|
||||||
netty/all ->
|
netty/all -> [todo]
|
||||||
netty/bom ->
|
netty/bom -> [todo]
|
||||||
netty/buffer -> netty-buffer
|
netty/buffer -> netty-buffer
|
||||||
netty/codec -> netty-handler-codec, netty-handler-codec-compression, netty-handler-codec-protobuf
|
netty/codec -> netty-handler-codec, netty-handler-codec-compression, netty-handler-codec-protobuf
|
||||||
netty/codec-dns -> netty-handler-codec-dns
|
netty/codec-dns -> [todo]
|
||||||
netty/codec-haproxy ->
|
netty/codec-haproxy -> [todo]
|
||||||
netty/codec-http -> netty-handler-codec-http, netty-handler-codec-rtsp, netty-handler-codec-spdy
|
netty/codec-http -> netty-handler-codec-http, netty-handler-codec-rtsp, netty-handler-codec-spdy
|
||||||
netty/codec-http2 ->
|
netty/codec-http2 ->
|
||||||
netty/codec-memcache ->
|
netty/codec-memcache ->
|
||||||
|
@ -62,7 +61,7 @@ netty/handler -> netty-handler
|
||||||
netty/handler-proxy
|
netty/handler-proxy
|
||||||
netty/handler-ssl-ocsp
|
netty/handler-ssl-ocsp
|
||||||
netty/resolver -> netty-resolver
|
netty/resolver -> netty-resolver
|
||||||
netty/resolver-dns -> netty-resolver-dns
|
netty/resolver-dns ->
|
||||||
netty/resolver-dns-classes-macos -> [dropped]
|
netty/resolver-dns-classes-macos -> [dropped]
|
||||||
netty/resolver-dns-native-macos -> [dropped]
|
netty/resolver-dns-native-macos -> [dropped]
|
||||||
netty/transport -> netty-channel
|
netty/transport -> netty-channel
|
||||||
|
|
|
@ -11,6 +11,8 @@ wrapper {
|
||||||
distributionType = Wrapper.DistributionType.BIN
|
distributionType = Wrapper.DistributionType.BIN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.google.osdetector'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
user = 'joerg'
|
user = 'joerg'
|
||||||
name = 'netty'
|
name = 'netty'
|
||||||
|
@ -28,15 +30,11 @@ ext {
|
||||||
organizationUrl = 'https://xbib.org'
|
organizationUrl = 'https://xbib.org'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.osdetector'
|
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
if (!it.name.endsWith('-native') && it.name != 'test-results') {
|
|
||||||
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
||||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||||
apply from: rootProject.file('gradle/publish/maven.gradle')
|
apply from: rootProject.file('gradle/publish/maven.gradle')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
apply from: rootProject.file('gradle/publish/sonatype.gradle')
|
apply from: rootProject.file('gradle/publish/sonatype.gradle')
|
||||||
apply from: rootProject.file('gradle/publish/forgejo.gradle')
|
apply from: rootProject.file('gradle/publish/forgejo.gradle')
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
group = org.xbib.netty
|
group = org.xbib.netty
|
||||||
name = netty
|
name = netty
|
||||||
version = 4.1.107.0
|
version = 4.1.104
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
apply plugin: 'base'
|
|
||||||
apply plugin: 'org.xbib.gradle.plugin.c'
|
|
|
@ -1 +0,0 @@
|
||||||
apply plugin: 'org.xbib.gradle.plugin.cmake'
|
|
|
@ -10,8 +10,11 @@ dependencies {
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
failFast = false
|
failFast = true
|
||||||
ignoreFailures = true
|
testLogging {
|
||||||
|
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
||||||
|
showStandardStreams = true
|
||||||
|
}
|
||||||
minHeapSize = "1g" // initial heap size
|
minHeapSize = "1g" // initial heap size
|
||||||
maxHeapSize = "2g" // maximum heap size
|
maxHeapSize = "2g" // maximum heap size
|
||||||
jvmArgs '--add-exports=java.base/jdk.internal=ALL-UNNAMED',
|
jvmArgs '--add-exports=java.base/jdk.internal=ALL-UNNAMED',
|
||||||
|
@ -27,10 +30,11 @@ test {
|
||||||
'--add-opens=jdk.unsupported/sun.misc=ALL-UNNAMED',
|
'--add-opens=jdk.unsupported/sun.misc=ALL-UNNAMED',
|
||||||
'-Dio.netty.bootstrap.extensions=serviceload'
|
'-Dio.netty.bootstrap.extensions=serviceload'
|
||||||
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
|
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
|
||||||
testLogging {
|
// we have remove native images, this is no longer used
|
||||||
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
systemProperty "nativeImage.handlerMetadataGroupId", "io.netty"
|
||||||
showStandardStreams = true
|
// we have remove native images
|
||||||
}
|
// we have remove native images, this is no longer used
|
||||||
|
systemProperty "nativeimage.handlerMetadataArtifactId", "netty-transport"
|
||||||
afterSuite { desc, result ->
|
afterSuite { desc, result ->
|
||||||
if (!desc.parent) {
|
if (!desc.parent) {
|
||||||
println "\nTest result: ${result.resultType}"
|
println "\nTest result: ${result.resultType}"
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
20
gradlew.bat
vendored
20
gradlew.bat
vendored
|
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
handlers=java.util.logging.ConsoleHandler
|
handlers=java.util.logging.ConsoleHandler
|
||||||
.level=INFO
|
.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.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=INFO
|
java.util.logging.ConsoleHandler.level=ALL
|
||||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||||
jdk.event.security.level=INFO
|
jdk.event.security.level=INFO
|
||||||
org.junit.jupiter.engine.execution.ConditionEvaluator.level=OFF
|
org.junit.jupiter.engine.execution.ConditionEvaluator.level=OFF
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
|
|
||||||
/* currently we do not build our C code natively, but we provide copies of the binaries in META-INF/native */
|
|
||||||
|
|
||||||
apply plugin: 'base'
|
|
||||||
|
|
||||||
task nettyEpollLinuxX8664(type: Jar) {
|
|
||||||
destinationDirectory.set(project.layout.buildDirectory.dir('libs'))
|
|
||||||
archiveBaseName.set(project.name + '-' + project.version)
|
|
||||||
archiveExtension.set('jar')
|
|
||||||
archiveClassifier.set('linux-x86_64')
|
|
||||||
version rootProject.version
|
|
||||||
from (project.layout.projectDirectory.dir('src/main/resources')) {
|
|
||||||
include 'META-INF/native/libnetty_transport_native_epoll_x86_64.so'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assemble.dependsOn(nettyEpollLinuxX8664)
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
'linux-x86_64' {
|
|
||||||
canBeConsumed = true
|
|
||||||
canBeResolved = false
|
|
||||||
/*attributes {
|
|
||||||
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY))
|
|
||||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
|
|
||||||
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL))
|
|
||||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, JavaVersion.current().majorVersion.toInteger())
|
|
||||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements, 'linux-x86_64'))
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,909 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Since glibc 2.8, the _GNU_SOURCE feature test macro must be defined
|
|
||||||
* (before including any header files) in order to obtain the
|
|
||||||
* definition of the ucred structure. See <a href=https://linux.die.net/man/7/unix>
|
|
||||||
*/
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/udp.h> // SOL_UDP
|
|
||||||
#include <sys/sendfile.h>
|
|
||||||
#include <linux/tcp.h> // TCP_NOTSENT_LOWAT is a linux specific define
|
|
||||||
#include "netty_epoll_linuxsocket.h"
|
|
||||||
#include "netty_epoll_vmsocket.h"
|
|
||||||
#include "netty_unix_errors.h"
|
|
||||||
#include "netty_unix_filedescriptor.h"
|
|
||||||
#include "netty_unix_jni.h"
|
|
||||||
#include "netty_unix_socket.h"
|
|
||||||
#include "netty_unix_util.h"
|
|
||||||
|
|
||||||
#define LINUXSOCKET_CLASSNAME "io/netty/channel/epoll/LinuxSocket"
|
|
||||||
|
|
||||||
// TCP_FASTOPEN is defined in linux 3.7. We define this here so older kernels can compile.
|
|
||||||
#ifndef TCP_FASTOPEN
|
|
||||||
#define TCP_FASTOPEN 23
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TCP_FASTOPEN_CONNECT is defined in linux 4.11. We define this here so older kernels can compile.
|
|
||||||
#ifndef TCP_FASTOPEN_CONNECT
|
|
||||||
#define TCP_FASTOPEN_CONNECT 30
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TCP_NOTSENT_LOWAT is defined in linux 3.12. We define this here so older kernels can compile.
|
|
||||||
#ifndef TCP_NOTSENT_LOWAT
|
|
||||||
#define TCP_NOTSENT_LOWAT 25
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// SO_BUSY_POLL is defined in linux 3.11. We define this here so older kernels can compile.
|
|
||||||
#ifndef SO_BUSY_POLL
|
|
||||||
#define SO_BUSY_POLL 46
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// UDP_GRO is defined in linux 5. We define this here so older kernels can compile.
|
|
||||||
#ifndef UDP_GRO
|
|
||||||
#define UDP_GRO 104
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static jweak peerCredentialsClassWeak = NULL;
|
|
||||||
static jmethodID peerCredentialsMethodId = NULL;
|
|
||||||
|
|
||||||
static jfieldID fileChannelFieldId = NULL;
|
|
||||||
static jfieldID transferredFieldId = NULL;
|
|
||||||
static jfieldID fdFieldId = NULL;
|
|
||||||
static jfieldID fileDescriptorFieldId = NULL;
|
|
||||||
|
|
||||||
// JNI Registered Methods Begin
|
|
||||||
static jint netty_epoll_linuxsocket_newVSockStreamFd(JNIEnv* env, jclass clazz) {
|
|
||||||
int fd = netty_unix_socket_nonBlockingSocket(AF_VSOCK, SOCK_STREAM, 0);
|
|
||||||
if (fd == -1) {
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_bindVSock(JNIEnv* env, jclass clazz, jint fd, jint cid, jint port) {
|
|
||||||
struct sockaddr_vm addr;
|
|
||||||
memset(&addr, 0, sizeof(struct sockaddr_vm));
|
|
||||||
|
|
||||||
addr.svm_family = AF_VSOCK;
|
|
||||||
addr.svm_port = port;
|
|
||||||
addr.svm_cid = cid;
|
|
||||||
|
|
||||||
int res = bind(fd, (struct sockaddr*) &addr, sizeof(struct sockaddr_vm));
|
|
||||||
|
|
||||||
if (res == -1) {
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_connectVSock(JNIEnv* env, jclass clazz, jint fd, jint cid, jint port) {
|
|
||||||
struct sockaddr_vm addr;
|
|
||||||
memset(&addr, 0, sizeof(struct sockaddr_vm));
|
|
||||||
addr.svm_family = AF_VSOCK;
|
|
||||||
addr.svm_port = port;
|
|
||||||
addr.svm_cid = cid;
|
|
||||||
|
|
||||||
int res;
|
|
||||||
int err;
|
|
||||||
do {
|
|
||||||
res = connect(fd, (struct sockaddr*) &addr, sizeof(struct sockaddr_vm));
|
|
||||||
} while (res == -1 && ((err = errno) == EINTR));
|
|
||||||
|
|
||||||
if (res == -1) {
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jbyteArray createVSockAddressArray(JNIEnv* env, const struct sockaddr_vm* addr) {
|
|
||||||
jbyteArray bArray = (*env)->NewByteArray(env, 8);
|
|
||||||
if (bArray == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int cid = (addr->svm_cid);
|
|
||||||
unsigned int port = (addr->svm_port);
|
|
||||||
|
|
||||||
unsigned char a[4];
|
|
||||||
a[0] = cid >> 24;
|
|
||||||
a[1] = cid >> 16;
|
|
||||||
a[2] = cid >> 8;
|
|
||||||
a[3] = cid;
|
|
||||||
(*env)->SetByteArrayRegion(env, bArray, 0, 4, (jbyte*) &a);
|
|
||||||
|
|
||||||
a[0] = port >> 24;
|
|
||||||
a[1] = port >> 16;
|
|
||||||
a[2] = port >> 8;
|
|
||||||
a[3] = port;
|
|
||||||
(*env)->SetByteArrayRegion(env, bArray, 4, 4, (jbyte*) &a);
|
|
||||||
return bArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jbyteArray netty_epoll_linuxsocket_remoteVSockAddress(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
struct sockaddr_vm addr = { 0 };
|
|
||||||
socklen_t len = sizeof(addr);
|
|
||||||
if (getpeername(fd, (struct sockaddr*) &addr, &len) == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return createVSockAddressArray(env, &addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jbyteArray netty_epoll_linuxsocket_localVSockAddress(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
struct sockaddr_vm addr = { 0 };
|
|
||||||
socklen_t len = sizeof(addr);
|
|
||||||
if (getsockname(fd, (struct sockaddr*) &addr, &len) == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return createVSockAddressArray(env, &addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTimeToLive(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_TTL, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setIpMulticastLoop(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jint optval) {
|
|
||||||
if (ipv6 == JNI_TRUE) {
|
|
||||||
u_int val = (u_int) optval;
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, sizeof(val));
|
|
||||||
} else {
|
|
||||||
u_char val = (u_char) optval;
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof(val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setInterface(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jbyteArray interfaceAddress, jint scopeId, jint interfaceIndex) {
|
|
||||||
struct sockaddr_storage interfaceAddr;
|
|
||||||
socklen_t interfaceAddrSize;
|
|
||||||
struct sockaddr_in* interfaceIpAddr;
|
|
||||||
|
|
||||||
memset(&interfaceAddr, 0, sizeof(interfaceAddr));
|
|
||||||
|
|
||||||
if (ipv6 == JNI_TRUE) {
|
|
||||||
if (interfaceIndex == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Unable to find network index");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &interfaceIndex, sizeof(interfaceIndex));
|
|
||||||
} else {
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, interfaceAddress, scopeId, 0, &interfaceAddr, &interfaceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
interfaceIpAddr = (struct sockaddr_in*) &interfaceAddr;
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &interfaceIpAddr->sin_addr, sizeof(interfaceIpAddr->sin_addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpCork(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpQuickAck(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_QUICKACK, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpDeferAccept(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpNotSentLowAt(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_NOTSENT_LOWAT, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpFastOpen(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_FASTOPEN, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpKeepIdle(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpKeepIntvl(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpKeepCnt(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpUserTimeout(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setIpFreeBind(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_FREEBIND, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setIpTransparent(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, SOL_IP, IP_TRANSPARENT, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setIpRecvOrigDestAddr(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_RECVORIGDSTADDR, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setSoBusyPoll(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, SOL_SOCKET, SO_BUSY_POLL, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_joinGroup(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jbyteArray groupAddress, jbyteArray interfaceAddress, jint scopeId, jint interfaceIndex) {
|
|
||||||
struct sockaddr_storage groupAddr;
|
|
||||||
socklen_t groupAddrSize;
|
|
||||||
struct sockaddr_storage interfaceAddr;
|
|
||||||
socklen_t interfaceAddrSize;
|
|
||||||
struct sockaddr_in* groupIpAddr;
|
|
||||||
struct sockaddr_in* interfaceIpAddr;
|
|
||||||
struct ip_mreq mreq;
|
|
||||||
|
|
||||||
struct sockaddr_in6* groupIp6Addr;
|
|
||||||
struct ipv6_mreq mreq6;
|
|
||||||
|
|
||||||
memset(&groupAddr, 0, sizeof(groupAddr));
|
|
||||||
memset(&interfaceAddr, 0, sizeof(interfaceAddr));
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, groupAddress, scopeId, 0, &groupAddr, &groupAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for groupAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (groupAddr.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, interfaceAddress, scopeId, 0, &interfaceAddr, &interfaceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for interfaceAddr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
interfaceIpAddr = (struct sockaddr_in*) &interfaceAddr;
|
|
||||||
groupIpAddr = (struct sockaddr_in*) &groupAddr;
|
|
||||||
|
|
||||||
memcpy(&mreq.imr_multiaddr, &groupIpAddr->sin_addr, sizeof(groupIpAddr->sin_addr));
|
|
||||||
memcpy(&mreq.imr_interface, &interfaceIpAddr->sin_addr, sizeof(interfaceIpAddr->sin_addr));
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
if (interfaceIndex == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Unable to find network index");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mreq6.ipv6mr_interface = interfaceIndex;
|
|
||||||
|
|
||||||
groupIp6Addr = (struct sockaddr_in6*) &groupAddr;
|
|
||||||
memcpy(&mreq6.ipv6mr_multiaddr, &groupIp6Addr->sin6_addr, sizeof(groupIp6Addr->sin6_addr));
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
netty_unix_errors_throwIOException(env, "Address family not supported");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_joinSsmGroup(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jbyteArray groupAddress, jbyteArray interfaceAddress, jint scopeId, jint interfaceIndex, jbyteArray sourceAddress) {
|
|
||||||
struct sockaddr_storage groupAddr;
|
|
||||||
socklen_t groupAddrSize;
|
|
||||||
struct sockaddr_storage interfaceAddr;
|
|
||||||
socklen_t interfaceAddrSize;
|
|
||||||
struct sockaddr_storage sourceAddr;
|
|
||||||
socklen_t sourceAddrSize;
|
|
||||||
struct sockaddr_in* groupIpAddr;
|
|
||||||
struct sockaddr_in* interfaceIpAddr;
|
|
||||||
struct sockaddr_in* sourceIpAddr;
|
|
||||||
struct ip_mreq_source mreq;
|
|
||||||
|
|
||||||
struct group_source_req mreq6;
|
|
||||||
|
|
||||||
memset(&groupAddr, 0, sizeof(groupAddr));
|
|
||||||
memset(&sourceAddr, 0, sizeof(sourceAddr));
|
|
||||||
memset(&interfaceAddr, 0, sizeof(interfaceAddr));
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, groupAddress, scopeId, 0, &groupAddr, &groupAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for groupAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, sourceAddress, scopeId, 0, &sourceAddr, &sourceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for sourceAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (groupAddr.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, interfaceAddress, scopeId, 0, &interfaceAddr, &interfaceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for interfaceAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
interfaceIpAddr = (struct sockaddr_in*) &interfaceAddr;
|
|
||||||
groupIpAddr = (struct sockaddr_in*) &groupAddr;
|
|
||||||
sourceIpAddr = (struct sockaddr_in*) &sourceAddr;
|
|
||||||
memcpy(&mreq.imr_multiaddr, &groupIpAddr->sin_addr, sizeof(groupIpAddr->sin_addr));
|
|
||||||
memcpy(&mreq.imr_interface, &interfaceIpAddr->sin_addr, sizeof(interfaceIpAddr->sin_addr));
|
|
||||||
memcpy(&mreq.imr_sourceaddr, &sourceIpAddr->sin_addr, sizeof(sourceIpAddr->sin_addr));
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq));
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
if (interfaceIndex == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Unable to find network index");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mreq6.gsr_group = groupAddr;
|
|
||||||
mreq6.gsr_interface = interfaceIndex;
|
|
||||||
mreq6.gsr_source = sourceAddr;
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, &mreq6, sizeof(mreq6));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
netty_unix_errors_throwIOException(env, "Address family not supported");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_leaveGroup(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jbyteArray groupAddress, jbyteArray interfaceAddress, jint scopeId, jint interfaceIndex) {
|
|
||||||
struct sockaddr_storage groupAddr;
|
|
||||||
socklen_t groupAddrSize;
|
|
||||||
|
|
||||||
struct sockaddr_storage interfaceAddr;
|
|
||||||
socklen_t interfaceAddrSize;
|
|
||||||
struct sockaddr_in* groupIpAddr;
|
|
||||||
struct sockaddr_in* interfaceIpAddr;
|
|
||||||
struct ip_mreq mreq;
|
|
||||||
|
|
||||||
struct sockaddr_in6* groupIp6Addr;
|
|
||||||
struct ipv6_mreq mreq6;
|
|
||||||
|
|
||||||
memset(&groupAddr, 0, sizeof(groupAddr));
|
|
||||||
memset(&interfaceAddr, 0, sizeof(interfaceAddr));
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, groupAddress, scopeId, 0, &groupAddr, &groupAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for groupAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (groupAddr.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, interfaceAddress, scopeId, 0, &interfaceAddr, &interfaceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for interfaceAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
interfaceIpAddr = (struct sockaddr_in*) &interfaceAddr;
|
|
||||||
groupIpAddr = (struct sockaddr_in*) &groupAddr;
|
|
||||||
|
|
||||||
memcpy(&mreq.imr_multiaddr, &groupIpAddr->sin_addr, sizeof(groupIpAddr->sin_addr));
|
|
||||||
memcpy(&mreq.imr_interface, &interfaceIpAddr->sin_addr, sizeof(interfaceIpAddr->sin_addr));
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
if (interfaceIndex == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Unable to find network index");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mreq6.ipv6mr_interface = interfaceIndex;
|
|
||||||
|
|
||||||
groupIp6Addr = (struct sockaddr_in6*) &groupAddr;
|
|
||||||
memcpy(&mreq6.ipv6mr_multiaddr, &groupIp6Addr->sin6_addr, sizeof(groupIp6Addr->sin6_addr));
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq6, sizeof(mreq6));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
netty_unix_errors_throwIOException(env, "Address family not supported");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_leaveSsmGroup(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jbyteArray groupAddress, jbyteArray interfaceAddress, jint scopeId, jint interfaceIndex, jbyteArray sourceAddress) {
|
|
||||||
struct sockaddr_storage groupAddr;
|
|
||||||
socklen_t groupAddrSize;
|
|
||||||
struct sockaddr_storage interfaceAddr;
|
|
||||||
socklen_t interfaceAddrSize;
|
|
||||||
struct sockaddr_storage sourceAddr;
|
|
||||||
socklen_t sourceAddrSize;
|
|
||||||
struct sockaddr_in* groupIpAddr;
|
|
||||||
struct sockaddr_in* interfaceIpAddr;
|
|
||||||
struct sockaddr_in* sourceIpAddr;
|
|
||||||
|
|
||||||
struct ip_mreq_source mreq;
|
|
||||||
struct group_source_req mreq6;
|
|
||||||
|
|
||||||
memset(&groupAddr, 0, sizeof(groupAddr));
|
|
||||||
memset(&sourceAddr, 0, sizeof(sourceAddr));
|
|
||||||
memset(&interfaceAddr, 0, sizeof(interfaceAddr));
|
|
||||||
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, groupAddress, scopeId, 0, &groupAddr, &groupAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for groupAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, sourceAddress, scopeId, 0, &sourceAddr, &sourceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for sourceAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (groupAddr.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, interfaceAddress, scopeId, 0, &interfaceAddr, &interfaceAddrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr for interfaceAddress");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
interfaceIpAddr = (struct sockaddr_in*) &interfaceAddr;
|
|
||||||
|
|
||||||
groupIpAddr = (struct sockaddr_in*) &groupAddr;
|
|
||||||
sourceIpAddr = (struct sockaddr_in*) &sourceAddr;
|
|
||||||
memcpy(&mreq.imr_multiaddr, &groupIpAddr->sin_addr, sizeof(groupIpAddr->sin_addr));
|
|
||||||
memcpy(&mreq.imr_interface, &interfaceIpAddr->sin_addr, sizeof(interfaceIpAddr->sin_addr));
|
|
||||||
memcpy(&mreq.imr_sourceaddr, &sourceIpAddr->sin_addr, sizeof(sourceIpAddr->sin_addr));
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof(mreq));
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
if (interfaceIndex == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Unable to find network index");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mreq6.gsr_group = groupAddr;
|
|
||||||
mreq6.gsr_interface = interfaceIndex;
|
|
||||||
mreq6.gsr_source = sourceAddr;
|
|
||||||
netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, MCAST_LEAVE_SOURCE_GROUP, &mreq6, sizeof(mreq6));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
netty_unix_errors_throwIOException(env, "Address family not supported");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setTcpMd5Sig(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jbyteArray address, jint scopeId, jbyteArray key) {
|
|
||||||
struct sockaddr_storage addr;
|
|
||||||
socklen_t addrSize;
|
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, address, scopeId, 0, &addr, &addrSize) == -1) {
|
|
||||||
netty_unix_errors_throwIOException(env, "Could not init sockaddr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct tcp_md5sig md5sig;
|
|
||||||
memset(&md5sig, 0, sizeof(md5sig));
|
|
||||||
md5sig.tcpm_addr.ss_family = addr.ss_family;
|
|
||||||
|
|
||||||
struct sockaddr_in* ipaddr;
|
|
||||||
struct sockaddr_in6* ip6addr;
|
|
||||||
|
|
||||||
switch (addr.ss_family) {
|
|
||||||
case AF_INET:
|
|
||||||
ipaddr = (struct sockaddr_in*) &addr;
|
|
||||||
memcpy(&((struct sockaddr_in *) &md5sig.tcpm_addr)->sin_addr, &ipaddr->sin_addr, sizeof(ipaddr->sin_addr));
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
ip6addr = (struct sockaddr_in6*) &addr;
|
|
||||||
memcpy(&((struct sockaddr_in6 *) &md5sig.tcpm_addr)->sin6_addr, &ip6addr->sin6_addr, sizeof(ip6addr->sin6_addr));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key != NULL) {
|
|
||||||
md5sig.tcpm_keylen = (*env)->GetArrayLength(env, key);
|
|
||||||
(*env)->GetByteArrayRegion(env, key, 0, md5sig.tcpm_keylen, (void *) &md5sig.tcpm_key);
|
|
||||||
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof(md5sig)) < 0) {
|
|
||||||
netty_unix_errors_throwIOExceptionErrorNo(env, "setsockopt() failed: ", errno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int netty_epoll_linuxsocket_getInterface(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6) {
|
|
||||||
if (ipv6 == JNI_TRUE) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
} else {
|
|
||||||
struct in_addr optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ntohl(optval.s_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTimeToLive(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_TTL, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getIpMulticastLoop(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6) {
|
|
||||||
if (ipv6 == JNI_TRUE) {
|
|
||||||
u_int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (jint) optval;
|
|
||||||
} else {
|
|
||||||
u_char optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (jint) optval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTcpKeepIdle(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTcpKeepIntvl(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTcpKeepCnt(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTcpUserTimeout(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_isIpFreeBind(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_FREEBIND, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_isIpTransparent(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, SOL_IP, IP_TRANSPARENT, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_isIpRecvOrigDestAddr(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_RECVORIGDSTADDR, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_getTcpInfo(JNIEnv* env, jclass clazz, jint fd, jlongArray array) {
|
|
||||||
struct tcp_info tcp_info;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_INFO, &tcp_info, sizeof(tcp_info)) == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jlong cArray[32];
|
|
||||||
// Expand to 64 bits, then cast away unsigned-ness.
|
|
||||||
cArray[0] = (jlong) (uint64_t) tcp_info.tcpi_state;
|
|
||||||
cArray[1] = (jlong) (uint64_t) tcp_info.tcpi_ca_state;
|
|
||||||
cArray[2] = (jlong) (uint64_t) tcp_info.tcpi_retransmits;
|
|
||||||
cArray[3] = (jlong) (uint64_t) tcp_info.tcpi_probes;
|
|
||||||
cArray[4] = (jlong) (uint64_t) tcp_info.tcpi_backoff;
|
|
||||||
cArray[5] = (jlong) (uint64_t) tcp_info.tcpi_options;
|
|
||||||
cArray[6] = (jlong) (uint64_t) tcp_info.tcpi_snd_wscale;
|
|
||||||
cArray[7] = (jlong) (uint64_t) tcp_info.tcpi_rcv_wscale;
|
|
||||||
cArray[8] = (jlong) (uint64_t) tcp_info.tcpi_rto;
|
|
||||||
cArray[9] = (jlong) (uint64_t) tcp_info.tcpi_ato;
|
|
||||||
cArray[10] = (jlong) (uint64_t) tcp_info.tcpi_snd_mss;
|
|
||||||
cArray[11] = (jlong) (uint64_t) tcp_info.tcpi_rcv_mss;
|
|
||||||
cArray[12] = (jlong) (uint64_t) tcp_info.tcpi_unacked;
|
|
||||||
cArray[13] = (jlong) (uint64_t) tcp_info.tcpi_sacked;
|
|
||||||
cArray[14] = (jlong) (uint64_t) tcp_info.tcpi_lost;
|
|
||||||
cArray[15] = (jlong) (uint64_t) tcp_info.tcpi_retrans;
|
|
||||||
cArray[16] = (jlong) (uint64_t) tcp_info.tcpi_fackets;
|
|
||||||
cArray[17] = (jlong) (uint64_t) tcp_info.tcpi_last_data_sent;
|
|
||||||
cArray[18] = (jlong) (uint64_t) tcp_info.tcpi_last_ack_sent;
|
|
||||||
cArray[19] = (jlong) (uint64_t) tcp_info.tcpi_last_data_recv;
|
|
||||||
cArray[20] = (jlong) (uint64_t) tcp_info.tcpi_last_ack_recv;
|
|
||||||
cArray[21] = (jlong) (uint64_t) tcp_info.tcpi_pmtu;
|
|
||||||
cArray[22] = (jlong) (uint64_t) tcp_info.tcpi_rcv_ssthresh;
|
|
||||||
cArray[23] = (jlong) (uint64_t) tcp_info.tcpi_rtt;
|
|
||||||
cArray[24] = (jlong) (uint64_t) tcp_info.tcpi_rttvar;
|
|
||||||
cArray[25] = (jlong) (uint64_t) tcp_info.tcpi_snd_ssthresh;
|
|
||||||
cArray[26] = (jlong) (uint64_t) tcp_info.tcpi_snd_cwnd;
|
|
||||||
cArray[27] = (jlong) (uint64_t) tcp_info.tcpi_advmss;
|
|
||||||
cArray[28] = (jlong) (uint64_t) tcp_info.tcpi_reordering;
|
|
||||||
cArray[29] = (jlong) (uint64_t) tcp_info.tcpi_rcv_rtt;
|
|
||||||
cArray[30] = (jlong) (uint64_t) tcp_info.tcpi_rcv_space;
|
|
||||||
cArray[31] = (jlong) (uint64_t) tcp_info.tcpi_total_retrans;
|
|
||||||
|
|
||||||
(*env)->SetLongArrayRegion(env, array, 0, 32, cArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_isTcpCork(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getSoBusyPoll(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, SOL_SOCKET, SO_BUSY_POLL, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTcpDeferAccept(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_isTcpQuickAck(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_QUICKACK, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_getTcpNotSentLowAt(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_NOTSENT_LOWAT, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jobject netty_epoll_linuxsocket_getPeerCredentials(JNIEnv *env, jclass clazz, jint fd) {
|
|
||||||
struct ucred credentials;
|
|
||||||
jclass peerCredentialsClass = NULL;
|
|
||||||
if(netty_unix_socket_getOption(env,fd, SOL_SOCKET, SO_PEERCRED, &credentials, sizeof (credentials)) == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
jintArray gids = (*env)->NewIntArray(env, 1);
|
|
||||||
(*env)->SetIntArrayRegion(env, gids, 0, 1, (jint*) &credentials.gid);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_NEW_LOCAL_FROM_WEAK(env, peerCredentialsClass, peerCredentialsClassWeak, error);
|
|
||||||
|
|
||||||
jobject creds = (*env)->NewObject(env, peerCredentialsClass, peerCredentialsMethodId, credentials.pid, credentials.uid, gids);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_DELETE_LOCAL(env, peerCredentialsClass);
|
|
||||||
return creds;
|
|
||||||
error:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_linuxsocket_isUdpGro(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
int optval;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, SOL_UDP, UDP_GRO, &optval, sizeof(optval)) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return optval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_linuxsocket_setUdpGro(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
|
||||||
netty_unix_socket_setOption(env, fd, SOL_UDP, UDP_GRO, &optval, sizeof(optval));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static jlong netty_epoll_linuxsocket_sendFile(JNIEnv* env, jclass clazz, jint fd, jobject fileRegion, jlong base_off, jlong off, jlong len) {
|
|
||||||
jobject fileChannel = (*env)->GetObjectField(env, fileRegion, fileChannelFieldId);
|
|
||||||
if (fileChannel == NULL) {
|
|
||||||
netty_unix_errors_throwRuntimeException(env, "failed to get DefaultFileRegion.file");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
jobject fileDescriptor = (*env)->GetObjectField(env, fileChannel, fileDescriptorFieldId);
|
|
||||||
if (fileDescriptor == NULL) {
|
|
||||||
netty_unix_errors_throwRuntimeException(env, "failed to get FileChannelImpl.fd");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
jint srcFd = (*env)->GetIntField(env, fileDescriptor, fdFieldId);
|
|
||||||
if (srcFd == -1) {
|
|
||||||
netty_unix_errors_throwRuntimeException(env, "failed to get FileDescriptor.fd");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ssize_t res;
|
|
||||||
off_t offset = base_off + off;
|
|
||||||
int err;
|
|
||||||
do {
|
|
||||||
res = sendfile(fd, srcFd, &offset, (size_t) len);
|
|
||||||
} while (res == -1 && ((err = errno) == EINTR));
|
|
||||||
if (res < 0) {
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
if (res > 0) {
|
|
||||||
// update the transferred field in DefaultFileRegion
|
|
||||||
(*env)->SetLongField(env, fileRegion, transferredFieldId, off + res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// JNI Registered Methods End
|
|
||||||
|
|
||||||
// JNI Method Registration Table Begin
|
|
||||||
static const JNINativeMethod fixed_method_table[] = {
|
|
||||||
{ "newVSockStreamFd", "()I", (void *) netty_epoll_linuxsocket_newVSockStreamFd },
|
|
||||||
{ "bindVSock", "(III)I", (void *) netty_epoll_linuxsocket_bindVSock },
|
|
||||||
{ "connectVSock", "(III)I", (void *) netty_epoll_linuxsocket_connectVSock },
|
|
||||||
{ "remoteVSockAddress", "(I)[B", (void *) netty_epoll_linuxsocket_remoteVSockAddress },
|
|
||||||
{ "localVSockAddress", "(I)[B", (void *) netty_epoll_linuxsocket_localVSockAddress },
|
|
||||||
{ "setTimeToLive", "(II)V", (void *) netty_epoll_linuxsocket_setTimeToLive },
|
|
||||||
{ "getTimeToLive", "(I)I", (void *) netty_epoll_linuxsocket_getTimeToLive },
|
|
||||||
{ "setInterface", "(IZ[BII)V", (void *) netty_epoll_linuxsocket_setInterface },
|
|
||||||
{ "getInterface", "(IZ)I", (void *) netty_epoll_linuxsocket_getInterface },
|
|
||||||
{ "setIpMulticastLoop", "(IZI)V", (void * ) netty_epoll_linuxsocket_setIpMulticastLoop },
|
|
||||||
{ "getIpMulticastLoop", "(IZ)I", (void * ) netty_epoll_linuxsocket_getIpMulticastLoop },
|
|
||||||
{ "setTcpCork", "(II)V", (void *) netty_epoll_linuxsocket_setTcpCork },
|
|
||||||
{ "setSoBusyPoll", "(II)V", (void *) netty_epoll_linuxsocket_setSoBusyPoll },
|
|
||||||
{ "setTcpQuickAck", "(II)V", (void *) netty_epoll_linuxsocket_setTcpQuickAck },
|
|
||||||
{ "setTcpDeferAccept", "(II)V", (void *) netty_epoll_linuxsocket_setTcpDeferAccept },
|
|
||||||
{ "setTcpNotSentLowAt", "(II)V", (void *) netty_epoll_linuxsocket_setTcpNotSentLowAt },
|
|
||||||
{ "isTcpCork", "(I)I", (void *) netty_epoll_linuxsocket_isTcpCork },
|
|
||||||
{ "getSoBusyPoll", "(I)I", (void *) netty_epoll_linuxsocket_getSoBusyPoll },
|
|
||||||
{ "getTcpDeferAccept", "(I)I", (void *) netty_epoll_linuxsocket_getTcpDeferAccept },
|
|
||||||
{ "getTcpNotSentLowAt", "(I)I", (void *) netty_epoll_linuxsocket_getTcpNotSentLowAt },
|
|
||||||
{ "isTcpQuickAck", "(I)I", (void *) netty_epoll_linuxsocket_isTcpQuickAck },
|
|
||||||
{ "setTcpFastOpen", "(II)V", (void *) netty_epoll_linuxsocket_setTcpFastOpen },
|
|
||||||
{ "setTcpKeepIdle", "(II)V", (void *) netty_epoll_linuxsocket_setTcpKeepIdle },
|
|
||||||
{ "setTcpKeepIntvl", "(II)V", (void *) netty_epoll_linuxsocket_setTcpKeepIntvl },
|
|
||||||
{ "setTcpKeepCnt", "(II)V", (void *) netty_epoll_linuxsocket_setTcpKeepCnt },
|
|
||||||
{ "setTcpUserTimeout", "(II)V", (void *) netty_epoll_linuxsocket_setTcpUserTimeout },
|
|
||||||
{ "setIpFreeBind", "(II)V", (void *) netty_epoll_linuxsocket_setIpFreeBind },
|
|
||||||
{ "setIpTransparent", "(II)V", (void *) netty_epoll_linuxsocket_setIpTransparent },
|
|
||||||
{ "setIpRecvOrigDestAddr", "(II)V", (void *) netty_epoll_linuxsocket_setIpRecvOrigDestAddr },
|
|
||||||
{ "getTcpKeepIdle", "(I)I", (void *) netty_epoll_linuxsocket_getTcpKeepIdle },
|
|
||||||
{ "getTcpKeepIntvl", "(I)I", (void *) netty_epoll_linuxsocket_getTcpKeepIntvl },
|
|
||||||
{ "getTcpKeepCnt", "(I)I", (void *) netty_epoll_linuxsocket_getTcpKeepCnt },
|
|
||||||
{ "getTcpUserTimeout", "(I)I", (void *) netty_epoll_linuxsocket_getTcpUserTimeout },
|
|
||||||
{ "isIpFreeBind", "(I)I", (void *) netty_epoll_linuxsocket_isIpFreeBind },
|
|
||||||
{ "isIpTransparent", "(I)I", (void *) netty_epoll_linuxsocket_isIpTransparent },
|
|
||||||
{ "isIpRecvOrigDestAddr", "(I)I", (void *) netty_epoll_linuxsocket_isIpRecvOrigDestAddr },
|
|
||||||
{ "getTcpInfo", "(I[J)V", (void *) netty_epoll_linuxsocket_getTcpInfo },
|
|
||||||
{ "setTcpMd5Sig", "(IZ[BI[B)V", (void *) netty_epoll_linuxsocket_setTcpMd5Sig },
|
|
||||||
{ "joinGroup", "(IZ[B[BII)V", (void *) netty_epoll_linuxsocket_joinGroup },
|
|
||||||
{ "joinSsmGroup", "(IZ[B[BII[B)V", (void *) netty_epoll_linuxsocket_joinSsmGroup },
|
|
||||||
{ "leaveGroup", "(IZ[B[BII)V", (void *) netty_epoll_linuxsocket_leaveGroup },
|
|
||||||
{ "leaveSsmGroup", "(IZ[B[BII[B)V", (void *) netty_epoll_linuxsocket_leaveSsmGroup },
|
|
||||||
{ "isUdpGro", "(I)I", (void *) netty_epoll_linuxsocket_isUdpGro },
|
|
||||||
{ "setUdpGro", "(II)V", (void *) netty_epoll_linuxsocket_setUdpGro }
|
|
||||||
|
|
||||||
// "sendFile" has a dynamic signature
|
|
||||||
};
|
|
||||||
|
|
||||||
static const jint fixed_method_table_size = sizeof(fixed_method_table) / sizeof(fixed_method_table[0]);
|
|
||||||
|
|
||||||
static jint dynamicMethodsTableSize() {
|
|
||||||
return fixed_method_table_size + 2; // 2 is for the dynamic method signatures.
|
|
||||||
}
|
|
||||||
|
|
||||||
static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) {
|
|
||||||
char* dynamicTypeName = NULL;
|
|
||||||
size_t size = sizeof(JNINativeMethod) * dynamicMethodsTableSize();
|
|
||||||
JNINativeMethod* dynamicMethods = malloc(size);
|
|
||||||
if (dynamicMethods == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(dynamicMethods, 0, size);
|
|
||||||
memcpy(dynamicMethods, fixed_method_table, sizeof(fixed_method_table));
|
|
||||||
|
|
||||||
JNINativeMethod* dynamicMethod = &dynamicMethods[fixed_method_table_size];
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials;", dynamicTypeName, error);
|
|
||||||
NETTY_JNI_UTIL_PREPEND("(I)L", dynamicTypeName, dynamicMethod->signature, error);
|
|
||||||
dynamicMethod->name = "getPeerCredentials";
|
|
||||||
dynamicMethod->fnPtr = (void *) netty_epoll_linuxsocket_getPeerCredentials;
|
|
||||||
netty_jni_util_free_dynamic_name(&dynamicTypeName);
|
|
||||||
|
|
||||||
++dynamicMethod;
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion;JJJ)J", dynamicTypeName, error);
|
|
||||||
NETTY_JNI_UTIL_PREPEND("(IL", dynamicTypeName, dynamicMethod->signature, error);
|
|
||||||
dynamicMethod->name = "sendFile";
|
|
||||||
dynamicMethod->fnPtr = (void *) netty_epoll_linuxsocket_sendFile;
|
|
||||||
netty_jni_util_free_dynamic_name(&dynamicTypeName);
|
|
||||||
return dynamicMethods;
|
|
||||||
error:
|
|
||||||
free(dynamicTypeName);
|
|
||||||
netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// JNI Method Registration Table End
|
|
||||||
|
|
||||||
// IMPORTANT: If you add any NETTY_JNI_UTIL_LOAD_CLASS or NETTY_JNI_UTIL_FIND_CLASS calls you also need to update
|
|
||||||
// Native to reflect that.
|
|
||||||
jint netty_epoll_linuxsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
|
|
||||||
int ret = JNI_ERR;
|
|
||||||
char* nettyClassName = NULL;
|
|
||||||
jclass fileRegionCls = NULL;
|
|
||||||
jclass fileChannelCls = NULL;
|
|
||||||
jclass fileDescriptorCls = NULL;
|
|
||||||
jclass peerCredentialsClass = NULL;
|
|
||||||
// Register the methods which are not referenced by static member variables
|
|
||||||
JNINativeMethod* dynamicMethods = createDynamicMethodsTable(packagePrefix);
|
|
||||||
if (dynamicMethods == NULL) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (netty_jni_util_register_natives(env,
|
|
||||||
packagePrefix,
|
|
||||||
LINUXSOCKET_CLASSNAME,
|
|
||||||
dynamicMethods,
|
|
||||||
dynamicMethodsTableSize()) != 0) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/unix/PeerCredentials", nettyClassName, done);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_LOAD_CLASS_WEAK(env, peerCredentialsClassWeak, nettyClassName, done);
|
|
||||||
NETTY_JNI_UTIL_NEW_LOCAL_FROM_WEAK(env, peerCredentialsClass, peerCredentialsClassWeak, done);
|
|
||||||
|
|
||||||
netty_jni_util_free_dynamic_name(&nettyClassName);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_GET_METHOD(env, peerCredentialsClass, peerCredentialsMethodId, "<init>", "(II[I)V", done);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/DefaultFileRegion", nettyClassName, done);
|
|
||||||
NETTY_JNI_UTIL_FIND_CLASS(env, fileRegionCls, nettyClassName, done);
|
|
||||||
netty_jni_util_free_dynamic_name(&nettyClassName);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, fileRegionCls, fileChannelFieldId, "file", "Ljava/nio/channels/FileChannel;", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, fileRegionCls, transferredFieldId, "transferred", "J", done);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_FIND_CLASS(env, fileChannelCls, "sun/nio/ch/FileChannelImpl", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, fileChannelCls, fileDescriptorFieldId, "fd", "Ljava/io/FileDescriptor;", done);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_FIND_CLASS(env, fileDescriptorCls, "java/io/FileDescriptor", done);
|
|
||||||
NETTY_JNI_UTIL_TRY_GET_FIELD(env, fileDescriptorCls, fdFieldId, "fd", "I");
|
|
||||||
if (fdFieldId == NULL) {
|
|
||||||
// Android uses a different field name, let's try it.
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, fileDescriptorCls, fdFieldId, "descriptor", "I", done);
|
|
||||||
}
|
|
||||||
ret = NETTY_JNI_UTIL_JNI_VERSION;
|
|
||||||
done:
|
|
||||||
netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize());
|
|
||||||
free(nettyClassName);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_DELETE_LOCAL(env, peerCredentialsClass);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void netty_epoll_linuxsocket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
|
|
||||||
NETTY_JNI_UTIL_UNLOAD_CLASS_WEAK(env, peerCredentialsClassWeak);
|
|
||||||
|
|
||||||
netty_jni_util_unregister_natives(env, packagePrefix, LINUXSOCKET_CLASSNAME);
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NETTY_EPOLL_LINUXSOCKET_H_
|
|
||||||
#define NETTY_EPOLL_LINUXSOCKET_H_
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
// JNI initialization hooks. Users of this file are responsible for calling these in the JNI_OnLoad and JNI_OnUnload methods.
|
|
||||||
jint netty_epoll_linuxsocket_JNI_OnLoad(JNIEnv* env, const char* packagePrefix);
|
|
||||||
void netty_epoll_linuxsocket_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,919 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <jni.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
#include <sys/eventfd.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <link.h>
|
|
||||||
#include <time.h>
|
|
||||||
// Needed to be able to use syscalls directly and so not depend on newer GLIBC versions
|
|
||||||
#include <linux/net.h>
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
|
|
||||||
// Needed for UDP_SEGMENT
|
|
||||||
#include <netinet/udp.h>
|
|
||||||
|
|
||||||
#include "netty_epoll_linuxsocket.h"
|
|
||||||
#include "netty_unix_buffer.h"
|
|
||||||
#include "netty_unix_errors.h"
|
|
||||||
#include "netty_unix_filedescriptor.h"
|
|
||||||
#include "netty_unix_jni.h"
|
|
||||||
#include "netty_unix_limits.h"
|
|
||||||
#include "netty_unix_socket.h"
|
|
||||||
#include "netty_unix_util.h"
|
|
||||||
#include "netty_unix.h"
|
|
||||||
|
|
||||||
// Add define if NETTY_BUILD_STATIC is defined so it is picked up in netty_jni_util.c
|
|
||||||
#ifdef NETTY_BUILD_STATIC
|
|
||||||
#define NETTY_JNI_UTIL_BUILD_STATIC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STATICALLY_CLASSNAME "io/netty/channel/epoll/NativeStaticallyReferencedJniMethods"
|
|
||||||
#define NATIVE_CLASSNAME "io/netty/channel/epoll/Native"
|
|
||||||
|
|
||||||
// TCP_FASTOPEN is defined in linux 3.7. We define this here so older kernels can compile.
|
|
||||||
#ifndef TCP_FASTOPEN
|
|
||||||
#define TCP_FASTOPEN 23
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Allow to compile on systems with older kernels.
|
|
||||||
#ifndef UDP_SEGMENT
|
|
||||||
#define UDP_SEGMENT 103
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// UDP_GRO is defined in linux 5. We define this here so older kernels can compile.
|
|
||||||
#ifndef UDP_GRO
|
|
||||||
#define UDP_GRO 104
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IP_RECVORIGDSTADDR
|
|
||||||
#if !defined(SOL_IP) && defined(IPPROTO_IP)
|
|
||||||
#define SOL_IP IPPROTO_IP
|
|
||||||
#endif /* !SOL_IP && IPPROTO_IP */
|
|
||||||
#endif // IP_RECVORIGDSTADDR
|
|
||||||
|
|
||||||
// optional
|
|
||||||
extern int epoll_create1(int flags) __attribute__((weak));
|
|
||||||
extern int epoll_pwait2(int epfd, struct epoll_event *events, int maxevents, const struct timespec *timeout, const sigset_t *sigmask) __attribute__((weak));
|
|
||||||
|
|
||||||
#ifndef __USE_GNU
|
|
||||||
struct mmsghdr {
|
|
||||||
struct msghdr msg_hdr; /* Message header */
|
|
||||||
unsigned int msg_len; /* Number of bytes transmitted */
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// All linux syscall numbers are stable so this is safe.
|
|
||||||
#ifndef SYS_recvmmsg
|
|
||||||
// Only support SYS_recvmmsg for __x86_64__ / __i386__ for now
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
// See https://github.com/torvalds/linux/blob/v5.4/arch/x86/entry/syscalls/syscall_64.tbl
|
|
||||||
#define SYS_recvmmsg 299
|
|
||||||
#elif defined(__i386__)
|
|
||||||
// See https://github.com/torvalds/linux/blob/v5.4/arch/x86/entry/syscalls/syscall_32.tbl
|
|
||||||
#define SYS_recvmmsg 337
|
|
||||||
#elif defined(__loongarch64)
|
|
||||||
// See https://github.com/torvalds/linux/blob/v6.1/include/uapi/asm-generic/unistd.h
|
|
||||||
#define SYS_recvmmsg 243
|
|
||||||
#else
|
|
||||||
#define SYS_recvmmsg -1
|
|
||||||
#endif
|
|
||||||
#endif // SYS_recvmmsg
|
|
||||||
|
|
||||||
#ifndef SYS_sendmmsg
|
|
||||||
// Only support SYS_sendmmsg for __x86_64__ / __i386__ for now
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
// See https://github.com/torvalds/linux/blob/v5.4/arch/x86/entry/syscalls/syscall_64.tbl
|
|
||||||
#define SYS_sendmmsg 307
|
|
||||||
#elif defined(__i386__)
|
|
||||||
// See https://github.com/torvalds/linux/blob/v5.4/arch/x86/entry/syscalls/syscall_32.tbl
|
|
||||||
#define SYS_sendmmsg 345
|
|
||||||
#elif defined(__loongarch64)
|
|
||||||
// See https://github.com/torvalds/linux/blob/v6.1/include/uapi/asm-generic/unistd.h
|
|
||||||
#define SYS_sendmmsg 269
|
|
||||||
#else
|
|
||||||
#define SYS_sendmmsg -1
|
|
||||||
#endif
|
|
||||||
#endif // SYS_sendmmsg
|
|
||||||
|
|
||||||
// Those are initialized in the init(...) method and cached for performance reasons
|
|
||||||
static jfieldID packetSenderAddrFieldId = NULL;
|
|
||||||
static jfieldID packetSenderAddrLenFieldId = NULL;
|
|
||||||
static jfieldID packetSenderScopeIdFieldId = NULL;
|
|
||||||
static jfieldID packetSenderPortFieldId = NULL;
|
|
||||||
static jfieldID packetRecipientAddrFieldId = NULL;
|
|
||||||
static jfieldID packetRecipientAddrLenFieldId = NULL;
|
|
||||||
static jfieldID packetRecipientScopeIdFieldId = NULL;
|
|
||||||
static jfieldID packetRecipientPortFieldId = NULL;
|
|
||||||
|
|
||||||
static jfieldID packetSegmentSizeFieldId = NULL;
|
|
||||||
static jfieldID packetMemoryAddressFieldId = NULL;
|
|
||||||
static jfieldID packetCountFieldId = NULL;
|
|
||||||
|
|
||||||
static const char* staticPackagePrefix = NULL;
|
|
||||||
static int register_unix_called = 0;
|
|
||||||
static int epoll_pwait2_supported = 0;
|
|
||||||
|
|
||||||
// util methods
|
|
||||||
static int getSysctlValue(const char * property, int* returnValue) {
|
|
||||||
int rc = -1;
|
|
||||||
FILE *fd=fopen(property, "r");
|
|
||||||
if (fd != NULL) {
|
|
||||||
char buf[32] = {0x0};
|
|
||||||
if (fgets(buf, 32, fd) != NULL) {
|
|
||||||
*returnValue = atoi(buf);
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
fclose(fd);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline jint epollCtl(JNIEnv* env, jint efd, int op, jint fd, jint flags) {
|
|
||||||
uint32_t events = flags;
|
|
||||||
struct epoll_event ev = {
|
|
||||||
.data.fd = fd,
|
|
||||||
.events = events
|
|
||||||
};
|
|
||||||
|
|
||||||
return epoll_ctl(efd, op, fd, &ev);
|
|
||||||
}
|
|
||||||
// JNI Registered Methods Begin
|
|
||||||
static jint netty_epoll_native_eventFd(JNIEnv* env, jclass clazz) {
|
|
||||||
jint eventFD = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
|
||||||
|
|
||||||
if (eventFD < 0) {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "eventfd() failed: ", errno);
|
|
||||||
}
|
|
||||||
return eventFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_timerFd(JNIEnv* env, jclass clazz) {
|
|
||||||
jint timerFD = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
|
||||||
|
|
||||||
if (timerFD < 0) {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "timerfd_create() failed: ", errno);
|
|
||||||
}
|
|
||||||
return timerFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_native_eventFdWrite(JNIEnv* env, jclass clazz, jint fd, jlong value) {
|
|
||||||
uint64_t val;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
jint ret = eventfd_write(fd, (eventfd_t) value);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
// We need to read before we can write again, let's try to read and then write again and if this
|
|
||||||
// fails we will bail out.
|
|
||||||
//
|
|
||||||
// See https://man7.org/linux/man-pages/man2/eventfd.2.html.
|
|
||||||
if (errno == EAGAIN) {
|
|
||||||
if (eventfd_read(fd, &val) == 0 || errno == EAGAIN) {
|
|
||||||
// Try again
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "eventfd_read(...) failed: ", errno);
|
|
||||||
} else {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "eventfd_write(...) failed: ", errno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_native_eventFdRead(JNIEnv* env, jclass clazz, jint fd) {
|
|
||||||
uint64_t eventfd_t;
|
|
||||||
|
|
||||||
if (eventfd_read(fd, &eventfd_t) != 0) {
|
|
||||||
// something is serious wrong
|
|
||||||
netty_unix_errors_throwRuntimeException(env, "eventfd_read() failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollCreate(JNIEnv* env, jclass clazz) {
|
|
||||||
jint efd;
|
|
||||||
if (epoll_create1) {
|
|
||||||
efd = epoll_create1(EPOLL_CLOEXEC);
|
|
||||||
} else {
|
|
||||||
// size will be ignored anyway but must be positive
|
|
||||||
efd = epoll_create(126);
|
|
||||||
}
|
|
||||||
if (efd < 0) {
|
|
||||||
int err = errno;
|
|
||||||
if (epoll_create1) {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "epoll_create1() failed: ", err);
|
|
||||||
} else {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "epoll_create() failed: ", err);
|
|
||||||
}
|
|
||||||
return efd;
|
|
||||||
}
|
|
||||||
if (!epoll_create1) {
|
|
||||||
if (fcntl(efd, F_SETFD, FD_CLOEXEC) < 0) {
|
|
||||||
int err = errno;
|
|
||||||
close(efd);
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "fcntl() failed: ", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return efd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollWait(JNIEnv* env, jclass clazz, jint efd, jlong address, jint len, jint timeout) {
|
|
||||||
struct epoll_event *ev = (struct epoll_event*) (intptr_t) address;
|
|
||||||
int result, err;
|
|
||||||
|
|
||||||
do {
|
|
||||||
result = epoll_wait(efd, ev, len, timeout);
|
|
||||||
if (result >= 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} while((err = errno) == EINTR);
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This needs to be consistent with Native.java
|
|
||||||
#define EPOLL_WAIT_RESULT(V, ARM_TIMER) ((jlong) ((uint64_t) ((uint32_t) V) << 32 | ARM_TIMER))
|
|
||||||
|
|
||||||
static jlong netty_epoll_native_epollWait0(JNIEnv* env, jclass clazz, jint efd, jlong address, jint len, jint timerFd, jint tvSec, jint tvNsec, jlong millisThreshold) {
|
|
||||||
// only reschedule the timer if there is a newer event.
|
|
||||||
// -1 is a special value used by EpollEventLoop.
|
|
||||||
uint32_t armTimer = millisThreshold <= 0 ? 1 : 0;
|
|
||||||
if (tvSec != ((jint) -1) && tvNsec != ((jint) -1)) {
|
|
||||||
if (millisThreshold > 0 && (tvSec != 0 || tvNsec != 0)) {
|
|
||||||
// Let's try to reduce the syscalls as much as possible as timerfd_settime(...) can be expensive:
|
|
||||||
// See https://github.com/netty/netty/issues/11695
|
|
||||||
|
|
||||||
if (epoll_pwait2_supported == 1) {
|
|
||||||
// We have epoll_pwait2(...) and it is supported, this means we can just pass in the itimerspec directly and not need an
|
|
||||||
// extra syscall even for very small timeouts.
|
|
||||||
struct timespec ts = { tvSec, tvNsec };
|
|
||||||
struct epoll_event *ev = (struct epoll_event*) (intptr_t) address;
|
|
||||||
int result, err;
|
|
||||||
do {
|
|
||||||
result = epoll_pwait2(efd, ev, len, &ts, NULL);
|
|
||||||
if (result >= 0) {
|
|
||||||
return EPOLL_WAIT_RESULT(result, armTimer);
|
|
||||||
}
|
|
||||||
} while((err = errno) == EINTR);
|
|
||||||
return EPOLL_WAIT_RESULT(-err, armTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int millis = tvNsec / 1000000;
|
|
||||||
// Check if we can reduce the syscall overhead by just use epoll_wait. This is done in cases when we can
|
|
||||||
// tolerate some "drift".
|
|
||||||
if (tvNsec == 0 ||
|
|
||||||
// Let's use the threshold to accept that we may be not 100 % accurate and ignore anything that
|
|
||||||
// is smaller then 1 ms.
|
|
||||||
millis >= millisThreshold ||
|
|
||||||
tvSec > 0) {
|
|
||||||
millis += tvSec * 1000;
|
|
||||||
int result = netty_epoll_native_epollWait(env, clazz, efd, address, len, millis);
|
|
||||||
return EPOLL_WAIT_RESULT(result, armTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
struct itimerspec ts;
|
|
||||||
memset(&ts.it_interval, 0, sizeof(struct timespec));
|
|
||||||
ts.it_value.tv_sec = tvSec;
|
|
||||||
ts.it_value.tv_nsec = tvNsec;
|
|
||||||
if (timerfd_settime(timerFd, 0, &ts, NULL) < 0) {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, "timerfd_settime() failed: ", errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
armTimer = 1;
|
|
||||||
}
|
|
||||||
int result = netty_epoll_native_epollWait(env, clazz, efd, address, len, -1);
|
|
||||||
return EPOLL_WAIT_RESULT(result, armTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cpu_relax() {
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
asm volatile("pause\n": : :"memory");
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
asm volatile("isb\n": : :"memory");
|
|
||||||
#elif defined(__riscv) && defined(__riscv_zihintpause)
|
|
||||||
asm volatile("pause\n": : :"memory");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollBusyWait0(JNIEnv* env, jclass clazz, jint efd, jlong address, jint len) {
|
|
||||||
struct epoll_event *ev = (struct epoll_event*) (intptr_t) address;
|
|
||||||
int result, err;
|
|
||||||
|
|
||||||
// Zeros = poll (aka return immediately).
|
|
||||||
do {
|
|
||||||
result = epoll_wait(efd, ev, len, 0);
|
|
||||||
if (result == 0) {
|
|
||||||
// Since we're always polling epoll_wait with no timeout,
|
|
||||||
// signal CPU that we're in a busy loop
|
|
||||||
cpu_relax();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result >= 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} while((err = errno) == EINTR);
|
|
||||||
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollCtlAdd0(JNIEnv* env, jclass clazz, jint efd, jint fd, jint flags) {
|
|
||||||
int res = epollCtl(env, efd, EPOLL_CTL_ADD, fd, flags);
|
|
||||||
if (res < 0) {
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
static jint netty_epoll_native_epollCtlMod0(JNIEnv* env, jclass clazz, jint efd, jint fd, jint flags) {
|
|
||||||
int res = epollCtl(env, efd, EPOLL_CTL_MOD, fd, flags);
|
|
||||||
if (res < 0) {
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollCtlDel0(JNIEnv* env, jclass clazz, jint efd, jint fd) {
|
|
||||||
// Create an empty event to workaround a bug in older kernels which can not handle NULL.
|
|
||||||
struct epoll_event event = { 0 };
|
|
||||||
int res = epoll_ctl(efd, EPOLL_CTL_DEL, fd, &event);
|
|
||||||
if (res < 0) {
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_sendmmsg0(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jobjectArray packets, jint offset, jint len) {
|
|
||||||
struct mmsghdr msg[len];
|
|
||||||
struct sockaddr_storage addr[len];
|
|
||||||
char controls[len][CMSG_SPACE(sizeof(uint16_t))];
|
|
||||||
|
|
||||||
socklen_t addrSize;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
jobject packet = (*env)->GetObjectArrayElement(env, packets, i + offset);
|
|
||||||
jbyteArray address = (jbyteArray) (*env)->GetObjectField(env, packet, packetRecipientAddrFieldId);
|
|
||||||
jint addrLen = (*env)->GetIntField(env, packet, packetRecipientAddrLenFieldId);
|
|
||||||
jint packetSegmentSize = (*env)->GetIntField(env, packet, packetSegmentSizeFieldId);
|
|
||||||
if (packetSegmentSize > 0) {
|
|
||||||
msg[i].msg_hdr.msg_control = controls[i];
|
|
||||||
msg[i].msg_hdr.msg_controllen = sizeof(controls[i]);
|
|
||||||
struct cmsghdr *cm = CMSG_FIRSTHDR(&msg[i].msg_hdr);
|
|
||||||
cm->cmsg_level = SOL_UDP;
|
|
||||||
cm->cmsg_type = UDP_SEGMENT;
|
|
||||||
cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
|
|
||||||
*((uint16_t *) CMSG_DATA(cm)) = packetSegmentSize;
|
|
||||||
}
|
|
||||||
if (addrLen != 0) {
|
|
||||||
jint scopeId = (*env)->GetIntField(env, packet, packetRecipientScopeIdFieldId);
|
|
||||||
jint port = (*env)->GetIntField(env, packet, packetRecipientPortFieldId);
|
|
||||||
|
|
||||||
if (netty_unix_socket_initSockaddr(env, ipv6, address, scopeId, port, &addr[i], &addrSize) == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
msg[i].msg_hdr.msg_name = &addr[i];
|
|
||||||
msg[i].msg_hdr.msg_namelen = addrSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg[i].msg_hdr.msg_iov = (struct iovec*) (intptr_t) (*env)->GetLongField(env, packet, packetMemoryAddressFieldId);
|
|
||||||
msg[i].msg_hdr.msg_iovlen = (*env)->GetIntField(env, packet, packetCountFieldId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t res;
|
|
||||||
int err;
|
|
||||||
do {
|
|
||||||
// We directly use the syscall to prevent depending on GLIBC 2.14.
|
|
||||||
res = syscall(SYS_sendmmsg, fd, msg, len, 0);
|
|
||||||
// keep on writing if it was interrupted
|
|
||||||
} while (res == -1 && ((err = errno) == EINTR));
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
return (jint) res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_packet_address(JNIEnv* env, jobject packet, struct sockaddr_storage* addr, jfieldID addrFieldId,
|
|
||||||
jfieldID addrLenFieldId, jfieldID scopeIdFieldId, jfieldID portFieldId) {
|
|
||||||
jbyteArray address = (jbyteArray) (*env)->GetObjectField(env, packet, addrFieldId);
|
|
||||||
|
|
||||||
if (addr->ss_family == AF_INET) {
|
|
||||||
struct sockaddr_in* ipaddr = (struct sockaddr_in*) addr;
|
|
||||||
|
|
||||||
(*env)->SetByteArrayRegion(env, address, 0, 4, (jbyte*) &ipaddr->sin_addr.s_addr);
|
|
||||||
(*env)->SetIntField(env, packet, addrLenFieldId, 4);
|
|
||||||
(*env)->SetIntField(env, packet, scopeIdFieldId, 0);
|
|
||||||
(*env)->SetIntField(env, packet, portFieldId, ntohs(ipaddr->sin_port));
|
|
||||||
} else {
|
|
||||||
int addrLen = netty_unix_socket_ipAddressLength(addr);
|
|
||||||
struct sockaddr_in6* ip6addr = (struct sockaddr_in6*) addr;
|
|
||||||
|
|
||||||
if (addrLen == 4) {
|
|
||||||
// IPV4 mapped IPV6 address
|
|
||||||
jbyte* addr = (jbyte*) &ip6addr->sin6_addr.s6_addr;
|
|
||||||
(*env)->SetByteArrayRegion(env, address, 0, 4, addr + 12);
|
|
||||||
} else {
|
|
||||||
(*env)->SetByteArrayRegion(env, address, 0, 16, (jbyte*) &ip6addr->sin6_addr.s6_addr);
|
|
||||||
}
|
|
||||||
(*env)->SetIntField(env, packet, addrLenFieldId, addrLen);
|
|
||||||
(*env)->SetIntField(env, packet, scopeIdFieldId, ip6addr->sin6_scope_id);
|
|
||||||
(*env)->SetIntField(env, packet, portFieldId, ntohs(ip6addr->sin6_port));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_packet(JNIEnv* env, jobject packet, struct msghdr* msg, int len) {
|
|
||||||
(*env)->SetIntField(env, packet, packetCountFieldId, len);
|
|
||||||
|
|
||||||
init_packet_address(env, packet, (struct sockaddr_storage*) msg->msg_name, packetSenderAddrFieldId, packetSenderAddrLenFieldId, packetSenderScopeIdFieldId, packetSenderPortFieldId);
|
|
||||||
|
|
||||||
struct cmsghdr *cmsg = NULL;
|
|
||||||
uint16_t gso_size = 0;
|
|
||||||
uint16_t *gsosizeptr = NULL;
|
|
||||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
|
||||||
if (cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) {
|
|
||||||
gsosizeptr = (uint16_t *) CMSG_DATA(cmsg);
|
|
||||||
gso_size = *gsosizeptr;
|
|
||||||
}
|
|
||||||
#ifdef IP_RECVORIGDSTADDR
|
|
||||||
else if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVORIGDSTADDR) {
|
|
||||||
init_packet_address(env, packet, (struct sockaddr_storage*) CMSG_DATA(cmsg), packetRecipientAddrFieldId, packetRecipientAddrLenFieldId, packetRecipientScopeIdFieldId, packetRecipientPortFieldId);
|
|
||||||
}
|
|
||||||
#endif // IP_RECVORIGDSTADDR
|
|
||||||
}
|
|
||||||
(*env)->SetIntField(env, packet, packetSegmentSizeFieldId, gso_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_recvmsg0(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jobject packet) {
|
|
||||||
struct msghdr msg = { 0 };
|
|
||||||
struct sockaddr_storage sock_address;
|
|
||||||
int addrSize = sizeof(sock_address);
|
|
||||||
// Enough space for GRO and IP_RECVORIGDSTADDR
|
|
||||||
char control[CMSG_SPACE(sizeof(uint16_t)) + sizeof(struct sockaddr_storage)] = { 0 };
|
|
||||||
msg.msg_name = &sock_address;
|
|
||||||
msg.msg_namelen = (socklen_t) addrSize;
|
|
||||||
msg.msg_iov = (struct iovec*) (intptr_t) (*env)->GetLongField(env, packet, packetMemoryAddressFieldId);
|
|
||||||
msg.msg_iovlen = (*env)->GetIntField(env, packet, packetCountFieldId);
|
|
||||||
msg.msg_control = control;
|
|
||||||
msg.msg_controllen = sizeof(control);
|
|
||||||
ssize_t res;
|
|
||||||
int err;
|
|
||||||
do {
|
|
||||||
res = recvmsg(fd, &msg, 0);
|
|
||||||
// keep on reading if it was interrupted
|
|
||||||
} while (res == -1 && ((err = errno) == EINTR));
|
|
||||||
if (res < 0) {
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
init_packet(env, packet, &msg, res);
|
|
||||||
return (jint) res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_recvmmsg0(JNIEnv* env, jclass clazz, jint fd, jboolean ipv6, jobjectArray packets, jint offset, jint len) {
|
|
||||||
struct mmsghdr msg[len];
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
struct sockaddr_storage addr[len];
|
|
||||||
int addrSize = sizeof(addr);
|
|
||||||
memset(addr, 0, addrSize);
|
|
||||||
int storageSize = sizeof(struct sockaddr_storage);
|
|
||||||
char* cntrlbuf = NULL;
|
|
||||||
|
|
||||||
#ifdef IP_RECVORIGDSTADDR
|
|
||||||
int readLocalAddr = 0;
|
|
||||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_RECVORIGDSTADDR,
|
|
||||||
&readLocalAddr, sizeof(readLocalAddr)) < 0) {
|
|
||||||
cntrlbuf = malloc(sizeof(char) * storageSize * len);
|
|
||||||
}
|
|
||||||
#endif // IP_RECVORIGDSTADDR
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
jobject packet = (*env)->GetObjectArrayElement(env, packets, i + offset);
|
|
||||||
msg[i].msg_hdr.msg_iov = (struct iovec*) (intptr_t) (*env)->GetLongField(env, packet, packetMemoryAddressFieldId);
|
|
||||||
msg[i].msg_hdr.msg_iovlen = (*env)->GetIntField(env, packet, packetCountFieldId);
|
|
||||||
|
|
||||||
msg[i].msg_hdr.msg_name = addr + i;
|
|
||||||
msg[i].msg_hdr.msg_namelen = (socklen_t) addrSize;
|
|
||||||
|
|
||||||
if (cntrlbuf != NULL) {
|
|
||||||
msg[i].msg_hdr.msg_control = cntrlbuf + i * storageSize;
|
|
||||||
msg[i].msg_hdr.msg_controllen = storageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t res;
|
|
||||||
int err;
|
|
||||||
do {
|
|
||||||
// We directly use the syscall to prevent depending on GLIBC 2.12.
|
|
||||||
res = syscall(SYS_recvmmsg, fd, &msg, len, 0, NULL);
|
|
||||||
|
|
||||||
// keep on reading if it was interrupted
|
|
||||||
} while (res == -1 && ((err = errno) == EINTR));
|
|
||||||
|
|
||||||
if (res >= 0) {
|
|
||||||
for (i = 0; i < res; i++) {
|
|
||||||
jobject packet = (*env)->GetObjectArrayElement(env, packets, i + offset);
|
|
||||||
init_packet(env, packet, &msg[i].msg_hdr, msg[i].msg_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Free the control message buffer if needed.
|
|
||||||
free(cntrlbuf);
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
return (jint) res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jstring netty_epoll_native_kernelVersion(JNIEnv* env, jclass clazz) {
|
|
||||||
struct utsname name;
|
|
||||||
|
|
||||||
int res = uname(&name);
|
|
||||||
if (res == 0) {
|
|
||||||
return (*env)->NewStringUTF(env, name.release);
|
|
||||||
}
|
|
||||||
netty_unix_errors_throwRuntimeExceptionErrorNo(env, "uname() failed: ", errno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean netty_epoll_native_isSupportingSendmmsg(JNIEnv* env, jclass clazz) {
|
|
||||||
if (SYS_sendmmsg == -1) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
if (syscall(SYS_sendmmsg, -1, NULL, 0, 0) == -1) {
|
|
||||||
if (errno == ENOSYS) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean netty_epoll_native_isSupportingUdpSegment(JNIEnv* env, jclass clazz) {
|
|
||||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
||||||
if (fd == -1) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
int gso_size = 512;
|
|
||||||
int ret = setsockopt(fd, SOL_UDP, UDP_SEGMENT, &gso_size, sizeof(gso_size));
|
|
||||||
close(fd);
|
|
||||||
return ret == -1 ? JNI_FALSE : JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean netty_epoll_native_isSupportingRecvmmsg(JNIEnv* env, jclass clazz) {
|
|
||||||
if (SYS_recvmmsg == -1) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
if (syscall(SYS_recvmmsg, -1, NULL, 0, 0, NULL) == -1) {
|
|
||||||
if (errno == ENOSYS) {
|
|
||||||
return JNI_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_tcpFastopenMode(JNIEnv* env, jclass clazz) {
|
|
||||||
int fastopen = 0;
|
|
||||||
getSysctlValue("/proc/sys/net/ipv4/tcp_fastopen", &fastopen);
|
|
||||||
return fastopen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollet(JNIEnv* env, jclass clazz) {
|
|
||||||
return EPOLLET;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollin(JNIEnv* env, jclass clazz) {
|
|
||||||
return EPOLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollout(JNIEnv* env, jclass clazz) {
|
|
||||||
return EPOLLOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollrdhup(JNIEnv* env, jclass clazz) {
|
|
||||||
return EPOLLRDHUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_epollerr(JNIEnv* env, jclass clazz) {
|
|
||||||
return EPOLLERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_sizeofEpollEvent(JNIEnv* env, jclass clazz) {
|
|
||||||
return sizeof(struct epoll_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_offsetofEpollData(JNIEnv* env, jclass clazz) {
|
|
||||||
return offsetof(struct epoll_event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_splice0(JNIEnv* env, jclass clazz, jint fd, jlong offIn, jint fdOut, jlong offOut, jlong len) {
|
|
||||||
ssize_t res;
|
|
||||||
int err;
|
|
||||||
loff_t off_in = (loff_t) offIn;
|
|
||||||
loff_t off_out = (loff_t) offOut;
|
|
||||||
|
|
||||||
loff_t* p_off_in = off_in >= 0 ? &off_in : NULL;
|
|
||||||
loff_t* p_off_out = off_out >= 0 ? &off_out : NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
res = splice(fd, p_off_in, fdOut, p_off_out, (size_t) len, SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
|
||||||
// keep on splicing if it was interrupted
|
|
||||||
} while (res == -1 && ((err = errno) == EINTR));
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
return (jint) res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_tcpMd5SigMaxKeyLen(JNIEnv* env, jclass clazz) {
|
|
||||||
struct tcp_md5sig md5sig;
|
|
||||||
|
|
||||||
// Defensive size check
|
|
||||||
if (sizeof(md5sig.tcpm_key) < TCP_MD5SIG_MAXKEYLEN) {
|
|
||||||
return sizeof(md5sig.tcpm_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TCP_MD5SIG_MAXKEYLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static jint netty_epoll_native_registerUnix(JNIEnv* env, jclass clazz) {
|
|
||||||
register_unix_called = 1;
|
|
||||||
return netty_unix_register(env, staticPackagePrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
// JNI Registered Methods End
|
|
||||||
|
|
||||||
// JNI Method Registration Table Begin
|
|
||||||
static const JNINativeMethod statically_referenced_fixed_method_table[] = {
|
|
||||||
{ "epollet", "()I", (void *) netty_epoll_native_epollet },
|
|
||||||
{ "epollin", "()I", (void *) netty_epoll_native_epollin },
|
|
||||||
{ "epollout", "()I", (void *) netty_epoll_native_epollout },
|
|
||||||
{ "epollrdhup", "()I", (void *) netty_epoll_native_epollrdhup },
|
|
||||||
{ "epollerr", "()I", (void *) netty_epoll_native_epollerr },
|
|
||||||
{ "tcpMd5SigMaxKeyLen", "()I", (void *) netty_epoll_native_tcpMd5SigMaxKeyLen },
|
|
||||||
{ "isSupportingSendmmsg", "()Z", (void *) netty_epoll_native_isSupportingSendmmsg },
|
|
||||||
{ "isSupportingRecvmmsg", "()Z", (void *) netty_epoll_native_isSupportingRecvmmsg },
|
|
||||||
{ "tcpFastopenMode", "()I", (void *) netty_epoll_native_tcpFastopenMode },
|
|
||||||
{ "kernelVersion", "()Ljava/lang/String;", (void *) netty_epoll_native_kernelVersion }
|
|
||||||
};
|
|
||||||
static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]);
|
|
||||||
static const JNINativeMethod fixed_method_table[] = {
|
|
||||||
{ "eventFd", "()I", (void *) netty_epoll_native_eventFd },
|
|
||||||
{ "timerFd", "()I", (void *) netty_epoll_native_timerFd },
|
|
||||||
{ "eventFdWrite", "(IJ)V", (void *) netty_epoll_native_eventFdWrite },
|
|
||||||
{ "eventFdRead", "(I)V", (void *) netty_epoll_native_eventFdRead },
|
|
||||||
{ "epollCreate", "()I", (void *) netty_epoll_native_epollCreate },
|
|
||||||
{ "epollWait0", "(IJIIIIJ)J", (void *) netty_epoll_native_epollWait0 },
|
|
||||||
{ "epollWait", "(IJII)I", (void *) netty_epoll_native_epollWait },
|
|
||||||
{ "epollBusyWait0", "(IJI)I", (void *) netty_epoll_native_epollBusyWait0 },
|
|
||||||
{ "epollCtlAdd0", "(III)I", (void *) netty_epoll_native_epollCtlAdd0 },
|
|
||||||
{ "epollCtlMod0", "(III)I", (void *) netty_epoll_native_epollCtlMod0 },
|
|
||||||
{ "epollCtlDel0", "(II)I", (void *) netty_epoll_native_epollCtlDel0 },
|
|
||||||
// "sendmmsg0" has a dynamic signature
|
|
||||||
{ "sizeofEpollEvent", "()I", (void *) netty_epoll_native_sizeofEpollEvent },
|
|
||||||
{ "offsetofEpollData", "()I", (void *) netty_epoll_native_offsetofEpollData },
|
|
||||||
{ "splice0", "(IJIJJ)I", (void *) netty_epoll_native_splice0 },
|
|
||||||
{ "isSupportingUdpSegment", "()Z", (void *) netty_epoll_native_isSupportingUdpSegment },
|
|
||||||
{ "registerUnix", "()I", (void *) netty_epoll_native_registerUnix },
|
|
||||||
|
|
||||||
};
|
|
||||||
static const jint fixed_method_table_size = sizeof(fixed_method_table) / sizeof(fixed_method_table[0]);
|
|
||||||
|
|
||||||
static jint dynamicMethodsTableSize() {
|
|
||||||
return fixed_method_table_size + 3; // 3 is for the dynamic method signatures.
|
|
||||||
}
|
|
||||||
|
|
||||||
static JNINativeMethod* createDynamicMethodsTable(const char* packagePrefix) {
|
|
||||||
char* dynamicTypeName = NULL;
|
|
||||||
size_t size = sizeof(JNINativeMethod) * dynamicMethodsTableSize();
|
|
||||||
JNINativeMethod* dynamicMethods = malloc(size);
|
|
||||||
if (dynamicMethods == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(dynamicMethods, 0, size);
|
|
||||||
memcpy(dynamicMethods, fixed_method_table, sizeof(fixed_method_table));
|
|
||||||
|
|
||||||
JNINativeMethod* dynamicMethod = &dynamicMethods[fixed_method_table_size];
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;II)I", dynamicTypeName, error);
|
|
||||||
NETTY_JNI_UTIL_PREPEND("(IZ[L", dynamicTypeName, dynamicMethod->signature, error);
|
|
||||||
dynamicMethod->name = "sendmmsg0";
|
|
||||||
dynamicMethod->fnPtr = (void *) netty_epoll_native_sendmmsg0;
|
|
||||||
netty_jni_util_free_dynamic_name(&dynamicTypeName);
|
|
||||||
|
|
||||||
++dynamicMethod;
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;II)I", dynamicTypeName, error);
|
|
||||||
NETTY_JNI_UTIL_PREPEND("(IZ[L", dynamicTypeName, dynamicMethod->signature, error);
|
|
||||||
dynamicMethod->name = "recvmmsg0";
|
|
||||||
dynamicMethod->fnPtr = (void *) netty_epoll_native_recvmmsg0;
|
|
||||||
netty_jni_util_free_dynamic_name(&dynamicTypeName);
|
|
||||||
|
|
||||||
++dynamicMethod;
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket;)I", dynamicTypeName, error);
|
|
||||||
NETTY_JNI_UTIL_PREPEND("(IZL", dynamicTypeName, dynamicMethod->signature, error);
|
|
||||||
dynamicMethod->name = "recvmsg0";
|
|
||||||
dynamicMethod->fnPtr = (void *) netty_epoll_native_recvmsg0;
|
|
||||||
netty_jni_util_free_dynamic_name(&dynamicTypeName);
|
|
||||||
|
|
||||||
return dynamicMethods;
|
|
||||||
error:
|
|
||||||
free(dynamicTypeName);
|
|
||||||
netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// JNI Method Registration Table End
|
|
||||||
|
|
||||||
// IMPORTANT: If you add any NETTY_JNI_UTIL_LOAD_CLASS or NETTY_JNI_UTIL_FIND_CLASS calls you also need to update
|
|
||||||
// Native to reflect that.
|
|
||||||
static jint netty_epoll_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
|
|
||||||
int ret = JNI_ERR;
|
|
||||||
int staticallyRegistered = 0;
|
|
||||||
int nativeRegistered = 0;
|
|
||||||
int linuxsocketOnLoadCalled = 0;
|
|
||||||
char* nettyClassName = NULL;
|
|
||||||
jclass nativeDatagramPacketCls = NULL;
|
|
||||||
JNINativeMethod* dynamicMethods = NULL;
|
|
||||||
|
|
||||||
// We must register the statically referenced methods first!
|
|
||||||
if (netty_jni_util_register_natives(env,
|
|
||||||
packagePrefix,
|
|
||||||
STATICALLY_CLASSNAME,
|
|
||||||
statically_referenced_fixed_method_table,
|
|
||||||
statically_referenced_fixed_method_table_size) != 0) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
staticallyRegistered = 1;
|
|
||||||
|
|
||||||
// Register the methods which are not referenced by static member variables
|
|
||||||
dynamicMethods = createDynamicMethodsTable(packagePrefix);
|
|
||||||
if (dynamicMethods == NULL) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netty_jni_util_register_natives(env,
|
|
||||||
packagePrefix,
|
|
||||||
NATIVE_CLASSNAME,
|
|
||||||
dynamicMethods,
|
|
||||||
dynamicMethodsTableSize()) != 0) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
nativeRegistered = 1;
|
|
||||||
|
|
||||||
if (netty_epoll_linuxsocket_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
linuxsocketOnLoadCalled = 1;
|
|
||||||
|
|
||||||
// Initialize this module
|
|
||||||
NETTY_JNI_UTIL_PREPEND(packagePrefix, "io/netty/channel/epoll/NativeDatagramPacketArray$NativeDatagramPacket", nettyClassName, done);
|
|
||||||
NETTY_JNI_UTIL_FIND_CLASS(env, nativeDatagramPacketCls, nettyClassName, done);
|
|
||||||
netty_jni_util_free_dynamic_name(&nettyClassName);
|
|
||||||
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetSenderAddrFieldId, "senderAddr", "[B", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetSenderAddrLenFieldId, "senderAddrLen", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetSenderScopeIdFieldId, "senderScopeId", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetSenderPortFieldId, "senderPort", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetRecipientAddrFieldId, "recipientAddr", "[B", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetRecipientAddrLenFieldId, "recipientAddrLen", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetRecipientScopeIdFieldId, "recipientScopeId", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetRecipientPortFieldId, "recipientPort", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetSegmentSizeFieldId, "segmentSize", "I", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetMemoryAddressFieldId, "memoryAddress", "J", done);
|
|
||||||
NETTY_JNI_UTIL_GET_FIELD(env, nativeDatagramPacketCls, packetCountFieldId, "count", "I", done);
|
|
||||||
|
|
||||||
ret = NETTY_JNI_UTIL_JNI_VERSION;
|
|
||||||
|
|
||||||
staticPackagePrefix = packagePrefix;
|
|
||||||
|
|
||||||
// Check if there is an epoll_pwait2 system call and also if it works. One some systems it might be there
|
|
||||||
// but actually is not implemented and so fail with ENOSYS.
|
|
||||||
// See https://github.com/netty/netty/issues/12343
|
|
||||||
if (epoll_pwait2) {
|
|
||||||
int efd = epoll_create(1);
|
|
||||||
if (efd != -1) {
|
|
||||||
struct timespec ts = { 0, 0 };
|
|
||||||
struct epoll_event ev;
|
|
||||||
do {
|
|
||||||
if (epoll_pwait2(efd, &ev, 1, &ts, NULL) != -1) {
|
|
||||||
epoll_pwait2_supported = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(errno == EINTR);
|
|
||||||
close(efd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
|
|
||||||
netty_jni_util_free_dynamic_methods_table(dynamicMethods, fixed_method_table_size, dynamicMethodsTableSize());
|
|
||||||
free(nettyClassName);
|
|
||||||
|
|
||||||
if (ret == JNI_ERR) {
|
|
||||||
if (staticallyRegistered == 1) {
|
|
||||||
netty_jni_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME);
|
|
||||||
}
|
|
||||||
if (nativeRegistered == 1) {
|
|
||||||
netty_jni_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME);
|
|
||||||
}
|
|
||||||
if (linuxsocketOnLoadCalled == 1) {
|
|
||||||
netty_epoll_linuxsocket_JNI_OnUnLoad(env, packagePrefix);
|
|
||||||
}
|
|
||||||
packetSenderAddrFieldId = NULL;
|
|
||||||
packetSenderAddrLenFieldId = NULL;
|
|
||||||
packetSenderScopeIdFieldId = NULL;
|
|
||||||
packetSenderPortFieldId = NULL;
|
|
||||||
packetRecipientAddrFieldId = NULL;
|
|
||||||
packetRecipientAddrLenFieldId = NULL;
|
|
||||||
packetRecipientScopeIdFieldId = NULL;
|
|
||||||
packetRecipientPortFieldId = NULL;
|
|
||||||
packetSegmentSizeFieldId = NULL;
|
|
||||||
packetMemoryAddressFieldId = NULL;
|
|
||||||
packetCountFieldId = NULL;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_epoll_native_JNI_OnUnload(JNIEnv* env) {
|
|
||||||
netty_epoll_linuxsocket_JNI_OnUnLoad(env, staticPackagePrefix);
|
|
||||||
|
|
||||||
if (register_unix_called == 1) {
|
|
||||||
register_unix_called = 0;
|
|
||||||
netty_unix_unregister(env, staticPackagePrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
netty_jni_util_unregister_natives(env, staticPackagePrefix, STATICALLY_CLASSNAME);
|
|
||||||
netty_jni_util_unregister_natives(env, staticPackagePrefix, NATIVE_CLASSNAME);
|
|
||||||
|
|
||||||
if (staticPackagePrefix != NULL) {
|
|
||||||
free((void *) staticPackagePrefix);
|
|
||||||
staticPackagePrefix = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
packetSenderAddrFieldId = NULL;
|
|
||||||
packetSenderAddrLenFieldId = NULL;
|
|
||||||
packetSenderScopeIdFieldId = NULL;
|
|
||||||
packetSenderPortFieldId = NULL;
|
|
||||||
packetRecipientAddrFieldId = NULL;
|
|
||||||
packetRecipientAddrLenFieldId = NULL;
|
|
||||||
packetRecipientScopeIdFieldId = NULL;
|
|
||||||
packetRecipientPortFieldId = NULL;
|
|
||||||
packetSegmentSizeFieldId = NULL;
|
|
||||||
packetMemoryAddressFieldId = NULL;
|
|
||||||
packetCountFieldId = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked by the JVM when statically linked
|
|
||||||
|
|
||||||
// We build with -fvisibility=hidden so ensure we mark everything that needs to be visible with JNIEXPORT
|
|
||||||
// https://mail.openjdk.java.net/pipermail/core-libs-dev/2013-February/014549.html
|
|
||||||
|
|
||||||
// Invoked by the JVM when statically linked
|
|
||||||
JNIEXPORT jint JNI_OnLoad_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
|
|
||||||
return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_epoll", netty_epoll_native_JNI_OnLoad);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked by the JVM when statically linked
|
|
||||||
JNIEXPORT void JNI_OnUnload_netty_transport_native_epoll(JavaVM* vm, void* reserved) {
|
|
||||||
netty_jni_util_JNI_OnUnload(vm, reserved, netty_epoll_native_JNI_OnUnload);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NETTY_BUILD_STATIC
|
|
||||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|
||||||
return netty_jni_util_JNI_OnLoad(vm, reserved, "netty_transport_native_epoll", netty_epoll_native_JNI_OnLoad);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) {
|
|
||||||
netty_jni_util_JNI_OnUnload(vm, reserved, netty_epoll_native_JNI_OnUnload);
|
|
||||||
}
|
|
||||||
#endif /* NETTY_BUILD_STATIC */
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NETTY_EPOLL_VMSOCKET_H_
|
|
||||||
#define NETTY_EPOLL_VMSOCKET_H_
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#ifndef AF_VSOCK
|
|
||||||
#define AF_VSOCK 40
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sockaddr_vm {
|
|
||||||
sa_family_t svm_family;
|
|
||||||
unsigned short svm_reserved1;
|
|
||||||
unsigned int svm_port;
|
|
||||||
unsigned int svm_cid;
|
|
||||||
unsigned char svm_zero[sizeof(struct sockaddr) -
|
|
||||||
sizeof(sa_family_t) -
|
|
||||||
sizeof(unsigned short) -
|
|
||||||
sizeof(unsigned int) -
|
|
||||||
sizeof(unsigned int)];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* NETTY_EPOLL_VMSOCKET_H_ */
|
|
Binary file not shown.
|
@ -1,12 +1,4 @@
|
||||||
apply plugin: 'com.google.osdetector'
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(':netty-channel')
|
api project(':netty-channel')
|
||||||
api project(':netty-channel-unix')
|
api project(':netty-channel-unix')
|
||||||
testImplementation project(':netty-testsuite')
|
|
||||||
testImplementation project(':netty-handler')
|
|
||||||
testImplementation testLibs.assertj
|
|
||||||
testImplementation testLibs.rerunner.jupiter
|
|
||||||
testRuntimeOnly project(path: ':netty-channel-epoll-native', configuration: osdetector.classifier)
|
|
||||||
testRuntimeOnly project(path: ':netty-tcnative-boringssl-static-native', configuration: osdetector.classifier)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,212 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,307 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,190 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,189 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,263 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { }
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,178 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,264 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,313 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue