use of org.lanternpowered.server.network.NetworkSession in project LanternServer by LanternPowered.
the class HandlerHandshakeIn method handle.
@Override
public void handle(NetworkContext context, MessageHandshakeIn message) {
final Optional<ProtocolState> optNextState = ProtocolState.getFromId(message.getNextState());
final NetworkSession session = context.getSession();
if (!optNextState.isPresent()) {
session.disconnect(t("Unknown protocol state! (%s)", message.getNextState()));
return;
}
final ProtocolState nextState = optNextState.get();
session.setProtocolState(nextState);
if (!nextState.equals(ProtocolState.LOGIN) && !nextState.equals(ProtocolState.STATUS)) {
session.disconnect(t("Received a unexpected handshake message! (%s)", nextState));
return;
}
final ProxyType proxyType = Lantern.getGame().getGlobalConfig().getProxyType();
String hostname = message.getHostname();
InetSocketAddress virtualAddress;
switch(proxyType) {
case WATERFALL:
case BUNGEE_CORD:
String[] split = hostname.split("\0\\|", 2);
// Check for a fml marker
session.getChannel().attr(NetworkSession.FML_MARKER).set(split.length == 2 == split[1].contains(FML_MARKER));
split = split[0].split("\00");
if (split.length == 3 || split.length == 4) {
virtualAddress = new InetSocketAddress(split[1], message.getPort());
final UUID uniqueId = UUIDHelper.fromFlatString(split[2]);
final Multimap<String, ProfileProperty> properties;
if (split.length == 4) {
try {
properties = LanternProfileProperty.createPropertiesMapFromJson(GSON.fromJson(split[3], JsonArray.class));
} catch (Exception e) {
session.disconnect(t("Invalid %s proxy data format.", proxyType.getName()));
throw new CodecException(e);
}
} else {
properties = LinkedHashMultimap.create();
}
session.getChannel().attr(HandlerLoginStart.SPOOFED_GAME_PROFILE).set(new LanternGameProfile(uniqueId, null, properties));
} else {
session.disconnect(t("Please enable client detail forwarding (also known as \"ip forwarding\") on " + "your proxy if you wish to use it on this server, and also make sure that you joined through the proxy."));
return;
}
break;
case LILY_PAD:
try {
final JsonObject jsonObject = GSON.fromJson(hostname, JsonObject.class);
final String securityKey = Lantern.getGame().getGlobalConfig().getProxySecurityKey();
// Validate the security key
if (!securityKey.isEmpty() && !jsonObject.get("s").getAsString().equals(securityKey)) {
session.disconnect(t("Proxy security key mismatch"));
Lantern.getLogger().warn("Proxy security key mismatch for the player {}", jsonObject.get("n").getAsString());
return;
}
final String name = jsonObject.get("n").getAsString();
final UUID uniqueId = UUIDHelper.fromFlatString(jsonObject.get("u").getAsString());
final Multimap<String, ProfileProperty> properties = LinkedHashMultimap.create();
if (jsonObject.has("p")) {
final JsonArray jsonArray = jsonObject.getAsJsonArray("p");
for (int i = 0; i < jsonArray.size(); i++) {
final JsonObject property = jsonArray.get(i).getAsJsonObject();
final String propertyName = property.get("n").getAsString();
final String propertyValue = property.get("v").getAsString();
final String propertySignature = property.has("s") ? property.get("s").getAsString() : null;
properties.put(propertyName, new LanternProfileProperty(propertyName, propertyValue, propertySignature));
}
}
session.getChannel().attr(HandlerLoginStart.SPOOFED_GAME_PROFILE).set(new LanternGameProfile(uniqueId, name, properties));
session.getChannel().attr(NetworkSession.FML_MARKER).set(false);
final int port = jsonObject.get("rP").getAsInt();
final String host = jsonObject.get("h").getAsString();
virtualAddress = new InetSocketAddress(host, port);
} catch (Exception e) {
session.disconnect(t("Invalid %s proxy data format.", proxyType.getName()));
throw new CodecException(e);
}
break;
case NONE:
int index = hostname.indexOf(FML_MARKER);
session.getChannel().attr(NetworkSession.FML_MARKER).set(index != -1);
if (index != -1) {
hostname = hostname.substring(0, index);
}
virtualAddress = new InetSocketAddress(hostname, message.getPort());
break;
default:
throw new IllegalStateException("The proxy type " + proxyType + " isn't implemented");
}
session.setVirtualHost(virtualAddress);
session.setProtocolVersion(message.getProtocolVersion());
if (nextState == ProtocolState.LOGIN) {
final int protocol = Lantern.getGame().getPlatform().getMinecraftVersion().getProtocol();
if (message.getProtocolVersion() < protocol) {
session.disconnect(t("multiplayer.disconnect.outdated_client", Lantern.getGame().getPlatform().getMinecraftVersion().getName()));
} else if (message.getProtocolVersion() > protocol) {
session.disconnect(t("multiplayer.disconnect.outdated_server", Lantern.getGame().getPlatform().getMinecraftVersion().getName()));
}
}
}
use of org.lanternpowered.server.network.NetworkSession in project LanternServer by LanternPowered.
the class HandlerPlayInChatMessage method handle.
@Override
public void handle(NetworkContext context, MessagePlayInChatMessage message) {
final NetworkSession session = context.getSession();
final LanternPlayer player = session.getPlayer();
player.resetIdleTimeoutCounter();
final String message0 = message.getMessage();
// Check for a valid click action callback
final Matcher matcher = LanternClickActionCallbacks.COMMAND_PATTERN.matcher(message0);
if (matcher.matches()) {
final UUID uniqueId = UUID.fromString(matcher.group(1));
final Optional<Consumer<CommandSource>> callback = LanternClickActionCallbacks.get().getCallbackForUUID(uniqueId);
if (callback.isPresent()) {
callback.get().accept(player);
} else {
player.sendMessage(error(t("The callback you provided was not valid. Keep in mind that callbacks will expire " + "after 10 minutes, so you might want to consider clicking faster next time!")));
}
return;
}
String message1 = StringUtils.normalizeSpace(message0);
if (!isAllowedString(message0)) {
session.disconnect(t("multiplayer.disconnect.illegal_characters"));
return;
}
if (message1.startsWith("/")) {
Lantern.getSyncExecutorService().submit(() -> Sponge.getCommandManager().process(player, message1.substring(1)));
} else {
final Text nameText = player.get(Keys.DISPLAY_NAME).get();
final Text rawMessageText = Text.of(message0);
final GlobalConfig.Chat.Urls urls = Lantern.getGame().getGlobalConfig().getChat().getUrls();
final Text messageText;
if (urls.isEnabled() && player.hasPermission(Permissions.Chat.FORMAT_URLS)) {
messageText = newTextWithLinks(message0, urls.getTemplate(), false);
} else {
messageText = rawMessageText;
}
final MessageChannel channel = player.getMessageChannel();
final CauseStack causeStack = CauseStack.current();
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
frame.addContext(EventContextKeys.PLAYER, player);
final MessageChannelEvent.Chat event = SpongeEventFactory.createMessageChannelEventChat(causeStack.getCurrentCause(), channel, Optional.of(channel), new MessageEvent.MessageFormatter(nameText, messageText), rawMessageText, false);
if (!Sponge.getEventManager().post(event) && !event.isMessageCancelled()) {
event.getChannel().ifPresent(c -> c.send(player, event.getMessage(), ChatTypes.CHAT));
}
}
}
final Attribute<ChatData> attr = context.getChannel().attr(CHAT_DATA);
ChatData chatData = attr.get();
if (chatData == null) {
chatData = new ChatData();
final ChatData chatData1 = attr.setIfAbsent(chatData);
if (chatData1 != null) {
chatData = chatData1;
}
}
// noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (chatData) {
final long currentTime = LanternGame.currentTimeTicks();
if (chatData.lastChatTime != -1L) {
chatData.chatThrottle = (int) Math.max(0, chatData.chatThrottle - (currentTime - chatData.lastChatTime));
}
chatData.lastChatTime = currentTime;
chatData.chatThrottle += 20;
if (chatData.chatThrottle > Lantern.getGame().getGlobalConfig().getChatSpamThreshold()) {
session.disconnect(t("disconnect.spam"));
}
}
}
use of org.lanternpowered.server.network.NetworkSession in project LanternServer by LanternPowered.
the class HandlerForgeHandshakeInAck method handle.
@Override
public void handle(NetworkContext context, MessageForgeHandshakeInOutAck message) {
final NetworkSession session = context.getSession();
final Attribute<ForgeServerHandshakePhase> phase = context.getChannel().attr(ForgeHandshakePhase.PHASE);
switch(phase.get()) {
case WAITING_ACK:
if (!message.getPhase().equals(ForgeClientHandshakePhase.WAITING_SERVER_DATA)) {
session.disconnect(t("Retrieved unexpected forge handshake ack message. (Got %s, expected %s)", message.getPhase(), ForgeClientHandshakePhase.WAITING_SERVER_DATA));
} else {
final List<MessageForgeHandshakeOutRegistryData.Entry> entries = new ArrayList<>();
entries.add(new MessageForgeHandshakeOutRegistryData.Entry("minecraft:items", new HashMap<>(), new ArrayList<>()));
entries.add(new MessageForgeHandshakeOutRegistryData.Entry("minecraft:blocks", new HashMap<>(), new ArrayList<>()));
session.send(new MessageForgeHandshakeOutRegistryData(entries));
session.send(new MessageForgeHandshakeInOutAck(ForgeServerHandshakePhase.WAITING_ACK));
phase.set(ForgeServerHandshakePhase.COMPLETE);
}
Lantern.getLogger().info("{}: Forge handshake -> Received ack (waitingServerData) message.", session.getGameProfile().getName().get());
break;
case COMPLETE:
if (!message.getPhase().equals(ForgeClientHandshakePhase.WAITING_SERVER_COMPLETE)) {
session.disconnect(t("Retrieved unexpected forge handshake ack message. (Got %s, expected %s)", message.getPhase(), ForgeClientHandshakePhase.WAITING_SERVER_COMPLETE));
} else {
session.send(new MessageForgeHandshakeInOutAck(ForgeServerHandshakePhase.COMPLETE));
phase.set(ForgeServerHandshakePhase.DONE);
}
Lantern.getLogger().info("{}: Forge handshake -> Received ack (waitingServerComplete) message.", session.getGameProfile().getName().get());
break;
case DONE:
if (!message.getPhase().equals(ForgeClientHandshakePhase.PENDING_COMPLETE) && !message.getPhase().equals(ForgeClientHandshakePhase.COMPLETE)) {
session.disconnect(t("Retrieved unexpected forge handshake ack message. (Got %s, expected %s or %s)", message.getPhase(), ForgeClientHandshakePhase.PENDING_COMPLETE, ForgeClientHandshakePhase.COMPLETE));
} else {
if (message.getPhase().equals(ForgeClientHandshakePhase.PENDING_COMPLETE)) {
session.send(new MessageForgeHandshakeInOutAck(ForgeServerHandshakePhase.DONE));
Lantern.getLogger().info("{}: Forge handshake -> Received ack (pendingComplete) message.", session.getGameProfile().getName().get());
} else {
session.setProtocolState(ProtocolState.PLAY);
session.initPlayer();
Lantern.getLogger().info("{}: Forge handshake -> Received ack (complete) message.", session.getGameProfile().getName().get());
}
}
break;
case ERROR:
break;
default:
session.disconnect(t("Retrieved unexpected forge handshake ack message. (Got %s)", message.getPhase()));
}
}
use of org.lanternpowered.server.network.NetworkSession in project LanternServer by LanternPowered.
the class HandlerForgeHandshakeInHello method handle.
@Override
public void handle(NetworkContext context, MessageForgeHandshakeInOutHello message) {
final NetworkSession session = context.getSession();
final Attribute<ForgeServerHandshakePhase> phase = session.getChannel().attr(ForgeHandshakePhase.PHASE);
if (phase.get() != ForgeServerHandshakePhase.HELLO) {
session.disconnect(t("Retrieved unexpected forge handshake hello message."));
return;
}
Lantern.getLogger().info("{}: Forge handshake -> Received hello message.", session.getGameProfile().getName().get());
}
use of org.lanternpowered.server.network.NetworkSession in project LanternServer by LanternPowered.
the class HandlerForgeHandshakeInStart method handle.
@Override
public void handle(NetworkContext context, MessageForgeHandshakeInStart message) {
final Attribute<ForgeServerHandshakePhase> phase = context.getChannel().attr(ForgeHandshakePhase.PHASE);
final NetworkSession session = context.getSession();
if (phase.get() != null && phase.get() != ForgeServerHandshakePhase.START) {
session.disconnect(t("Retrieved unexpected forge handshake start message."));
return;
}
final boolean fml = session.getChannel().attr(NetworkSession.FML_MARKER).get();
final Set<String> channels = new HashSet<>(Sponge.getChannelRegistrar().getRegisteredChannels(Platform.Type.SERVER));
if (fml) {
channels.add("FML");
channels.add("FML|HS");
channels.add("FML|MP");
}
if (!channels.isEmpty()) {
session.send(new MessagePlayInOutRegisterChannels(channels));
}
// future if sponge uses completely it's own protocol.
if (false && fml) {
phase.set(ForgeServerHandshakePhase.HELLO);
session.send(new MessageForgeHandshakeInOutHello());
Lantern.getLogger().info("{}: Start forge handshake.", session.getGameProfile().getName().get());
} else {
Lantern.getLogger().info("{}: Skip forge handshake.", session.getGameProfile().getName().get());
phase.set(ForgeServerHandshakePhase.DONE);
session.setProtocolState(ProtocolState.PLAY);
session.initPlayer();
}
}
Aggregations