Skip to content

Commit 089b217

Browse files
committed
Initial commit
1 parent 72223ec commit 089b217

File tree

5 files changed

+140
-7
lines changed

5 files changed

+140
-7
lines changed

pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@
4242
<version>2.0.2-SNAPSHOT</version>
4343
<scope>provided</scope>
4444
</dependency>
45+
<dependency>
46+
<groupId>io.netty.incubator</groupId>
47+
<artifactId>netty-incubator-codec-native-quic</artifactId>
48+
<version>0.0.57.Final</version>
49+
<classifier>linux-x86_64</classifier>
50+
</dependency>
4551
</dependencies>
4652

4753
<build>

src/main/java/org/nethergames/proxytransport/ProxyTransport.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import dev.waterdog.waterdogpe.network.protocol.ProtocolCodecs;
44
import dev.waterdog.waterdogpe.plugin.Plugin;
5-
import org.nethergames.proxytransport.integration.CustomTransportServerInfo;
5+
import org.nethergames.proxytransport.integration.QuicTransportServerInfo;
66
import org.nethergames.proxytransport.utils.CodecUpdater;
77

88
public class ProxyTransport extends Plugin {
@@ -12,7 +12,7 @@ public void onStartup() {
1212
ProtocolCodecs.addUpdater(new CodecUpdater());
1313

1414
getLogger().info("ProxyTransport was started.");
15-
getLogger().info("Registered type with name {}", CustomTransportServerInfo.TYPE.getIdentifier());
15+
getLogger().info("Registered type with name {}", QuicTransportServerInfo.TYPE.getIdentifier());
1616
}
1717

1818
@Override

src/main/java/org/nethergames/proxytransport/integration/CustomClientEventHandler.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import io.netty.channel.ChannelInboundHandlerAdapter;
77

88
public class CustomClientEventHandler extends ChannelInboundHandlerAdapter {
9-
public static final String NAME = "tcp-client-event-handler";
9+
public static final String NAME = "client-event-handler";
1010

1111
private final ProxiedPlayer player;
1212
private final ClientConnection connection;
@@ -27,7 +27,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E
2727
return;
2828
}
2929

30-
this.player.getLogger().warning("[" + connection.getSocketAddress() + "|" + this.player.getName() + "] - Exception in TCP connection caught", cause);
30+
this.player.getLogger().warning("[" + connection.getSocketAddress() + "|" + this.player.getName() + "] - Exception in connection caught", cause);
3131
this.player.onDownstreamTimeout(this.connection.getServerInfo());
3232

3333
this.connection.disconnect();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package org.nethergames.proxytransport.integration;
2+
3+
import dev.waterdog.waterdogpe.network.connection.client.ClientConnection;
4+
import dev.waterdog.waterdogpe.network.serverinfo.ServerInfo;
5+
import dev.waterdog.waterdogpe.network.serverinfo.ServerInfoType;
6+
import dev.waterdog.waterdogpe.player.ProxiedPlayer;
7+
import io.netty.bootstrap.Bootstrap;
8+
import io.netty.channel.*;
9+
import io.netty.channel.epoll.Epoll;
10+
import io.netty.channel.epoll.EpollDatagramChannel;
11+
import io.netty.channel.epoll.EpollEventLoopGroup;
12+
import io.netty.channel.nio.NioEventLoopGroup;
13+
import io.netty.channel.socket.DatagramChannel;
14+
import io.netty.channel.socket.nio.NioDatagramChannel;
15+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
16+
import io.netty.incubator.codec.quic.*;
17+
import io.netty.util.concurrent.Future;
18+
import io.netty.util.concurrent.Promise;
19+
import net.jodah.expiringmap.internal.NamedThreadFactory;
20+
import org.nethergames.proxytransport.impl.TransportChannelInitializer;
21+
22+
import java.net.InetSocketAddress;
23+
import java.util.HashMap;
24+
import java.util.concurrent.ThreadFactory;
25+
import java.util.concurrent.TimeUnit;
26+
27+
public class QuicTransportServerInfo extends ServerInfo {
28+
public static final int availableCPU = Runtime.getRuntime().availableProcessors();
29+
public static final ThreadFactory downstreamThreadFactory = new NamedThreadFactory("QUIC-Downstream %s");
30+
public static final EventLoopGroup downstreamLoopGroup = Epoll.isAvailable() ? new EpollEventLoopGroup(availableCPU, downstreamThreadFactory) : new NioEventLoopGroup(availableCPU, downstreamThreadFactory);
31+
32+
public static final String TYPE_IDENT = "quic";
33+
public static final ServerInfoType TYPE = ServerInfoType.builder()
34+
.identifier(TYPE_IDENT)
35+
.serverInfoFactory(QuicTransportServerInfo::new)
36+
.register();
37+
38+
private final HashMap<InetSocketAddress, Future<QuicChannel>> serverConnections = new HashMap<>();
39+
40+
public QuicTransportServerInfo(String serverName, InetSocketAddress address, InetSocketAddress publicAddress) {
41+
super(serverName, address, publicAddress);
42+
}
43+
44+
@Override
45+
public ServerInfoType getServerType() {
46+
return TYPE;
47+
}
48+
49+
@Override
50+
public Future<ClientConnection> createConnection(ProxiedPlayer proxiedPlayer) {
51+
EventLoop eventLoop = proxiedPlayer.getProxy().getWorkerEventLoopGroup().next();
52+
Promise<ClientConnection> promise = eventLoop.newPromise();
53+
54+
this.createServerConnection(eventLoop, this.getAddress()).addListener((Future<QuicChannel> future) -> {
55+
if (future.isSuccess()) {
56+
QuicChannel quicChannel = future.getNow();
57+
58+
quicChannel.createStream(QuicStreamType.BIDIRECTIONAL, new TransportChannelInitializer(proxiedPlayer, this, promise)).addListener((Future<QuicStreamChannel> streamFuture) -> {
59+
if (!streamFuture.isSuccess()) {
60+
promise.tryFailure(streamFuture.cause());
61+
quicChannel.close();
62+
}
63+
});
64+
} else {
65+
promise.tryFailure(future.cause());
66+
}
67+
});
68+
69+
return promise;
70+
}
71+
72+
private Future<QuicChannel> createServerConnection(EventLoopGroup eventLoopGroup, InetSocketAddress address) {
73+
EventLoop eventLoop = eventLoopGroup.next();
74+
75+
if (this.serverConnections.containsKey(address)) {
76+
return this.serverConnections.get(address);
77+
}
78+
79+
Promise<QuicChannel> promise = eventLoop.newPromise();
80+
this.serverConnections.put(address, promise);
81+
82+
QuicSslContext sslContext = QuicSslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).applicationProtocols("ng").build();
83+
ChannelHandler codec = new QuicClientCodecBuilder()
84+
.sslContext(sslContext)
85+
.maxIdleTimeout(5000, TimeUnit.MILLISECONDS)
86+
.initialMaxData(10000000)
87+
.initialMaxStreamDataBidirectionalLocal(1000000)
88+
.build();
89+
90+
new Bootstrap()
91+
.group(downstreamLoopGroup)
92+
.handler(codec)
93+
.channel(getProperSocketChannel())
94+
.bind(0).addListener((ChannelFuture channelFuture) -> {
95+
if (channelFuture.isSuccess()) {
96+
QuicChannel.newBootstrap(channelFuture.channel())
97+
.streamHandler(new ChannelInboundHandlerAdapter() {
98+
@Override
99+
public void channelActive(ChannelHandlerContext ctx) {
100+
ctx.close();
101+
}
102+
})
103+
.remoteAddress(address)
104+
.connect().addListener((Future<QuicChannel> quicChannelFuture) -> {
105+
if (quicChannelFuture.isSuccess()) {
106+
QuicChannel quicChannel = quicChannelFuture.getNow();
107+
quicChannel.closeFuture().addListener(f -> serverConnections.remove(address));
108+
109+
promise.trySuccess(quicChannel);
110+
} else {
111+
promise.tryFailure(quicChannelFuture.cause());
112+
channelFuture.channel().close();
113+
}
114+
});
115+
} else {
116+
promise.tryFailure(channelFuture.cause());
117+
channelFuture.channel().close();
118+
}
119+
});
120+
121+
return promise;
122+
}
123+
124+
public Class<? extends DatagramChannel> getProperSocketChannel() {
125+
return Epoll.isAvailable() ? EpollDatagramChannel.class : NioDatagramChannel.class;
126+
}
127+
}

