Skip to content

Commit 61b3ffd

Browse files
Feature: Allow setting a different port in the motd (#4293)
* Allow changing the broadcasted port using a system property. This may be needed if the port Geyser runs on & the port Bedrock players connect on do not match - e.g. due to port forwarding/different routing. * initial stab at making the broadcast port an (unsafe) config option * Automatically set broadcast port to be the bind port unless manually overridden * Warn about broadcast port mismatch * Use 0 instead of -1 as indicator to broadcast the port geyser is running on
1 parent 3f577f4 commit 61b3ffd

File tree

7 files changed

+81
-19
lines changed

7 files changed

+81
-19
lines changed

api/src/main/java/org/geysermc/geyser/api/network/BedrockListener.java

+8
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ public interface BedrockListener {
5050
*/
5151
int port();
5252

53+
/**
54+
* Gets the broadcast port that's sent to Bedrock clients with the motd.
55+
* This is the port that Bedrock clients will connect with. It usually does not differ from the listening port.
56+
*
57+
* @return the broadcast port
58+
*/
59+
int broadcastPort();
60+
5361
/**
5462
* Gets the primary MOTD shown to Bedrock players if a ping passthrough setting is not enabled.
5563
* <p>

core/src/main/java/org/geysermc/geyser/GeyserImpl.java

+16
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,22 @@ private void startInstance() {
314314
}
315315
}
316316

317+
String broadcastPort = System.getProperty("geyserBroadcastPort", "");
318+
if (!broadcastPort.isEmpty()) {
319+
int parsedPort;
320+
try {
321+
parsedPort = Integer.parseInt(broadcastPort);
322+
if (parsedPort < 1 || parsedPort > 65535) {
323+
throw new NumberFormatException("The broadcast port must be between 1 and 65535 inclusive!");
324+
}
325+
} catch (NumberFormatException e) {
326+
logger.error(String.format("Invalid broadcast port: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")"));
327+
parsedPort = config.getBedrock().port();
328+
}
329+
config.getBedrock().setBroadcastPort(parsedPort);
330+
logger.info("Broadcast port set from system property: " + parsedPort);
331+
}
332+
317333
boolean floodgatePresent = bootstrap.testFloodgatePluginPresent();
318334
if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) {
319335
logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " "

core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java

+29-17
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.geysermc.geyser.api.util.PlatformType;
3232
import org.geysermc.geyser.command.GeyserCommand;
3333
import org.geysermc.geyser.command.GeyserCommandSource;
34+
import org.geysermc.geyser.configuration.GeyserConfiguration;
3435
import org.geysermc.geyser.session.GeyserSession;
3536
import org.geysermc.geyser.text.GeyserLocale;
3637
import org.geysermc.geyser.util.LoopbackUtil;
@@ -84,7 +85,7 @@ public void execute(@Nullable GeyserSession session, GeyserCommandSource sender,
8485
return;
8586
}
8687
} else {
87-
port = 19132;
88+
port = geyser.getConfig().getBedrock().broadcastPort();
8889
}
8990
String ip = fullAddress[0];
9091

@@ -112,30 +113,41 @@ public void execute(@Nullable GeyserSession session, GeyserCommandSource sender,
112113
return;
113114
}
114115

115-
// Issue: do the ports not line up?
116-
if (port != geyser.getConfig().getBedrock().port()) {
117-
if (fullAddress.length == 2) {
118-
sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration ("
119-
+ geyser.getConfig().getBedrock().port() + ")");
120-
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config.");
121-
if (geyser.getConfig().getBedrock().isCloneRemotePort()) {
122-
sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead.");
116+
GeyserConfiguration config = geyser.getConfig();
117+
118+
// Issue: do the ports not line up? We only check this if players don't override the broadcast port - if they do, they (hopefully) know what they're doing
119+
if (config.getBedrock().broadcastPort() == config.getBedrock().port()) {
120+
if (port != config.getBedrock().port()) {
121+
if (fullAddress.length == 2) {
122+
sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration ("
123+
+ config.getBedrock().port() + ")");
124+
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config.");
125+
if (config.getBedrock().isCloneRemotePort()) {
126+
sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead.");
127+
}
128+
} else {
129+
sender.sendMessage("You did not specify the port to check (add it with \":<port>\"), " +
130+
"and the default port 19132 does not match the port in your Geyser configuration ("
131+
+ config.getBedrock().port() + ")!");
132+
sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`.");
123133
}
124-
} else {
125-
sender.sendMessage("You did not specify the port to check (add it with \":<port>\"), " +
126-
"and the default port 19132 does not match the port in your Geyser configuration ("
127-
+ geyser.getConfig().getBedrock().port() + ")!");
128-
sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`.");
134+
}
135+
} else {
136+
if (config.getBedrock().broadcastPort() != port) {
137+
sender.sendMessage("The port you are testing with (" + port + ") is not the same as the broadcast port set in your Geyser configuration ("
138+
+ config.getBedrock().broadcastPort() + "). ");
139+
sender.sendMessage("You ONLY need to change the broadcast port if clients connects with a port different from the port Geyser is running on.");
140+
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `broadcast-port` in the config.");
129141
}
130142
}
131143

132144
// Issue: is the `bedrock` `address` in the config different?
133-
if (!geyser.getConfig().getBedrock().address().equals("0.0.0.0")) {
145+
if (!config.getBedrock().address().equals("0.0.0.0")) {
134146
sender.sendMessage("The address specified in `bedrock` `address` is not \"0.0.0.0\" - this may cause issues unless this is deliberate and intentional.");
135147
}
136148

137149
// Issue: did someone turn on enable-proxy-protocol, and they didn't mean it?
138-
if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) {
150+
if (config.getBedrock().isEnableProxyProtocol()) {
139151
sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " +
140152
"Unless you're deliberately using additional software that REQUIRES this setting, you may not need it enabled.");
141153
}
@@ -166,7 +178,7 @@ public void execute(@Nullable GeyserSession session, GeyserCommandSource sender,
166178
String connectionTestMotd = "Geyser Connection Test " + randomStr;
167179
CONNECTION_TEST_MOTD = connectionTestMotd;
168180

169-
sender.sendMessage("Testing server connection now. Please wait...");
181+
sender.sendMessage("Testing server connection to " + ip + " with port: " + port + " now. Please wait...");
170182
JsonNode output;
171183
try {
172184
String hostname = URLEncoder.encode(ip, StandardCharsets.UTF_8);

core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ interface IBedrockConfiguration extends BedrockListener {
122122

123123
void setPort(int port);
124124

125+
void setBroadcastPort(int broadcastPort);
126+
125127
boolean isCloneRemotePort();
126128

127129
int getCompressionLevel();

core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java

+9
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,15 @@ public int port() {
172172
return port;
173173
}
174174

175+
@Setter
176+
@JsonProperty("broadcast-port")
177+
private int broadcastPort = 0;
178+
179+
@Override
180+
public int broadcastPort() {
181+
return broadcastPort;
182+
}
183+
175184
@Getter
176185
@JsonProperty("clone-remote-port")
177186
private boolean cloneRemotePort = false;

core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ public final class GeyserServer {
102102

103103
private ChannelFuture bootstrapFuture;
104104

105+
/**
106+
* The port to broadcast in the pong. This can be different from the port the server is bound to, e.g. due to port forwarding.
107+
*/
108+
private final int broadcastPort;
109+
105110
public GeyserServer(GeyserImpl geyser, int threadCount) {
106111
this.geyser = geyser;
107112
this.group = TRANSPORT.eventLoopGroupFactory().apply(threadCount);
@@ -115,6 +120,13 @@ public GeyserServer(GeyserImpl geyser, int threadCount) {
115120
} else {
116121
this.proxiedAddresses = null;
117122
}
123+
124+
// It's set to 0 only if no system property or manual config value was set
125+
if (geyser.getConfig().getBedrock().broadcastPort() == 0) {
126+
geyser.getConfig().getBedrock().setBroadcastPort(geyser.getConfig().getBedrock().port());
127+
}
128+
129+
this.broadcastPort = geyser.getConfig().getBedrock().broadcastPort();
118130
}
119131

120132
public CompletableFuture<Void> bind(InetSocketAddress address) {
@@ -243,8 +255,8 @@ public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {
243255
.nintendoLimited(false)
244256
.protocolVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
245257
.version(GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()) // Required to not be empty as of 1.16.210.59. Can only contain . and numbers.
246-
.ipv4Port(this.geyser.getConfig().getBedrock().port())
247-
.ipv6Port(this.geyser.getConfig().getBedrock().port())
258+
.ipv4Port(this.broadcastPort)
259+
.ipv6Port(this.broadcastPort)
248260
.serverId(bootstrapFuture.channel().config().getOption(RakChannelOption.RAK_GUID));
249261

250262
if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {

core/src/main/resources/config.yml

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ bedrock:
3030
# How much to compress network traffic to the Bedrock client. The higher the number, the more CPU usage used, but
3131
# the smaller the bandwidth used. Does not have any effect below -1 or above 9. Set to -1 to disable.
3232
compression-level: 6
33+
# The port to broadcast to Bedrock clients with the MOTD that they should use to connect to the server.
34+
# DO NOT uncomment and change this unless Geyser runs on a different internal port than the one that is used to connect.
35+
# broadcast-port: 19132
3336
# Whether to enable PROXY protocol or not for clients. You DO NOT WANT this feature unless you run UDP reverse proxy
3437
# in front of your Geyser instance.
3538
enable-proxy-protocol: false

0 commit comments

Comments
 (0)