Skip to content

Commit edc2323

Browse files
Reimplement session structure (#869)
* Reimplement session structure Benefits are clear, developers can easily provide custom behaviour by overriding the server and client classes to provide custom channels (like geyser does for localchannel) and also custom channel handlers can be provided, like for ViaVersion support. Transfers were moved to a flag. There are now ClientSession and ServerSession interfaces which extend Session. This way a ServerSession doesn't have connect methods. Binding to UnixDomainSockets or any other type of SocketAddress is now supported and the client can connect to those too. Tcp was renamed to Net because now non-tcp protocols like local channels and udp (for bedrock ViaBedrock) can be used. * Split up server groups and share channel initializer code This allows us to share more code between server and client. Additionally, the split worker groups allow mcpl to handle server packets more closely to vanilla and reduce timeouts during load. * Allow more code sharing for custom implementations * Fill in arbitrary values for remote address if ipv6 client connects to ipv4 server and vice verse * Use proper separator for ipv6 * Fix channel method signature * Update protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ClientListener.java Co-authored-by: chris <github@onechris.mozmail.com> * Update protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ClientListener.java Co-authored-by: chris <github@onechris.mozmail.com> * Update protocol/src/main/java/org/geysermc/mcprotocollib/network/net/NetClientSession.java Co-authored-by: chris <github@onechris.mozmail.com> * Add log * Implement resolving InetSocketAddresses is unresolved * Rename net package and drop prefix for most classes * Move session and server into their own packages * Rename Net prefix to network * Add ClientNetworkSession factory and pass props properly when following redirects --------- Co-authored-by: chris <github@onechris.mozmail.com>
1 parent 1daf036 commit edc2323

32 files changed

+738
-492
lines changed

example/src/main/java/org/geysermc/mcprotocollib/network/example/PingServerTest.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package org.geysermc.mcprotocollib.network.example;
22

3+
import org.geysermc.mcprotocollib.network.ClientSession;
34
import org.geysermc.mcprotocollib.network.Server;
4-
import org.geysermc.mcprotocollib.network.Session;
5-
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
6-
import org.geysermc.mcprotocollib.network.tcp.TcpServer;
5+
import org.geysermc.mcprotocollib.network.factory.ClientNetworkSessionFactory;
6+
import org.geysermc.mcprotocollib.network.server.NetworkServer;
77
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
99

1010
import javax.crypto.KeyGenerator;
1111
import javax.crypto.SecretKey;
12+
import java.net.InetSocketAddress;
1213
import java.security.NoSuchAlgorithmException;
1314

1415
public class PingServerTest {
@@ -25,11 +26,14 @@ public static void main(String[] args) {
2526
return;
2627
}
2728

28-
Server server = new TcpServer("127.0.0.1", 25565, TestProtocol::new);
29+
Server server = new NetworkServer(new InetSocketAddress("127.0.0.1", 25565), TestProtocol::new);
2930
server.addListener(new ServerListener(key));
3031
server.bind();
3132

32-
Session client = new TcpClientSession("127.0.0.1", 25565, new TestProtocol(key));
33+
ClientSession client = ClientNetworkSessionFactory.factory()
34+
.setAddress("127.0.0.1", 25565)
35+
.setProtocol(new TestProtocol(key))
36+
.create();
3337
client.connect();
3438
}
3539
}

