Skip to content

Commit

Permalink
Add more packet handlers, allowing upstream to connect to remote
Browse files Browse the repository at this point in the history
  • Loading branch information
RednedEpic committed Jul 10, 2019
1 parent f0b8dc7 commit 17b99a8
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.console.ConsoleCommandReader;
import org.geysermc.connector.console.GeyserLogger;
import org.geysermc.connector.network.listener.ConnectorServerEventListener;
import org.geysermc.connector.network.ConnectorServerEventHandler;
import org.geysermc.connector.plugin.GeyserPluginLoader;
import org.geysermc.connector.plugin.GeyserPluginManager;

Expand Down Expand Up @@ -115,7 +115,7 @@ private GeyserConnector() {
pluginManager.getLoader().loadPlugins();

BedrockServer bedrockServer = new BedrockServer(new InetSocketAddress(config.getBedrock().getAddress(), config.getBedrock().getPort()));
bedrockServer.setHandler(new ConnectorServerEventListener(this));
bedrockServer.setHandler(new ConnectorServerEventHandler(this));
bedrockServer.bind().whenComplete((avoid, throwable) -> {
if (throwable == null) {
logger.info("Started RakNet on " + config.getBedrock().getAddress() + ":" + config.getBedrock().getPort());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,22 @@
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network.listener;
package org.geysermc.connector.network;

import com.nukkitx.protocol.bedrock.BedrockPong;
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.network.session.GeyserSession;

import java.net.InetSocketAddress;

public class ConnectorServerEventListener implements BedrockServerEventHandler {
public class ConnectorServerEventHandler implements BedrockServerEventHandler {

private GeyserConnector connector;

public ConnectorServerEventListener(GeyserConnector connector) {
public ConnectorServerEventHandler(GeyserConnector connector) {
this.connector = connector;
}

Expand All @@ -53,6 +54,7 @@ public BedrockPong onQuery(InetSocketAddress inetSocketAddress) {

@Override
public void onSessionCreation(BedrockServerSession bedrockServerSession) {

bedrockServerSession.setLogging(true);
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserSession(connector, bedrockServerSession)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*
* You can view the LICENCE file for details.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network;

import com.nimbusds.jose.JWSObject;
import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler;
import com.nukkitx.protocol.bedrock.packet.LoginPacket;
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
import com.nukkitx.protocol.bedrock.packet.ResourcePackClientResponsePacket;
import com.nukkitx.protocol.bedrock.packet.ResourcePackStackPacket;
import com.nukkitx.protocol.bedrock.packet.ResourcePacksInfoPacket;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.remote.RemoteJavaServer;
import org.geysermc.connector.network.session.GeyserSession;

import java.util.UUID;

public class UpstreamPacketHandler implements BedrockPacketHandler {

private GeyserConnector connector;
private GeyserSession session;

public UpstreamPacketHandler(GeyserConnector connector, GeyserSession session) {
this.connector = connector;
this.session = session;
}

@Override
public boolean handle(LoginPacket loginPacket) {
// TODO: Implement support for multiple protocols
if (loginPacket.getProtocolVersion() != GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) {
session.getUpstream().disconnect("Unsupported Bedrock version. Are you running an outdated version?");
return true;
}

session.getUpstream().setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC);

try {
JSONObject chainData = (JSONObject) JSONValue.parse(loginPacket.getChainData().array());
JSONArray chainArray = (JSONArray) chainData.get("chain");

Object identityObject = chainArray.get(chainArray.size() - 1);

JWSObject identity = JWSObject.parse((String) identityObject);
JSONObject extraData = (JSONObject) identity.getPayload().toJSONObject().get("extraData");

session.setAuthenticationData(extraData.getAsString("displayName"), UUID.fromString(extraData.getAsString("identity")), extraData.getAsString("XUID"));
} catch (Exception ex) {
session.getUpstream().disconnect("An internal error occurred when connecting to this server.");
ex.printStackTrace();
return true;
}

PlayStatusPacket playStatus = new PlayStatusPacket();
playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS);
session.getUpstream().sendPacketImmediately(playStatus);

ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
session.getUpstream().sendPacketImmediately(resourcePacksInfo);
return true;
}

@Override
public boolean handle(ResourcePackClientResponsePacket textPacket) {
switch (textPacket.getStatus()) {
case COMPLETED:
// Start connecting to remote server
RemoteJavaServer remoteServer = new RemoteJavaServer(connector.getConfig().getRemote().getAddress(), connector.getConfig().getRemote().getPort());
session.connect(remoteServer);
connector.getLogger().info("Player connected with " + session.getAuthenticationData().getName());
break;
case HAVE_ALL_PACKS:
ResourcePackStackPacket stack = new ResourcePackStackPacket();
stack.setExperimental(false);
stack.setForcedToAccept(false);
session.getUpstream().sendPacketImmediately(stack);
break;
default:
session.getUpstream().disconnect("disconnectionScreen.resourcePack");
break;
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*
* You can view the LICENCE file for details.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network.remote;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class RemoteJavaServer {

private String address;
private int port;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* GNU LESSER GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*
* You can view the LICENCE file for details.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network.session;

import com.github.steveice10.mc.protocol.MinecraftProtocol;
import com.github.steveice10.packetlib.Client;
import com.github.steveice10.packetlib.event.session.ConnectedEvent;
import com.github.steveice10.packetlib.event.session.DisconnectedEvent;
import com.github.steveice10.packetlib.event.session.PacketReceivedEvent;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.tcp.TcpSessionFactory;
import com.nukkitx.network.util.DisconnectReason;
import com.nukkitx.protocol.PlayerSession;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.remote.RemoteJavaServer;

import java.util.UUID;

public class GeyserSession implements PlayerSession {

private GeyserConnector connector;

@Getter
private RemoteJavaServer remoteServer;

@Getter
private BedrockServerSession upstream;

@Getter
private Client downstream;

@Getter
private AuthenticationData authenticationData;

private boolean closed;

public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
this.connector = connector;
this.upstream = bedrockServerSession;
}

public void connect(RemoteJavaServer remoteServer) {
MinecraftProtocol protocol = new MinecraftProtocol(authenticationData.getName());
downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory());
downstream.getSession().addListener(new SessionAdapter() {

@Override
public void connected(ConnectedEvent event) {
connector.getLogger().info(authenticationData.getName() + " has connected to remote java server on address " + remoteServer.getAddress());
}

@Override
public void disconnected(DisconnectedEvent event) {
connector.getLogger().info(authenticationData.getName() + " has disconnected from remote java server on address " + remoteServer.getAddress());
upstream.disconnect(event.getReason());
}

@Override
public void packetReceived(PacketReceivedEvent event) {
// TODO: Implement translator code here
}
});

downstream.getSession().connect();
this.remoteServer = remoteServer;
}

public void disconnect(String reason) {
if (!closed) {
downstream.getSession().disconnect(reason);
upstream.disconnect(reason);
}
}

@Override
public boolean isClosed() {
return closed;
}

@Override
public void close() {
disconnect("Server closed.");
}

@Override
public void onDisconnect(DisconnectReason disconnectReason) {
downstream.getSession().disconnect("Disconnected from server. Reason: " + disconnectReason);
}

@Override
public void onDisconnect(String reason) {
downstream.getSession().disconnect("Disconnected from server. Reason: " + reason);
}

public void setAuthenticationData(String name, UUID uuid, String xboxUUID) {
authenticationData = new AuthenticationData(name, uuid, xboxUUID);
}

@Getter
@AllArgsConstructor
public class AuthenticationData {

private String name;
private UUID uuid;
private String xboxUUID;
}
}

0 comments on commit 17b99a8

Please sign in to comment.