src/main/java/org/nethergames/proxytransport/integration/CustomTransportServerInfo.java renamed to src/main/java/org/nethergames/proxytransport/integration/TcpTransportServerInfo.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@
2222
import java.net.InetSocketAddress;
2323
import java.util.concurrent.ThreadFactory;
2424

25-
public class CustomTransportServerInfo extends ServerInfo {
25+
public class TcpTransportServerInfo extends ServerInfo {
2626
public static final int availableCPU = Runtime.getRuntime().availableProcessors();
2727
public static final ThreadFactory downstreamThreadFactory = new NamedThreadFactory("TCP-Downstream %s");
2828
public static final EventLoopGroup downstreamLoopGroup = Epoll.isAvailable() ? new EpollEventLoopGroup(availableCPU, downstreamThreadFactory) : new NioEventLoopGroup(availableCPU, downstreamThreadFactory);
2929

3030
public static final String TYPE_IDENT = "tcp";
3131
public static final ServerInfoType TYPE = ServerInfoType.builder()
3232
.identifier(TYPE_IDENT)
33-
.serverInfoFactory(CustomTransportServerInfo::new)
33+
.serverInfoFactory(TcpTransportServerInfo::new)
3434
.register();
3535

36-
public CustomTransportServerInfo(String serverName, InetSocketAddress address, InetSocketAddress publicAddress) {
36+
public TcpTransportServerInfo(String serverName, InetSocketAddress address, InetSocketAddress publicAddress) {
3737
super(serverName, address, publicAddress);
3838
}
3939

0 commit comments

Comments
 (0)