example/src/main/java/org/geysermc/mcprotocollib/network/example/ServerListener.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public ServerListener(SecretKey key) {
2121

2222
@Override
2323
public void serverBound(ServerBoundEvent event) {
24-
log.info("SERVER Bound: {}:{}", event.getServer().getHost(), event.getServer().getPort());
24+
log.info("SERVER Bound: {}", event.getServer().getBindAddress());
2525
}
2626

2727
@Override
@@ -36,14 +36,14 @@ public void serverClosed(ServerClosedEvent event) {
3636

3737
@Override
3838
public void sessionAdded(SessionAddedEvent event) {
39-
log.info("SERVER Session Added: {}:{}", event.getSession().getHost(), event.getSession().getPort());
39+
log.info("SERVER Session Added: {}", event.getSession().getRemoteAddress());
4040
((TestProtocol) event.getSession().getPacketProtocol()).setSecretKey(this.key);
4141
event.getSession().setEncryption(((TestProtocol) event.getSession().getPacketProtocol()).getEncryption());
4242
}
4343

4444
@Override
4545
public void sessionRemoved(SessionRemovedEvent event) {
46-
log.info("SERVER Session Removed: {}:{}", event.getSession().getHost(), event.getSession().getPort());
46+
log.info("SERVER Session Removed: {}", event.getSession().getRemoteAddress());
4747
event.getServer().close(false);
4848
}
4949
}

example/src/main/java/org/geysermc/mcprotocollib/network/example/TestProtocol.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public EncryptionConfig getEncryption() {
7272
}
7373

7474
@Override
75-
public void newClientSession(Session session, boolean transferring) {
75+
public void newClientSession(Session session) {
7676
session.addListener(new ClientSessionListener());
7777
}
7878

example/src/main/java/org/geysermc/mcprotocollib/protocol/example/MinecraftProtocolTest.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import net.raphimc.minecraftauth.step.msa.StepCredentialsMsaCode;
1212
import org.geysermc.mcprotocollib.auth.GameProfile;
1313
import org.geysermc.mcprotocollib.auth.SessionService;
14+
import org.geysermc.mcprotocollib.network.ClientSession;
1415
import org.geysermc.mcprotocollib.network.ProxyInfo;
1516
import org.geysermc.mcprotocollib.network.Server;
1617
import org.geysermc.mcprotocollib.network.Session;
@@ -20,9 +21,9 @@
2021
import org.geysermc.mcprotocollib.network.event.server.SessionRemovedEvent;
2122
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
2223
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
24+
import org.geysermc.mcprotocollib.network.factory.ClientNetworkSessionFactory;
2325
import org.geysermc.mcprotocollib.network.packet.Packet;
24-
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
25-
import org.geysermc.mcprotocollib.network.tcp.TcpServer;
26+
import org.geysermc.mcprotocollib.network.server.NetworkServer;
2627
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
2728
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
2829
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
@@ -38,6 +39,8 @@
3839
import org.slf4j.Logger;
3940
import org.slf4j.LoggerFactory;
4041

42+
import java.net.InetSocketAddress;
43+
import java.net.SocketAddress;
4144
import java.nio.charset.StandardCharsets;
4245
import java.time.Instant;
4346
import java.util.ArrayList;
@@ -50,8 +53,7 @@ public class MinecraftProtocolTest {
5053
private static final boolean SPAWN_SERVER = true;
5154
private static final boolean ENCRYPT_CONNECTION = true;
5255
private static final boolean SHOULD_AUTHENTICATE = false;
53-
private static final String HOST = "127.0.0.1";
54-
private static final int PORT = 25565;
56+
private static final SocketAddress ADDRESS = new InetSocketAddress("127.0.0.1", 25565);
5557
private static final ProxyInfo PROXY = null;
5658
private static final ProxyInfo AUTH_PROXY = null;
5759
private static final String USERNAME = "Username";
@@ -62,7 +64,7 @@ public static void main(String[] args) {
6264
SessionService sessionService = new SessionService();
6365
sessionService.setProxy(AUTH_PROXY);
6466

65-
Server server = new TcpServer(HOST, PORT, MinecraftProtocol::new);
67+
Server server = new NetworkServer(ADDRESS, MinecraftProtocol::new);
6668
server.setGlobalFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
6769
server.setGlobalFlag(MinecraftConstants.ENCRYPT_CONNECTION, ENCRYPT_CONNECTION);
6870
server.setGlobalFlag(MinecraftConstants.SHOULD_AUTHENTICATE, SHOULD_AUTHENTICATE);
@@ -155,7 +157,11 @@ private static void status() {
155157
sessionService.setProxy(AUTH_PROXY);
156158

157159
MinecraftProtocol protocol = new MinecraftProtocol();
158-
Session client = new TcpClientSession(HOST, PORT, protocol, PROXY);
160+
ClientSession client = ClientNetworkSessionFactory.factory()
161+
.setRemoteSocketAddress(ADDRESS)
162+
.setProtocol(protocol)
163+
.setProxy(PROXY)
164+
.create();
159165
client.setFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
160166
client.setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, (session, info) -> {
161167
log.info("Version: {}, {}", info.getVersionInfo().getVersionName(), info.getVersionInfo().getProtocolVersion());
@@ -203,7 +209,12 @@ private static void login() {
203209
SessionService sessionService = new SessionService();
204210
sessionService.setProxy(AUTH_PROXY);
205211

206-
Session client = new TcpClientSession(HOST, PORT, protocol, PROXY);
212+
213+
ClientSession client = ClientNetworkSessionFactory.factory()
214+
.setRemoteSocketAddress(ADDRESS)
215+
.setProtocol(protocol)
216+
.setProxy(PROXY)
217+
.create();
207218
client.setFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
208219
client.addListener(new SessionAdapter() {
209220
@Override

protocol/src/main/java/org/geysermc/mcprotocollib/network/BuiltinFlags.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ public class BuiltinFlags {
1313
*/
1414
public static final Flag<InetSocketAddress> CLIENT_PROXIED_ADDRESS = new Flag<>("client-proxied-address", InetSocketAddress.class);
1515

16+
/**
17+
* Whether the current client is transferring.
18+
*/
19+
public static final Flag<Boolean> CLIENT_TRANSFERRING = new Flag<>("transferring", Boolean.class);
20+
1621
/**
1722
* When set to false, an SRV record resolve is not attempted.
1823
*/
@@ -34,7 +39,7 @@ public class BuiltinFlags {
3439
* Used by both the server and client.
3540
*/
3641
public static final Flag<Integer> READ_TIMEOUT = new Flag<>("read-timeout", Integer.class);
37-
42+
3843
/**
3944
* Write timeout in seconds.
4045
* Used by both the server and client.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.geysermc.mcprotocollib.network;
2+
3+
import org.checkerframework.checker.nullness.qual.Nullable;
4+
5+
/**
6+
* A network client session.
7+
*/
8+
public interface ClientSession extends Session {
9+
/**
10+
* Connects this session to its host and port.
11+
*/
12+
default void connect() {
13+
connect(true);
14+
}
15+
16+
/**
17+
* Connects this session to its host and port.
18+
*
19+
* @param wait Whether to wait for the connection to be established before returning.
20+
*/
21+
void connect(boolean wait);
22+
23+
/**
24+
* Get the proxy used by this session.
25+
*
26+
* @return The proxy used by this session.
27+
*/
28+
@Nullable ProxyInfo getProxy();
29+
}

protocol/src/main/java/org/geysermc/mcprotocollib/network/Server.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import org.geysermc.mcprotocollib.network.event.server.ServerListener;
44
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
5+
import org.geysermc.mcprotocollib.network.server.AbstractServer;
56

7+
import java.net.SocketAddress;
68
import java.util.List;
79
import java.util.Map;
810
import java.util.function.Supplier;
@@ -12,18 +14,11 @@
1214
*/
1315
public interface Server {
1416
/**
15-
* Gets the host the session is listening on.
17+
* Gets the bind address the server is listening on.
1618
*
17-
* @return The listening host.
19+
* @return The listening bind address.
1820
*/
19-
String getHost();
20-
21-
/**
22-
* Gets the port the session is listening on.
23-
*
24-
* @return The listening port.
25-
*/
26-
int getPort();
21+
SocketAddress getBindAddress();
2722

2823
/**
2924
* Gets the packet protocol of the server.
@@ -62,19 +57,28 @@ public interface Server {
6257
* @return Value of the flag.
6358
* @throws IllegalStateException If the flag's value isn't of the required type.
6459
*/
65-
<T> T getGlobalFlag(Flag<T> flag);
60+
default <T> T getGlobalFlag(Flag<T> flag) {
61+
return getGlobalFlagSupplied(flag, () -> null);
62+
}
63+
64+
/**
65+
* @see #getGlobalFlagSupplied(Flag, Supplier)
66+
*/
67+
default <T> T getGlobalFlag(Flag<T> flag, T def) {
68+
return getGlobalFlagSupplied(flag, () -> def);
69+
}
6670

6771
/**
6872
* Gets the value of the given flag as an instance of the given type.
6973
* If the flag is not set, the specified default value will be returned.
7074
*
7175
* @param <T> Type of the flag.
7276
* @param flag Flag to check for.
73-
* @param def Default value of the flag.
77+
* @param defSupplier Default value supplier.
7478
* @return Value of the flag.
7579
* @throws IllegalStateException If the flag's value isn't of the required type.
7680
*/
77-
<T> T getGlobalFlag(Flag<T> flag, T def);
81+
<T> T getGlobalFlagSupplied(Flag<T> flag, Supplier<T> defSupplier);
7882

7983
/**
8084
* Sets the value of a flag. The flag will be used in sessions if a session does
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.geysermc.mcprotocollib.network;
2+
3+
/**
4+
* A network server session.
5+
*/
6+
public interface ServerSession extends Session {
7+
}

protocol/src/main/java/org/geysermc/mcprotocollib/network/Session.java

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,53 +9,21 @@
99
import org.geysermc.mcprotocollib.network.crypt.EncryptionConfig;
1010
import org.geysermc.mcprotocollib.network.event.session.SessionEvent;
1111
import org.geysermc.mcprotocollib.network.event.session.SessionListener;
12+
import org.geysermc.mcprotocollib.network.netty.FlushHandler;
1213
import org.geysermc.mcprotocollib.network.packet.Packet;
1314
import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
14-
import org.geysermc.mcprotocollib.network.tcp.FlushHandler;
1515

1616
import java.net.SocketAddress;
1717
import java.util.List;
1818
import java.util.Map;
19+
import java.util.concurrent.Executor;
20+
import java.util.function.Supplier;
1921

2022
/**
2123
* A network session.
2224
*/
2325
public interface Session {
2426

25-
/**
26-
* Connects this session to its host and port.
27-
*/
28-
void connect();
29-
30-
/**
31-
* Connects this session to its host and port.
32-
*
33-
* @param wait Whether to wait for the connection to be established before returning.
34-
*/
35-
void connect(boolean wait);
36-
37-
/**
38-
* Connects this session to its host and port.
39-
*
40-
* @param wait Whether to wait for the connection to be established before returning.
41-
* @param transferring Whether the session is a client being transferred.
42-
*/
43-
void connect(boolean wait, boolean transferring);
44-
45-
/**
46-
* Gets the host the session is connected to.
47-
*
48-
* @return The connected host.
49-
*/
50-
String getHost();
51-
52-
/**
53-
* Gets the port the session is connected to.
54-
*
55-
* @return The connected port.
56-
*/
57-
int getPort();
58-
5927
/**
6028
* Gets the local address of the session.
6129
*
@@ -111,7 +79,16 @@ public interface Session {
11179
* @return Value of the flag.
11280
* @throws IllegalStateException If the flag's value isn't of the required type.
11381
*/
114-
<T> T getFlag(Flag<T> flag);
82+
default <T> T getFlag(Flag<T> flag) {
83+
return this.getFlagSupplied(flag, () -> null);
84+
}
85+
86+
/**
87+
* @see #getFlagSupplied(Flag, Supplier)
88+
*/
89+
default <T> T getFlag(Flag<T> flag, T def) {
90+
return this.getFlagSupplied(flag, () -> def);
91+
}
11592

11693
/**
11794
* Gets the value of the given flag as an instance of the given type. If this
@@ -120,11 +97,11 @@ public interface Session {
12097
*
12198
* @param <T> Type of the flag.
12299
* @param flag Flag to check for.
123-
* @param def Default value of the flag.
100+
* @param defSupplier Default value supplier.
124101
* @return Value of the flag.
125102
* @throws IllegalStateException If the flag's value isn't of the required type.
126103
*/
127-
<T> T getFlag(Flag<T> flag, T def);
104+
<T> T getFlagSupplied(Flag<T> flag, Supplier<T> defSupplier);
128105

129106
/**
130107
* Sets the value of a flag. This does not change a server's flags if this session
@@ -286,6 +263,13 @@ default void disconnect(@NonNull Component reason) {
286263
*/
287264
Channel getChannel();
288265

266+
/**
267+
* Returns the executor that handles packet handling.
268+
*
269+
* @return The packet handler executor
270+
*/
271+
Executor getPacketHandlerExecutor();
272+
289273
/**
290274
* Changes the inbound state of the session and then re-enables auto read.
291275
* This is used after a terminal packet was handled and the session is ready to receive more packets in the new state.

0 commit comments

Comments
 (0)