-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial writeup of new bungee handler
- Loading branch information
1 parent
f3b084f
commit c05d277
Showing
9 changed files
with
361 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
187 changes: 187 additions & 0 deletions
187
src/main/java/com/denizenscript/depenizen/bukkit/bungee/BungeeBridge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
package com.denizenscript.depenizen.bukkit.bungee; | ||
|
||
import com.denizenscript.depenizen.bukkit.properties.bungee.BungeePlayerProperties; | ||
import io.netty.bootstrap.Bootstrap; | ||
import io.netty.buffer.ByteBuf; | ||
import io.netty.channel.*; | ||
import io.netty.channel.nio.NioEventLoopGroup; | ||
import io.netty.channel.socket.SocketChannel; | ||
import io.netty.channel.socket.nio.NioSocketChannel; | ||
import net.aufdemrand.denizen.objects.dPlayer; | ||
import net.aufdemrand.denizen.utilities.debugging.dB; | ||
import net.aufdemrand.denizencore.objects.properties.PropertyParser; | ||
|
||
import java.net.SocketAddress; | ||
|
||
public class BungeeBridge { | ||
|
||
public static BungeeBridge instance; | ||
|
||
public static class NettyExceptionHandler extends ChannelDuplexHandler { | ||
|
||
@Override | ||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { | ||
dB.echoError(cause); | ||
} | ||
|
||
@Override | ||
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { | ||
ctx.connect(remoteAddress, localAddress, promise.addListener(new ChannelFutureListener() { | ||
@Override | ||
public void operationComplete(ChannelFuture future) { | ||
if (!future.isSuccess()) { | ||
dB.echoError(future.cause()); | ||
} | ||
} | ||
})); | ||
} | ||
|
||
@Override | ||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { | ||
ctx.write(msg, promise.addListener(new ChannelFutureListener() { | ||
@Override | ||
public void operationComplete(ChannelFuture future) { | ||
if (!future.isSuccess()) { | ||
dB.echoError(future.cause()); | ||
} | ||
} | ||
})); | ||
} | ||
} | ||
|
||
public static class ClientHandler extends ChannelInboundHandlerAdapter { | ||
|
||
public static final byte[] FAKE_HANDSHAKE = new byte[] { | ||
5 + 5 + 3, // Packet length prefix | ||
0, // Packet ID 0 | ||
20, // "Protocol 20" | ||
1 + 1 + 5, // 1-byte host name, 1 byte null, 5 bytes 'depen' | ||
68, // Host name is the letter 'D' | ||
0, // null byte to sneak in our identifier | ||
(byte)'d', (byte)'e', (byte)'p', (byte)'e', (byte)'n', // Special identifier 'depen' | ||
80, 0, // "We're connecting to port 80" | ||
1 // We request protocol 1: ping status (to avoid uneeded proxy functionality) | ||
}; | ||
|
||
public ByteBuf tmp; | ||
|
||
public void fail(String reason) { | ||
dB.echoError("Depenizen-Bungee connection failed: " + reason); | ||
channel.close(); | ||
} | ||
|
||
public static enum Stage { | ||
AWAIT_HEADER, | ||
AWAIT_DATA | ||
} | ||
|
||
public Channel channel; | ||
|
||
public int waitingLength; | ||
|
||
public int packetId; | ||
|
||
public Stage currentStage = Stage.AWAIT_HEADER; | ||
|
||
@Override | ||
public void handlerAdded(ChannelHandlerContext ctx) { | ||
tmp = ctx.alloc().buffer(4); | ||
} | ||
|
||
@Override | ||
public void handlerRemoved(ChannelHandlerContext ctx) { | ||
dB.log("Depenizen-Bungee connection ended."); | ||
tmp.release(); | ||
tmp = null; | ||
// TODO: trigger reconnect (after a delay) | ||
} | ||
|
||
@Override | ||
public void channelActive(ChannelHandlerContext ctx) { | ||
dB.log("Depenizen-Bungee bridge sending handshake..."); | ||
// Send a fake minecraft handshake to get us in | ||
ByteBuf handshake = ctx.alloc().buffer(FAKE_HANDSHAKE.length); | ||
handshake.writeBytes(FAKE_HANDSHAKE); | ||
ctx.writeAndFlush(handshake); // Will release handshake | ||
} | ||
|
||
@Override | ||
public void channelRead(ChannelHandlerContext ctx, Object msg) { | ||
ByteBuf m = (ByteBuf) msg; | ||
tmp.writeBytes(m); | ||
m.release(); | ||
if (currentStage == Stage.AWAIT_HEADER) { | ||
if (tmp.readableBytes() >= 8) { | ||
waitingLength = tmp.readInt(); | ||
packetId = tmp.readInt(); | ||
currentStage = Stage.AWAIT_DATA; | ||
/*if (!DepenizenBungee.instance.packets.containsKey(packetId)) { | ||
fail("Invalid packet id: " + packetId); | ||
return; | ||
}*/ | ||
} | ||
} | ||
if (currentStage == Stage.AWAIT_DATA) { | ||
if (tmp.readableBytes() >= waitingLength) { | ||
try { | ||
//DepenizenBungee.instance.packets.get(packetId).process(this, tmp); | ||
currentStage = Stage.AWAIT_HEADER; | ||
} | ||
catch (Throwable ex) { | ||
ex.printStackTrace(); | ||
fail("Internal exception."); | ||
return; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
public Channel channel; | ||
|
||
public NioEventLoopGroup workerGroup; | ||
|
||
public String address; | ||
|
||
public int port; | ||
|
||
public void sendPacket(Packet packet) { | ||
ByteBuf buf = channel.alloc().buffer(); | ||
packet.writeTo(buf); | ||
ByteBuf header = channel.alloc().buffer(); | ||
header.writeInt(buf.writerIndex()); | ||
header.writeInt(packet.getPacketId()); | ||
channel.write(header); | ||
channel.writeAndFlush(buf); | ||
} | ||
|
||
public void init(String address, int port) { | ||
this.address = address; | ||
this.port = port; | ||
workerGroup = new NioEventLoopGroup(); | ||
connect(); | ||
successInit(); | ||
} | ||
|
||
public void connect() { | ||
Bootstrap b = new Bootstrap(); | ||
b.group(workerGroup); | ||
b.channel(NioSocketChannel.class); | ||
b.option(ChannelOption.SO_KEEPALIVE, true); | ||
b.handler(new ChannelInitializer<SocketChannel>() { | ||
@Override | ||
public void initChannel(SocketChannel ch) { | ||
ClientHandler handler = new ClientHandler(); | ||
handler.channel = ch; | ||
ch.pipeline().addLast(handler).addLast(new NettyExceptionHandler()); | ||
channel = ch; | ||
} | ||
}); | ||
b.connect(address, port); | ||
} | ||
|
||
public void successInit() { | ||
instance = this; | ||
PropertyParser.registerProperty(BungeePlayerProperties.class, dPlayer.class); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/denizenscript/depenizen/bukkit/bungee/BungeeHelpers.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.denizenscript.depenizen.bukkit.bungee; | ||
|
||
import com.denizenscript.depenizen.bukkit.bungee.packets.out.SendPlayerPacket; | ||
|
||
import java.util.UUID; | ||
|
||
public class BungeeHelpers { | ||
|
||
public static void sendPlayer(UUID id, String server) { | ||
SendPlayerPacket packet = new SendPlayerPacket(); | ||
packet.playerToSend = id; | ||
packet.serverTarget = server; | ||
BungeeBridge.instance.sendPacket(packet); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/com/denizenscript/depenizen/bukkit/bungee/Packet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.denizenscript.depenizen.bukkit.bungee; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
|
||
public abstract class Packet { | ||
|
||
public abstract int getPacketId(); | ||
|
||
public abstract void writeTo(ByteBuf buf); | ||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/com/denizenscript/depenizen/bukkit/bungee/packets/out/SendPlayerPacket.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.denizenscript.depenizen.bukkit.bungee.packets.out; | ||
|
||
import com.denizenscript.depenizen.bukkit.bungee.Packet; | ||
import com.google.common.base.Charsets; | ||
import io.netty.buffer.ByteBuf; | ||
|
||
import java.util.UUID; | ||
|
||
public class SendPlayerPacket extends Packet { | ||
|
||
public UUID playerToSend; | ||
|
||
public String serverTarget; | ||
|
||
@Override | ||
public int getPacketId() { | ||
return 10; | ||
} | ||
|
||
@Override | ||
public void writeTo(ByteBuf buf) { | ||
buf.writeLong(playerToSend.getMostSignificantBits()); | ||
buf.writeLong(playerToSend.getLeastSignificantBits()); | ||
byte[] serverTargetBytes = serverTarget.getBytes(Charsets.UTF_8); | ||
buf.writeInt(serverTargetBytes.length); | ||
buf.writeBytes(serverTargetBytes); | ||
} | ||
} |
Oops, something went wrong.