This commit is contained in:
catfoolyou 2025-02-25 12:32:58 -05:00
parent cf21caabb0
commit 415b09b03f
8 changed files with 131 additions and 191 deletions

View File

@ -18,14 +18,7 @@ public class ServerConnection implements Server
private final BungeeServerInfo info;
private boolean isObsolete;
private Unsafe unsafe = new Unsafe()
{
@Override
public void sendPacket(DefinedPacket packet)
{
ch.write( packet );
}
};
private final Connection.Unsafe unsafe;
@Override
public void sendData(String channel, byte[] data)
@ -34,20 +27,15 @@ public class ServerConnection implements Server
}
@Override
public synchronized void disconnect(String reason)
{
if ( !ch.isClosed() )
{
// TODO: Can we just use a future here?
unsafe().sendPacket( new PacketFFKick( reason ) );
ch.getHandle().eventLoop().schedule( new Runnable()
{
public synchronized void disconnect(final String reason) {
if (this.ch != null && !this.ch.isClosed()) {
this.unsafe().sendPacket(new PacketFFKick(reason));
this.ch.getHandle().eventLoop().schedule((Runnable) new Runnable() {
@Override
public void run()
{
ch.getHandle().close();
public void run() {
ServerConnection.this.ch.getHandle().close();
}
}, 100, TimeUnit.MILLISECONDS );
}, 100L, TimeUnit.MILLISECONDS);
}
}

View File

@ -10,6 +10,8 @@ import java.util.Objects;
import java.util.Queue;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import io.netty.channel.ChannelHandler;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
@ -51,6 +53,8 @@ public class ServerConnector extends PacketHandler
private SecretKey secretkey;
private boolean sentMessages;
private boolean protocolSupport = BungeeCord.getInstance().config.getProtocolSupport();
public ServerConnector(ProxyServer bungee, UserConnection user, BungeeServerInfo target){
this.bungee = bungee;
this.user = user;
@ -79,177 +83,135 @@ public class ServerConnector extends PacketHandler
@Override
public void connected(ChannelWrapper channel) throws Exception
{
System.out.println("[ServerConnector] - connected");
this.ch = channel;
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF( "Login" );
out.writeUTF( user.getAddress().getHostString() );
out.writeInt( user.getAddress().getPort() );
channel.write( new PacketFAPluginMessage( "BungeeCord", out.toByteArray() ) );
channel.write( user.getPendingConnection().getHandshake() );
// Skip encryption if we are not using Forge
if ( user.getPendingConnection().getForgeLogin() == null )
{
channel.write( PacketConstants.CLIENT_LOGIN );
channel.write(this.user.getPendingConnection().getHandshake());
if (!protocolSupport) {
final ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Login");
out.writeUTF(this.user.getAddress().getHostString());
out.writeInt(this.user.getAddress().getPort());
channel.write(new PacketFAPluginMessage("BungeeCord", out.toByteArray()));
if (this.user.getPendingConnection().getForgeLogin() == null) {
channel.write(PacketConstants.CLIENT_LOGIN);
}
}
}
@Override
public void disconnected(ChannelWrapper channel) throws Exception
{
user.getPendingConnects().remove( target );
user.getPendingConnects().remove(this.target);
}
@Override
public void handle(Packet1Login login) throws Exception
{
Preconditions.checkState( thisState == State.LOGIN, "Not exepcting LOGIN" );
ServerConnection server = new ServerConnection( ch, target );
ServerConnectedEvent event = new ServerConnectedEvent( user, server );
bungee.getPluginManager().callEvent( event );
ch.write( BungeeCord.getInstance().registerChannels() );
Queue<DefinedPacket> packetQueue = target.getPacketQueue();
synchronized ( packetQueue )
{
while ( !packetQueue.isEmpty() )
{
ch.write( packetQueue.poll() );
public void handle(final Packet1Login login) throws Exception {
System.out.println("[ServerConnector] - Handling LOGIN");
Preconditions.checkState(this.thisState == State.LOGIN || this.thisState == State.ENCRYPT_REQUEST, (Object)"Not expecting LOGIN/ENCRYPT_REQUEST");
if (this.thisState == State.ENCRYPT_REQUEST) {
this.thisState = State.LOGIN;
}
final ServerConnection server = new ServerConnection(this.ch, this.target);
final ServerConnectedEvent event = new ServerConnectedEvent(this.user, server);
this.bungee.getPluginManager().callEvent(event);
this.ch.write(BungeeCord.getInstance().registerChannels());
final Queue<DefinedPacket> packetQueue = this.target.getPacketQueue();
synchronized (packetQueue) {
while (!packetQueue.isEmpty()) {
this.ch.write(packetQueue.poll());
}
}
for ( PacketFAPluginMessage message : user.getPendingConnection().getRegisterMessages() )
{
ch.write( message );
for (final PacketFAPluginMessage message : this.user.getPendingConnection().getRegisterMessages()) {
this.ch.write(message);
}
if ( !sentMessages )
{
for ( PacketFAPluginMessage message : user.getPendingConnection().getLoginMessages() )
{
ch.write( message );
if (!this.sentMessages) {
for (final PacketFAPluginMessage message : this.user.getPendingConnection().getLoginMessages()) {
this.ch.write(message);
}
}
if ( user.getSettings() != null )
{
ch.write( user.getSettings() );
if (this.user.getSettings() != null) {
this.ch.write(this.user.getSettings());
}
synchronized ( user.getSwitchMutex() )
{
if ( user.getServer() == null )
{
// Once again, first connection
user.setClientEntityId( login.getEntityId() );
user.setServerEntityId( login.getEntityId() );
// Set tab list size, this sucks balls, TODO: what shall we do about packet mutability
synchronized (this.user.getSwitchMutex()) {
if (this.user.getServer() == null) {
this.user.setClientEntityId(login.getEntityId());
this.user.setServerEntityId(login.getEntityId());
Packet1Login modLogin;
if ( ch.getHandle().pipeline().get( PacketDecoder.class ).getProtocol() == Forge.getInstance() )
{
modLogin = new Forge1Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), login.getDimension(), login.getDifficulty(), login.getUnused(),
(byte) user.getPendingConnection().getListener().getTabListSize() );
} else
{
modLogin = new Packet1Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte) login.getDimension(), login.getDifficulty(), login.getUnused(),
(byte) user.getPendingConnection().getListener().getTabListSize() );
if (((PacketDecoder)this.ch.getHandle().pipeline().get((Class)PacketDecoder.class)).getProtocol() == Forge.getInstance()) {
modLogin = new Forge1Login(login.getEntityId(), login.getLevelType(), login.getGameMode(), login.getDimension(), login.getDifficulty(), login.getUnused(), (byte)this.user.getPendingConnection().getListener().getTabListSize());
}
user.unsafe().sendPacket( modLogin );
MinecraftOutput out = new MinecraftOutput();
out.writeStringUTF8WithoutLengthHeaderBecauseDinnerboneStuffedUpTheMCBrandPacket( ProxyServer.getInstance().getName() + " (" + ProxyServer.getInstance().getVersion() + ")" );
user.unsafe().sendPacket( new PacketFAPluginMessage( "MC|Brand", out.toArray() ) );
} else
{
user.getTabList().onServerChange();
Scoreboard serverScoreboard = user.getServerSentScoreboard();
for ( Objective objective : serverScoreboard.getObjectives() )
{
user.unsafe().sendPacket( new PacketCEScoreboardObjective( objective.getName(), objective.getValue(), (byte) 1 ) );
else {
modLogin = new Packet1Login(login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte)login.getDimension(), login.getDifficulty(), login.getUnused(), (byte)this.user.getPendingConnection().getListener().getTabListSize());
}
for ( Team team : serverScoreboard.getTeams() )
{
user.unsafe().sendPacket( new PacketD1Team( team.getName() ) );
this.user.unsafe().sendPacket(modLogin);
}
else {
this.user.getTabList().onServerChange();
final Scoreboard serverScoreboard = this.user.getServerSentScoreboard();
for (final Objective objective : serverScoreboard.getObjectives()) {
this.user.unsafe().sendPacket(new PacketCEScoreboardObjective(objective.getName(), objective.getValue(), (byte)1));
}
for (final Team team : serverScoreboard.getTeams()) {
this.user.unsafe().sendPacket(new PacketD1Team(team.getName()));
}
serverScoreboard.clear();
user.sendDimensionSwitch();
user.setServerEntityId( login.getEntityId() );
user.unsafe().sendPacket( new Packet9Respawn( login.getDimension(), login.getDifficulty(), login.getGameMode(), (short) 256, login.getLevelType() ) );
// Remove from old servers
user.getServer().setObsolete( true );
user.getServer().disconnect( "Quitting" );
this.user.sendDimensionSwitch();
this.user.setServerEntityId(login.getEntityId());
this.user.unsafe().sendPacket(new Packet9Respawn(login.getDimension(), login.getDifficulty(), login.getGameMode(), (short)256, login.getLevelType()));
this.user.getServer().setObsolete(true);
this.user.getServer().disconnect("Quitting");
}
// TODO: Fix this?
if ( !user.isActive() )
{
server.disconnect( "Quitting" );
// Silly server admins see stack trace and die
bungee.getLogger().warning( "No client connected for pending server!" );
if (!this.user.isActive()) {
server.disconnect("Quitting");
this.bungee.getLogger().warning("No client connected for pending server!");
return;
}
// Add to new server
// TODO: Move this to the connected() method of DownstreamBridge
target.addPlayer( user );
user.getPendingConnects().remove( target );
user.setServer( server );
ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user, server ) );
this.target.addPlayer(this.user);
this.user.getPendingConnects().remove(this.target);
this.user.setServer(server);
((HandlerBoss)this.ch.getHandle().pipeline().get((Class)HandlerBoss.class)).setHandler(new DownstreamBridge(this.bungee, this.user, server));
}
bungee.getPluginManager().callEvent( new ServerSwitchEvent( user ) );
thisState = State.FINISHED;
this.bungee.getPluginManager().callEvent(new ServerSwitchEvent(this.user));
this.thisState = State.FINISHED;
throw new CancelSendSignal();
}
@Override
public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception
{
Preconditions.checkState( thisState == State.ENCRYPT_REQUEST, "Not expecting ENCRYPT_REQUEST" );
// Only need to handle this if we want to use encryption
if ( user.getPendingConnection().getForgeLogin() != null )
{
PublicKey publickey = EncryptionUtil.getPubkey( encryptRequest );
public void handle(final PacketFDEncryptionRequest encryptRequest) throws Exception {
Preconditions.checkState(this.thisState == State.ENCRYPT_REQUEST, (Object)"Not expecting ENCRYPT_REQUEST");
if (protocolSupport) {
final ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Login");
out.writeUTF(this.user.getAddress().getHostString());
out.writeInt(this.user.getAddress().getPort());
this.user.unsafe().sendPacket(new PacketFAPluginMessage("BungeeCord", out.toByteArray()));
if (this.user.getPendingConnection().getForgeLogin() == null) {
this.user.unsafe().sendPacket(PacketConstants.CLIENT_LOGIN);
}
}
if (this.user.getPendingConnection().getForgeLogin() != null) {
final PublicKey publickey = EncryptionUtil.getPubkey(encryptRequest);
this.secretkey = EncryptionUtil.getSecret();
byte[] shared = EncryptionUtil.encrypt( publickey, secretkey.getEncoded() );
byte[] token = EncryptionUtil.encrypt( publickey, encryptRequest.getVerifyToken() );
ch.write( new PacketFCEncryptionResponse( shared, token ) );
Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, secretkey );
ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
thisState = State.ENCRYPT_RESPONSE;
} else
{
thisState = State.LOGIN;
final byte[] shared = EncryptionUtil.encrypt(publickey, this.secretkey.getEncoded());
final byte[] token = EncryptionUtil.encrypt(publickey, encryptRequest.getVerifyToken());
this.ch.write(new PacketFCEncryptionResponse(shared, token));
final Cipher encrypt = EncryptionUtil.getCipher(1, this.secretkey);
this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, (ChannelHandler)new CipherEncoder(encrypt));
this.thisState = State.ENCRYPT_RESPONSE;
}
else {
this.thisState = State.LOGIN;
}
}
@Override
public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception
{
Preconditions.checkState( thisState == State.ENCRYPT_RESPONSE, "Not expecting ENCRYPT_RESPONSE" );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, secretkey );
ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
ch.write( user.getPendingConnection().getForgeLogin() );
ch.write( PacketConstants.CLIENT_LOGIN );
thisState = State.LOGIN;
public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception {
Preconditions.checkState(this.thisState == State.ENCRYPT_RESPONSE, (Object)"Not expecting ENCRYPT_RESPONSE");
final Cipher decrypt = EncryptionUtil.getCipher(2, this.secretkey);
this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, (ChannelHandler)new CipherDecoder(decrypt));
this.ch.write(this.user.getPendingConnection().getForgeLogin());
this.ch.write(PacketConstants.CLIENT_LOGIN);
this.thisState = State.LOGIN;
}
@Override

View File

@ -177,14 +177,7 @@ public final class UserConnection implements ProxiedPlayer
return displayName;
}
private Unsafe unsafe = new Unsafe()
{
@Override
public void sendPacket(DefinedPacket packet)
{
ch.write( packet );
}
};
private final Connection.Unsafe unsafe;
@ConstructorProperties({ "bungee", "ch", "name", "pendingConnection" })
public UserConnection(final ProxyServer bungee, final ChannelWrapper ch, final String name, final InitialHandler pendingConnection) {

View File

@ -111,7 +111,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
boolean skipEncryption = false;
if (handshake.getProcolVersion() == 78) {
skipEncryption = true;
this.handshake.swapProtocol((byte) 78);
System.out.println("Skipping encryption...");
//this.handshake.swapProtocol((byte) 78);
}else if(handshake.getProcolVersion() > 78) {
this.disconnect("this server does not support microsoft accounts");
return;
@ -212,6 +213,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
@Override
public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception {
System.out.println("Handle PacketFCEncryptionResponse");
Preconditions.checkState(this.thisState == State.ENCRYPT, (Object) "Not expecting ENCRYPT");
this.sharedKey = EncryptionUtil.getSecret(encryptResponse, this.request);
final Cipher decrypt = EncryptionUtil.getCipher(2, this.sharedKey);
@ -220,6 +222,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
}
private void finish() throws GeneralSecurityException {
System.out.println("Finish");
final ProxiedPlayer old = this.bungee.getPlayer(this.handshake.getUsername());
if (old != null) {
old.disconnect(this.bungee.getTranslation("already_connected"));
@ -254,6 +257,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
@Override
public void handle(final PacketCDClientStatus clientStatus) throws Exception {
System.out.println("[InitialHandler] - PacketCDClientStatus");
Preconditions.checkState(this.thisState == State.LOGIN, (Object) "Not expecting LOGIN");
final UserConnection userCon = new UserConnection(this.bungee, this.ch, this.getName(), this);
InetAddress ins = WebSocketProxy.localToRemote.get(this.ch.getHandle().remoteAddress());

View File

@ -61,14 +61,14 @@ public class UpstreamBridge extends PacketHandler
public void handle(final byte[] buf) throws Exception {
EntityMap.rewrite(Unpooled.wrappedBuffer(buf), this.con.getClientEntityId(), this.con.getServerEntityId());
if (this.con.getServer() != null && this.con.getServer().getCh() != null) {
this.con.getServer().getCh().write(buf); // Change to buf if its a problem
this.con.getServer().getCh().write(buf);
}
}
@Override
public void handle(Packet0KeepAlive alive) throws Exception
{
if ( alive.getRandomId() == con.getSentPingId() )
if (alive.getRandomId() == con.getSentPingId())
{
int newPing = (int) ( System.currentTimeMillis() - con.getSentPingTime() );
con.getTabList().onPingChange( newPing );

View File

@ -177,7 +177,6 @@ public class WebSocketListener extends WebSocketServer {
@Override
public void onMessage(WebSocket arg0, ByteBuffer arg1) {
System.out.println("[WebsocketListener] - onMessage called");
Object o = arg0.getAttachment();
if(o == null || (o instanceof PendingSocket)) {
InetAddress realAddr;
@ -210,7 +209,6 @@ public class WebSocketListener extends WebSocketServer {
}
if(o != null) {
if(o instanceof WebSocketProxy) {
System.out.println("Instance of WebSocketProxy, sending packet");
((WebSocketProxy)o).sendPacket(arg1);
}else {
System.out.println("Closing websocket");

View File

@ -1,28 +1,23 @@
//
// Decompiled by Procyon v0.5.36
//
package net.md_5.bungee.netty;
import com.google.common.base.Preconditions;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
public class ChannelWrapper
{
public class ChannelWrapper {
private final Channel ch;
public boolean isClosed() {
return closed;
}
private volatile boolean closed;
public ChannelWrapper(ChannelHandlerContext ctx)
{
public ChannelWrapper(final ChannelHandlerContext ctx) {
this.ch = ctx.channel();
}
public synchronized void write(final Object packet) {
public synchronized void write(final Object packet) { // This is a problem, the packets ARE being sent but arent coming to client
if (!this.closed) {
System.out.println("[ChannelWrapper] - trying to send packet");
this.ch.write(packet);
}
}
@ -34,15 +29,11 @@ public class ChannelWrapper
}
}
public void addBefore(String baseName, String name, ChannelHandler handler)
{
Preconditions.checkState( ch.eventLoop().inEventLoop(), "cannot add handler outside of event loop" );
//ch.pipeline().flush();
ch.pipeline().addBefore( baseName, name, handler );
public Channel getHandle() {
return this.ch;
}
public Channel getHandle()
{
return ch;
public boolean isClosed() {
return this.closed;
}
}

View File

@ -47,6 +47,7 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter {
}
public void messageReceived(final ChannelHandlerContext ctx, final MessageList<Object> msgs) throws Exception {
System.out.println("[HandlerBoss] - Message (packet?) received");
for (final Object msg : msgs) {
if (this.handler != null && ctx.channel().isActive()) {
if (msg instanceof PacketWrapper) {
@ -64,6 +65,9 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter {
this.handler.handle((byte[]) msg);
}
}
else {
System.out.println("Handler null or channel down");
}
}
}