SRV improvements and improvements for GeyserConnect (#2048)

- Individual per-player remote, port, and address
- Removal of RemoteServer class
- Do SRV lookup on startup and that's it
This commit is contained in:
Camotoy 2021-03-17 11:15:57 -04:00 committed by GitHub
parent 3d4fff8dee
commit b176fc7a2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 61 deletions

View file

@ -140,9 +140,9 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.steveice10</groupId> <groupId>com.github.GeyserMC</groupId>
<artifactId>PacketLib</artifactId> <artifactId>PacketLib</artifactId>
<version>54f761c</version> <version>b77a427</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib --> <exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib -->

View file

@ -40,7 +40,6 @@ import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.metrics.Metrics; import org.geysermc.connector.metrics.Metrics;
import org.geysermc.connector.network.ConnectorServerEventHandler; import org.geysermc.connector.network.ConnectorServerEventHandler;
import org.geysermc.connector.network.remote.RemoteServer;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.BiomeTranslator; import org.geysermc.connector.network.translators.BiomeTranslator;
import org.geysermc.connector.network.translators.EntityIdentifierRegistry; import org.geysermc.connector.network.translators.EntityIdentifierRegistry;
@ -97,9 +96,8 @@ public class GeyserConnector {
private static GeyserConnector instance; private static GeyserConnector instance;
private RemoteServer remoteServer;
@Setter @Setter
private AuthType authType; private AuthType defaultAuthType;
private boolean shuttingDown = false; private boolean shuttingDown = false;
@ -166,7 +164,7 @@ public class GeyserConnector {
String remoteAddress = config.getRemote().getAddress(); String remoteAddress = config.getRemote().getAddress();
int remotePort = config.getRemote().getPort(); int remotePort = config.getRemote().getPort();
// Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry. // Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry.
if ((config.isLegacyPingPassthrough() || platformType == PlatformType.STANDALONE) && !remoteAddress.matches(IP_REGEX) && !remoteAddress.equalsIgnoreCase("localhost")) { if (!remoteAddress.matches(IP_REGEX) && !remoteAddress.equalsIgnoreCase("localhost")) {
try { try {
// Searches for a server address and a port from a SRV record of the specified host name // Searches for a server address and a port from a SRV record of the specified host name
InitialDirContext ctx = new InitialDirContext(); InitialDirContext ctx = new InitialDirContext();
@ -186,8 +184,7 @@ public class GeyserConnector {
} }
} }
remoteServer = new RemoteServer(config.getRemote().getAddress(), remotePort); defaultAuthType = AuthType.getByName(config.getRemote().getAuthType());
authType = AuthType.getByName(config.getRemote().getAuthType());
CooldownUtils.setShowCooldown(config.isShowCooldown()); CooldownUtils.setShowCooldown(config.isShowCooldown());
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
@ -334,8 +331,7 @@ public class GeyserConnector {
generalThreadPool.shutdown(); generalThreadPool.shutdown();
bedrockServer.close(); bedrockServer.close();
players.clear(); players.clear();
remoteServer = null; defaultAuthType = null;
authType = null;
this.getCommandManager().getCommands().clear(); this.getCommandManager().getCommands().clear();
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.done")); bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.done"));
@ -371,6 +367,7 @@ public class GeyserConnector {
* @param xuid the Xbox user identifier * @param xuid the Xbox user identifier
* @return the player or <code>null</code> if there is no player online with this xuid * @return the player or <code>null</code> if there is no player online with this xuid
*/ */
@SuppressWarnings("unused") // API usage
public GeyserSession getPlayerByXuid(String xuid) { public GeyserSession getPlayerByXuid(String xuid) {
for (GeyserSession session : players) { for (GeyserSession session : players) {
if (session.getAuthData() != null && session.getAuthData().getXboxUUID().equals(xuid)) { if (session.getAuthData() != null && session.getAuthData().getXboxUUID().equals(xuid)) {

View file

@ -97,7 +97,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
public boolean handle(ResourcePackClientResponsePacket packet) { public boolean handle(ResourcePackClientResponsePacket packet) {
switch (packet.getStatus()) { switch (packet.getStatus()) {
case COMPLETED: case COMPLETED:
session.connect(connector.getRemoteServer()); session.connect();
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.connect", session.getAuthData().getName())); connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.connect", session.getAuthData().getName()));
break; break;
@ -186,7 +186,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
public boolean handle(SetLocalPlayerAsInitializedPacket packet) { public boolean handle(SetLocalPlayerAsInitializedPacket packet) {
LanguageUtils.loadGeyserLocale(session.getLocale()); LanguageUtils.loadGeyserLocale(session.getLocale());
if (!session.isLoggedIn() && !session.isLoggingIn() && session.getConnector().getAuthType() == AuthType.ONLINE) { if (!session.isLoggedIn() && !session.isLoggingIn() && session.getRemoteAuthType() == AuthType.ONLINE) {
// TODO it is safer to key authentication on something that won't change (UUID, not username) // TODO it is safer to key authentication on something that won't change (UUID, not username)
if (!couldLoginUserByName(session.getAuthData().getName())) { if (!couldLoginUserByName(session.getAuthData().getName())) {
LoginEncryptionUtils.showLoginWindow(session); LoginEncryptionUtils.showLoginWindow(session);

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.network.remote;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class RemoteServer {
private String address;
private int port;
}

View file

@ -81,7 +81,6 @@ import org.geysermc.connector.entity.player.SessionPlayerEntity;
import org.geysermc.connector.entity.player.SkullPlayerEntity; import org.geysermc.connector.entity.player.SkullPlayerEntity;
import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.inventory.PlayerInventory;
import org.geysermc.connector.network.remote.RemoteServer;
import org.geysermc.connector.network.session.auth.AuthData; import org.geysermc.connector.network.session.auth.AuthData;
import org.geysermc.connector.network.session.auth.BedrockClientData; import org.geysermc.connector.network.session.auth.BedrockClientData;
import org.geysermc.connector.network.session.cache.*; import org.geysermc.connector.network.session.cache.*;
@ -113,13 +112,21 @@ public class GeyserSession implements CommandSender {
private final GeyserConnector connector; private final GeyserConnector connector;
private final UpstreamSession upstream; private final UpstreamSession upstream;
private RemoteServer remoteServer;
private Client downstream; private Client downstream;
@Setter @Setter
private AuthData authData; private AuthData authData;
@Setter @Setter
private BedrockClientData clientData; private BedrockClientData clientData;
/* Setter for GeyserConnect */
@Setter
private String remoteAddress;
@Setter
private int remotePort;
@Setter
private AuthType remoteAuthType;
/* Setter for GeyserConnect */
@Deprecated @Deprecated
@Setter @Setter
private boolean microsoftAccount; private boolean microsoftAccount;
@ -438,9 +445,14 @@ public class GeyserSession implements CommandSender {
}); });
} }
public void connect(RemoteServer remoteServer) { /**
* Send all necessary packets to load Bedrock into the server
*/
public void connect() {
startGame(); startGame();
this.remoteServer = remoteServer; this.remoteAddress = connector.getConfig().getRemote().getAddress();
this.remotePort = connector.getConfig().getRemote().getPort();
this.remoteAuthType = connector.getDefaultAuthType();
// Set the hardcoded shield ID to the ID we just defined in StartGamePacket // Set the hardcoded shield ID to the ID we just defined in StartGamePacket
upstream.getSession().getHardcodedBlockingId().set(ItemRegistry.SHIELD.getBedrockId()); upstream.getSession().getHardcodedBlockingId().set(ItemRegistry.SHIELD.getBedrockId());
@ -485,8 +497,8 @@ public class GeyserSession implements CommandSender {
} }
public void login() { public void login() {
if (connector.getAuthType() != AuthType.ONLINE) { if (this.remoteAuthType != AuthType.ONLINE) {
if (connector.getAuthType() == AuthType.OFFLINE) { if (this.remoteAuthType == AuthType.OFFLINE) {
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.offline")); connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.offline"));
} else { } else {
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.floodgate")); connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.floodgate"));
@ -595,7 +607,7 @@ public class GeyserSession implements CommandSender {
* After getting whatever credentials needed, we attempt to join the Java server. * After getting whatever credentials needed, we attempt to join the Java server.
*/ */
private void connectDownstream() { private void connectDownstream() {
boolean floodgate = connector.getAuthType() == AuthType.FLOODGATE; boolean floodgate = this.remoteAuthType == AuthType.FLOODGATE;
final PublicKey publicKey; final PublicKey publicKey;
if (floodgate) { if (floodgate) {
@ -618,7 +630,8 @@ public class GeyserSession implements CommandSender {
// Start ticking // Start ticking
tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory()); downstream = new Client(this.remoteAddress, this.remotePort, protocol, new TcpSessionFactory());
disableSrvResolving();
if (connector.getConfig().getRemote().isUseProxyProtocol()) { if (connector.getConfig().getRemote().isUseProxyProtocol()) {
downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
@ -666,7 +679,7 @@ public class GeyserSession implements CommandSender {
disconnect(LanguageUtils.getPlayerLocaleString("geyser.network.remote.invalid_account", clientData.getLanguageCode())); disconnect(LanguageUtils.getPlayerLocaleString("geyser.network.remote.invalid_account", clientData.getLanguageCode()));
return; return;
} }
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.connect", authData.getName(), protocol.getProfile().getName(), remoteServer.getAddress())); connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.connect", authData.getName(), protocol.getProfile().getName(), remoteAddress));
playerEntity.setUuid(protocol.getProfile().getId()); playerEntity.setUuid(protocol.getProfile().getId());
playerEntity.setUsername(protocol.getProfile().getName()); playerEntity.setUsername(protocol.getProfile().getName());
@ -687,7 +700,7 @@ public class GeyserSession implements CommandSender {
public void disconnected(DisconnectedEvent event) { public void disconnected(DisconnectedEvent event) {
loggingIn = false; loggingIn = false;
loggedIn = false; loggedIn = false;
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect", authData.getName(), remoteServer.getAddress(), event.getReason())); connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect", authData.getName(), remoteAddress, event.getReason()));
if (event.getCause() != null) { if (event.getCause() != null) {
event.getCause().printStackTrace(); event.getCause().printStackTrace();
} }
@ -705,7 +718,7 @@ public class GeyserSession implements CommandSender {
playerEntity.setUuid(profile.getId()); playerEntity.setUuid(profile.getId());
// Check if they are not using a linked account // Check if they are not using a linked account
if (connector.getAuthType() == AuthType.OFFLINE || playerEntity.getUuid().getMostSignificantBits() == 0) { if (remoteAuthType == AuthType.OFFLINE || playerEntity.getUuid().getMostSignificantBits() == 0) {
SkinManager.handleBedrockSkin(playerEntity, clientData); SkinManager.handleBedrockSkin(playerEntity, clientData);
} }
} }
@ -793,6 +806,13 @@ public class GeyserSession implements CommandSender {
collisionManager.updateScaffoldingFlags(); collisionManager.updateScaffoldingFlags();
} }
/**
* Will be overwritten for GeyserConnect.
*/
protected void disableSrvResolving() {
this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false);
}
@Override @Override
public String getName() { public String getName() {
return authData.getName(); return authData.getName();

View file

@ -286,7 +286,7 @@ public class SkinManager {
String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl(); String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl();
String capeUrl = SkinProvider.EMPTY_CAPE.getTextureUrl(); String capeUrl = SkinProvider.EMPTY_CAPE.getTextureUrl();
if (("steve".equals(skinUrl) || "alex".equals(skinUrl)) && GeyserConnector.getInstance().getAuthType() != AuthType.ONLINE) { if (("steve".equals(skinUrl) || "alex".equals(skinUrl)) && GeyserConnector.getInstance().getDefaultAuthType() != AuthType.ONLINE) {
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(profile.getId()); GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(profile.getId());
if (session != null) { if (session != null) {