ConnectionEstablishedEvent

This commit is contained in:
LOOHP 2023-01-10 15:27:15 +00:00
parent 9f2c426a50
commit ba0f98b6c7
3 changed files with 215 additions and 175 deletions

View File

@ -0,0 +1,37 @@
/*
* This file is part of Limbo.
*
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
* Copyright (C) 2023. Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.loohp.limbo.events.connection;
import com.loohp.limbo.events.Event;
import com.loohp.limbo.network.ClientConnection;
public class ConnectionEstablishedEvent extends Event {
private ClientConnection connection;
public ConnectionEstablishedEvent(ClientConnection connection) {
this.connection = connection;
}
public ClientConnection getConnection() {
return connection;
}
}

View File

@ -22,15 +22,15 @@ package com.loohp.limbo.events.player;
import com.loohp.limbo.events.Cancellable; import com.loohp.limbo.events.Cancellable;
import com.loohp.limbo.events.Event; import com.loohp.limbo.events.Event;
import com.loohp.limbo.network.ClientConnection; import com.loohp.limbo.network.ClientConnection;
import net.md_5.bungee.api.chat.BaseComponent; import net.kyori.adventure.text.Component;
public class PlayerLoginEvent extends Event implements Cancellable { public class PlayerLoginEvent extends Event implements Cancellable {
private ClientConnection connection; private final ClientConnection connection;
private boolean cancelled; private boolean cancelled;
private BaseComponent[] cancelReason; private Component cancelReason;
public PlayerLoginEvent(ClientConnection connection, boolean cancelled, BaseComponent... cancelReason) { public PlayerLoginEvent(ClientConnection connection, boolean cancelled, Component cancelReason) {
this.connection = connection; this.connection = connection;
this.cancelled = cancelled; this.cancelled = cancelled;
this.cancelReason = cancelReason; this.cancelReason = cancelReason;
@ -40,11 +40,11 @@ public class PlayerLoginEvent extends Event implements Cancellable {
return connection; return connection;
} }
public BaseComponent[] getCancelReason() { public Component getCancelReason() {
return cancelReason; return cancelReason;
} }
public void setCancelReason(BaseComponent... cancelReason) { public void setCancelReason(Component cancelReason) {
this.cancelReason = cancelReason; this.cancelReason = cancelReason;
} }

View File

@ -21,6 +21,7 @@ package com.loohp.limbo.network;
import com.loohp.limbo.Limbo; import com.loohp.limbo.Limbo;
import com.loohp.limbo.entity.EntityEquipment; import com.loohp.limbo.entity.EntityEquipment;
import com.loohp.limbo.events.connection.ConnectionEstablishedEvent;
import com.loohp.limbo.events.inventory.AnvilRenameInputEvent; import com.loohp.limbo.events.inventory.AnvilRenameInputEvent;
import com.loohp.limbo.events.inventory.InventoryCloseEvent; import com.loohp.limbo.events.inventory.InventoryCloseEvent;
import com.loohp.limbo.events.inventory.InventoryCreativeEvent; import com.loohp.limbo.events.inventory.InventoryCreativeEvent;
@ -352,6 +353,8 @@ public class ClientConnection extends Thread {
state = ClientState.DISCONNECTED; state = ClientState.DISCONNECTED;
} }
Limbo.getInstance().getEventsManager().callEvent(new ConnectionEstablishedEvent(this));
PacketHandshakingIn handshake = (PacketHandshakingIn) channel.readPacket(handShakeSize); PacketHandshakingIn handshake = (PacketHandshakingIn) channel.readPacket(handShakeSize);
boolean isBungeecord = Limbo.getInstance().getServerProperties().isBungeecord(); boolean isBungeecord = Limbo.getInstance().getServerProperties().isBungeecord();
@ -363,195 +366,195 @@ public class ClientConnection extends Thread {
try { try {
switch (handshake.getHandshakeType()) { switch (handshake.getHandshakeType()) {
case STATUS: case STATUS:
state = ClientState.STATUS; state = ClientState.STATUS;
while (clientSocket.isConnected()) { while (clientSocket.isConnected()) {
PacketIn packetIn = channel.readPacket(); PacketIn packetIn = channel.readPacket();
if (packetIn instanceof PacketStatusInRequest) { if (packetIn instanceof PacketStatusInRequest) {
ServerProperties properties = Limbo.getInstance().getServerProperties(); ServerProperties properties = Limbo.getInstance().getServerProperties();
String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "<ip address withheld>") + ":" + clientSocket.getPort(); String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "<ip address withheld>") + ":" + clientSocket.getPort();
if (Limbo.getInstance().getServerProperties().handshakeVerboseEnabled()) { if (Limbo.getInstance().getServerProperties().handshakeVerboseEnabled()) {
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Handshake Status has pinged"); Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Handshake Status has pinged");
}
ServerProperties p = Limbo.getInstance().getServerProperties();
StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), p.getMotd(), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)));
PacketStatusOutResponse response = new PacketStatusOutResponse(Limbo.getInstance().buildServerListResponseJson(event.getVersion(), event.getProtocol(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline(), event.getFavicon()));
sendPacket(response);
} else if (packetIn instanceof PacketStatusInPing) {
PacketStatusInPing ping = (PacketStatusInPing) packetIn;
PacketStatusOutPong pong = new PacketStatusOutPong(ping.getPayload());
sendPacket(pong);
break;
} }
ServerProperties p = Limbo.getInstance().getServerProperties();
StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), p.getMotd(), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)));
PacketStatusOutResponse response = new PacketStatusOutResponse(Limbo.getInstance().buildServerListResponseJson(event.getVersion(), event.getProtocol(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline(), event.getFavicon()));
sendPacket(response);
} else if (packetIn instanceof PacketStatusInPing) {
PacketStatusInPing ping = (PacketStatusInPing) packetIn;
PacketStatusOutPong pong = new PacketStatusOutPong(ping.getPayload());
sendPacket(pong);
break;
} }
break; }
case LOGIN: break;
state = ClientState.LOGIN; case LOGIN:
ServerProperties properties = Limbo.getInstance().getServerProperties(); state = ClientState.LOGIN;
ServerProperties properties = Limbo.getInstance().getServerProperties();
if (isBungeecord || isBungeeGuard) {
try {
String[] data = bungeeForwarding.split("\\x00");
String host = "";
String floodgate = "";
String clientIp = "";
String bungee = "";
String skinData = "";
int state = 0;
for (int i = 0; i < data.length; i++) {
if (!properties.isReducedDebugInfo()) {
Limbo.getInstance().getConsole().sendMessage(String.valueOf(i) + ": " + data[i]);
}
switch (state) {
default:
Limbo.getInstance().getConsole().sendMessage(String.valueOf(i) + ": ignore data: State: " + String.valueOf(state));
break;
case 0:
host = data[i];
state = 1;
break;
case 1:
if (data[i].startsWith("^Floodgate^")) {
floodgate = data[i];
state = 2;
break;
}
/* fallthrough */
case 2:
clientIp = data[i];
state = 3;
break;
case 3:
bungee = data[i];
state = 4;
break;
case 4:
skinData = data[i];
state = 6;
break;
}
}
if (state != 6) {
throw new IllegalStateException("Illegal bungee state: " + String.valueOf(state));
}
if (isBungeecord || isBungeeGuard) {
try {
String[] data = bungeeForwarding.split("\\x00");
String host = "";
String floodgate = "";
String clientIp = "";
String bungee = "";
String skinData = "";
int state = 0;
for (int i = 0; i < data.length; i++) {
if (!properties.isReducedDebugInfo()) { if (!properties.isReducedDebugInfo()) {
Limbo.getInstance().getConsole().sendMessage("Host: " + host); Limbo.getInstance().getConsole().sendMessage(String.valueOf(i) + ": " + data[i]);
Limbo.getInstance().getConsole().sendMessage("Floodgate: " + floodgate);
Limbo.getInstance().getConsole().sendMessage("clientIp: " + clientIp);
Limbo.getInstance().getConsole().sendMessage("bungee: " + bungee);
Limbo.getInstance().getConsole().sendMessage("skinData: " + skinData);
} }
bungeeUUID = UUID.fromString(bungee.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5")); switch (state) {
inetAddress = InetAddress.getByName(clientIp); default:
Limbo.getInstance().getConsole().sendMessage(String.valueOf(i) + ": ignore data: State: " + String.valueOf(state));
break;
case 0:
host = data[i];
state = 1;
break;
case 1:
if (data[i].startsWith("^Floodgate^")) {
floodgate = data[i];
state = 2;
break;
}
/* fallthrough */
case 2:
clientIp = data[i];
state = 3;
break;
case 3:
bungee = data[i];
state = 4;
break;
case 4:
skinData = data[i];
state = 6;
break;
}
}
if (state != 6) {
throw new IllegalStateException("Illegal bungee state: " + String.valueOf(state));
}
boolean bungeeGuardFound = false; if (!properties.isReducedDebugInfo()) {
Limbo.getInstance().getConsole().sendMessage("Host: " + host);
Limbo.getInstance().getConsole().sendMessage("Floodgate: " + floodgate);
Limbo.getInstance().getConsole().sendMessage("clientIp: " + clientIp);
Limbo.getInstance().getConsole().sendMessage("bungee: " + bungee);
Limbo.getInstance().getConsole().sendMessage("skinData: " + skinData);
}
if (!skinData.equals("")) { bungeeUUID = UUID.fromString(bungee.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5"));
JSONArray skinJson = (JSONArray) new JSONParser().parse(skinData); inetAddress = InetAddress.getByName(clientIp);
for (Object obj : skinJson) { boolean bungeeGuardFound = false;
JSONObject property = (JSONObject) obj;
if (property.get("name").toString().equals("textures")) { if (!skinData.equals("")) {
String skin = property.get("value").toString(); JSONArray skinJson = (JSONArray) new JSONParser().parse(skinData);
String signature = property.get("signature").toString();
forwardedSkin = new SkinResponse(skin, signature); for (Object obj : skinJson) {
} else if (isBungeeGuard && property.get("name").toString().equals("bungeeguard-token")) { JSONObject property = (JSONObject) obj;
String token = property.get("value").toString(); if (property.get("name").toString().equals("textures")) {
bungeeGuardFound = Limbo.getInstance().getServerProperties().getForwardingSecrets().contains(token); String skin = property.get("value").toString();
} String signature = property.get("signature").toString();
forwardedSkin = new SkinResponse(skin, signature);
} else if (isBungeeGuard && property.get("name").toString().equals("bungeeguard-token")) {
String token = property.get("value").toString();
bungeeGuardFound = Limbo.getInstance().getServerProperties().getForwardingSecrets().contains(token);
} }
} }
if (isBungeeGuard && !bungeeGuardFound) {
disconnectDuringLogin(TextComponent.fromLegacyText("Invalid information forwarding"));
break;
}
} catch (Exception e) {
if (!properties.isReducedDebugInfo()) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Limbo.getInstance().getConsole().sendMessage(sw.toString());
}
Limbo.getInstance().getConsole().sendMessage("If you wish to use bungeecord's IP forwarding, please enable that in your bungeecord config.yml as well!");
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
} }
}
int messageId = this.random.nextInt();
while (clientSocket.isConnected()) {
PacketIn packetIn = channel.readPacket();
if (packetIn instanceof PacketLoginInLoginStart) {
PacketLoginInLoginStart start = (PacketLoginInLoginStart) packetIn;
String username = start.getUsername();
if (Limbo.getInstance().getServerProperties().isVelocityModern()) {
PacketLoginOutPluginMessaging loginPluginRequest = new PacketLoginOutPluginMessaging(messageId, ForwardingUtils.VELOCITY_FORWARDING_CHANNEL);
sendPacket(loginPluginRequest);
continue;
}
UUID uuid = isBungeecord || isBungeeGuard ? bungeeUUID : (start.hasUniqueId() ? start.getUniqueId() : null);
if (uuid == null) {
uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
}
if (!properties.enforceWhitelist() && properties.uuidWhitelisted(uuid)) {
disconnectDuringLogin(TextComponent.fromLegacyText("You are not whitelisted on the server"));
break;
}
PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(uuid, username);
sendPacket(success);
state = ClientState.PLAY;
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
Limbo.getInstance().getUnsafe().a(player);
break;
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
if (response.getMessageId() != messageId) {
disconnectDuringLogin(TextComponent.fromLegacyText("Internal error, messageId did not match"));
break;
}
if (!response.getData().isPresent()) {
disconnectDuringLogin(TextComponent.fromLegacyText("Unknown login plugin response packet!"));
break;
}
byte[] responseData = response.getData().get();
if (!ForwardingUtils.validateVelocityModernResponse(responseData)) {
disconnectDuringLogin(TextComponent.fromLegacyText("Invalid playerinfo forwarding!"));
break;
}
ForwardingUtils.VelocityModernForwardingData data = ForwardingUtils.getVelocityDataFrom(responseData);
inetAddress = InetAddress.getByName(data.getIpAddress());
forwardedSkin = data.getSkinResponse();
PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(data.getUuid(), data.getUsername());
sendPacket(success);
state = ClientState.PLAY;
player = new Player(this, data.getUsername(), data.getUuid(), Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
Limbo.getInstance().getUnsafe().a(player);
if (isBungeeGuard && !bungeeGuardFound) {
disconnectDuringLogin(TextComponent.fromLegacyText("Invalid information forwarding"));
break; break;
} }
} catch (Exception e) {
if (!properties.isReducedDebugInfo()) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Limbo.getInstance().getConsole().sendMessage(sw.toString());
}
Limbo.getInstance().getConsole().sendMessage("If you wish to use bungeecord's IP forwarding, please enable that in your bungeecord config.yml as well!");
disconnectDuringLogin(new BaseComponent[] {new TextComponent(ChatColor.RED + "Please connect from the proxy!")});
} }
}
int messageId = this.random.nextInt();
while (clientSocket.isConnected()) {
PacketIn packetIn = channel.readPacket();
PlayerLoginEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerLoginEvent(this, false)); if (packetIn instanceof PacketLoginInLoginStart) {
if (event.isCancelled()) { PacketLoginInLoginStart start = (PacketLoginInLoginStart) packetIn;
disconnectDuringLogin(event.getCancelReason()); String username = start.getUsername();
if (Limbo.getInstance().getServerProperties().isVelocityModern()) {
PacketLoginOutPluginMessaging loginPluginRequest = new PacketLoginOutPluginMessaging(messageId, ForwardingUtils.VELOCITY_FORWARDING_CHANNEL);
sendPacket(loginPluginRequest);
continue;
}
UUID uuid = isBungeecord || isBungeeGuard ? bungeeUUID : (start.hasUniqueId() ? start.getUniqueId() : null);
if (uuid == null) {
uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
}
if (!properties.enforceWhitelist() && properties.uuidWhitelisted(uuid)) {
disconnectDuringLogin(TextComponent.fromLegacyText("You are not whitelisted on the server"));
break;
}
PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(uuid, username);
sendPacket(success);
state = ClientState.PLAY;
player = new Player(this, username, uuid, Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
Limbo.getInstance().getUnsafe().a(player);
break;
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
if (response.getMessageId() != messageId) {
disconnectDuringLogin(TextComponent.fromLegacyText("Internal error, messageId did not match"));
break;
}
if (!response.getData().isPresent()) {
disconnectDuringLogin(TextComponent.fromLegacyText("Unknown login plugin response packet!"));
break;
}
byte[] responseData = response.getData().get();
if (!ForwardingUtils.validateVelocityModernResponse(responseData)) {
disconnectDuringLogin(TextComponent.fromLegacyText("Invalid playerinfo forwarding!"));
break;
}
ForwardingUtils.VelocityModernForwardingData data = ForwardingUtils.getVelocityDataFrom(responseData);
inetAddress = InetAddress.getByName(data.getIpAddress());
forwardedSkin = data.getSkinResponse();
PacketLoginOutLoginSuccess success = new PacketLoginOutLoginSuccess(data.getUuid(), data.getUsername());
sendPacket(success);
state = ClientState.PLAY;
player = new Player(this, data.getUsername(), data.getUuid(), Limbo.getInstance().getNextEntityId(), Limbo.getInstance().getServerProperties().getWorldSpawn(), new PlayerInteractManager());
player.setSkinLayers((byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
Limbo.getInstance().getUnsafe().a(player);
break;
} }
}
break; PlayerLoginEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerLoginEvent(this, false, Component.empty()));
if (event.isCancelled()) {
disconnectDuringLogin(event.getCancelReason());
}
break;
} }
} catch (Exception e) { } catch (Exception e) {
channel.close(); channel.close();