Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-27 16:40:14 +01:00
Support HAProxy in legacy ping passthrough
Dieser Commit ist enthalten in:
Ursprung
4656383c67
Commit
16bb79e7aa
@ -28,6 +28,9 @@ package org.geysermc.geyser.ping;
|
|||||||
import com.fasterxml.jackson.core.JsonParseException;
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
import com.nukkitx.nbt.util.VarInts;
|
import com.nukkitx.nbt.util.VarInts;
|
||||||
|
import io.netty.handler.codec.haproxy.HAProxyCommand;
|
||||||
|
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
|
||||||
|
import io.netty.util.NetUtil;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||||
|
|
||||||
@ -35,13 +38,12 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ConnectException;
|
import java.net.*;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable {
|
public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable {
|
||||||
|
private static final byte[] HAPROXY_BINARY_PREFIX = new byte[]{13, 10, 13, 10, 0, 13, 10, 81, 85, 73, 84, 10};
|
||||||
|
|
||||||
private final GeyserImpl geyser;
|
private final GeyserImpl geyser;
|
||||||
|
|
||||||
public GeyserLegacyPingPassthrough(GeyserImpl geyser) {
|
public GeyserLegacyPingPassthrough(GeyserImpl geyser) {
|
||||||
@ -74,54 +76,68 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try (Socket socket = new Socket()) {
|
||||||
Socket socket = new Socket();
|
|
||||||
String address = geyser.getConfig().getRemote().getAddress();
|
String address = geyser.getConfig().getRemote().getAddress();
|
||||||
int port = geyser.getConfig().getRemote().getPort();
|
int port = geyser.getConfig().getRemote().getPort();
|
||||||
socket.connect(new InetSocketAddress(address, port), 5000);
|
socket.connect(new InetSocketAddress(address, port), 5000);
|
||||||
|
|
||||||
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
|
||||||
DataOutputStream handshake = new DataOutputStream(byteArrayStream);
|
try (DataOutputStream handshake = new DataOutputStream(byteArrayStream)) {
|
||||||
handshake.write(0x0);
|
handshake.write(0x0);
|
||||||
VarInts.writeUnsignedInt(handshake, MinecraftProtocol.getJavaProtocolVersion());
|
VarInts.writeUnsignedInt(handshake, MinecraftProtocol.getJavaProtocolVersion());
|
||||||
VarInts.writeUnsignedInt(handshake, address.length());
|
VarInts.writeUnsignedInt(handshake, address.length());
|
||||||
handshake.writeBytes(address);
|
handshake.writeBytes(address);
|
||||||
handshake.writeShort(port);
|
handshake.writeShort(port);
|
||||||
VarInts.writeUnsignedInt(handshake, 1);
|
VarInts.writeUnsignedInt(handshake, 1);
|
||||||
|
}
|
||||||
|
|
||||||
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
|
byte[] buffer;
|
||||||
VarInts.writeUnsignedInt(dataOutputStream, byteArrayStream.size());
|
|
||||||
dataOutputStream.write(byteArrayStream.toByteArray());
|
|
||||||
dataOutputStream.writeByte(0x01);
|
|
||||||
dataOutputStream.writeByte(0x00);
|
|
||||||
|
|
||||||
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
|
try (DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
|
||||||
VarInts.readUnsignedInt(dataInputStream);
|
if (geyser.getConfig().getRemote().isUseProxyProtocol()) {
|
||||||
VarInts.readUnsignedInt(dataInputStream);
|
// HAProxy support
|
||||||
int length = VarInts.readUnsignedInt(dataInputStream);
|
// Based on https://github.com/netty/netty/blob/d8ad931488f6b942dabe28ecd6c399b4438da0a8/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessageEncoder.java#L78
|
||||||
byte[] buffer = new byte[length];
|
dataOutputStream.write(HAPROXY_BINARY_PREFIX);
|
||||||
dataInputStream.readFully(buffer);
|
dataOutputStream.writeByte((0x02 << 4) | HAProxyCommand.PROXY.byteValue());
|
||||||
dataOutputStream.writeByte(0x09);
|
dataOutputStream.writeByte(socket.getLocalAddress() instanceof Inet4Address ?
|
||||||
dataOutputStream.writeByte(0x01);
|
HAProxyProxiedProtocol.TCP4.byteValue() : HAProxyProxiedProtocol.TCP6.byteValue());
|
||||||
dataOutputStream.writeLong(System.currentTimeMillis());
|
byte[] srcAddrBytes = NetUtil.createByteArrayFromIpAddressString(
|
||||||
|
((InetSocketAddress) socket.getLocalSocketAddress()).getAddress().getHostAddress());
|
||||||
|
byte[] dstAddrBytes = NetUtil.createByteArrayFromIpAddressString(address);
|
||||||
|
dataOutputStream.writeShort(srcAddrBytes.length + dstAddrBytes.length + 4);
|
||||||
|
dataOutputStream.write(srcAddrBytes);
|
||||||
|
dataOutputStream.write(dstAddrBytes);
|
||||||
|
dataOutputStream.writeShort(((InetSocketAddress) socket.getLocalSocketAddress()).getPort());
|
||||||
|
dataOutputStream.writeShort(port);
|
||||||
|
}
|
||||||
|
|
||||||
VarInts.readUnsignedInt(dataInputStream);
|
VarInts.writeUnsignedInt(dataOutputStream, byteArrayStream.size());
|
||||||
String json = new String(buffer);
|
dataOutputStream.write(byteArrayStream.toByteArray());
|
||||||
|
dataOutputStream.writeByte(0x01);
|
||||||
|
dataOutputStream.writeByte(0x00);
|
||||||
|
|
||||||
this.pingInfo = GeyserImpl.JSON_MAPPER.readValue(json, GeyserPingInfo.class);
|
try (DataInputStream dataInputStream = new DataInputStream(socket.getInputStream())) {
|
||||||
|
VarInts.readUnsignedInt(dataInputStream);
|
||||||
|
VarInts.readUnsignedInt(dataInputStream);
|
||||||
|
int length = VarInts.readUnsignedInt(dataInputStream);
|
||||||
|
buffer = new byte[length];
|
||||||
|
dataInputStream.readFully(buffer);
|
||||||
|
dataOutputStream.writeByte(0x09);
|
||||||
|
dataOutputStream.writeByte(0x01);
|
||||||
|
dataOutputStream.writeLong(System.currentTimeMillis());
|
||||||
|
|
||||||
byteArrayStream.close();
|
VarInts.readUnsignedInt(dataInputStream);
|
||||||
handshake.close();
|
}
|
||||||
dataOutputStream.close();
|
}
|
||||||
dataInputStream.close();
|
|
||||||
socket.close();
|
this.pingInfo = GeyserImpl.JSON_MAPPER.readValue(buffer, GeyserPingInfo.class);
|
||||||
} catch (SocketTimeoutException | ConnectException ex) {
|
} catch (SocketTimeoutException | ConnectException ex) {
|
||||||
this.pingInfo = null;
|
this.pingInfo = null;
|
||||||
this.geyser.getLogger().debug("Connection timeout for ping passthrough.");
|
this.geyser.getLogger().debug("Connection timeout for ping passthrough.");
|
||||||
} catch (JsonParseException | JsonMappingException ex) {
|
} catch (JsonParseException | JsonMappingException ex) {
|
||||||
this.geyser.getLogger().error("Failed to parse json when pinging server!", ex);
|
this.geyser.getLogger().error("Failed to parse json when pinging server!", ex);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
this.geyser.getLogger().error("IO error while trying to use legacy ping passthrough", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1649,7 +1649,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||||||
if (org.geysermc.geyser.network.MinecraftProtocol.supports1_19_10(this)) {
|
if (org.geysermc.geyser.network.MinecraftProtocol.supports1_19_10(this)) {
|
||||||
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
|
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
|
||||||
adventureSettingsPacket.setNoMvP(false);
|
adventureSettingsPacket.setNoMvP(false);
|
||||||
adventureSettingsPacket.setNoMvP(false);
|
adventureSettingsPacket.setNoPvM(false);
|
||||||
adventureSettingsPacket.setImmutableWorld(worldImmutable);
|
adventureSettingsPacket.setImmutableWorld(worldImmutable);
|
||||||
adventureSettingsPacket.setShowNameTags(false);
|
adventureSettingsPacket.setShowNameTags(false);
|
||||||
adventureSettingsPacket.setAutoJump(true);
|
adventureSettingsPacket.setAutoJump(true);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren