|
| 1 | +/** |
| 2 | + * JRakLib is not affiliated with Jenkins Software LLC or RakNet. |
| 3 | + * This software is a port of RakLib https://github.com/PocketMine/RakLib. |
| 4 | +
|
| 5 | + * This file is part of JRakLib. |
| 6 | + * |
| 7 | + * JRakLib is free software: you can redistribute it and/or modify |
| 8 | + * it under the terms of the GNU Lesser General Public License as published by |
| 9 | + * the Free Software Foundation, either version 3 of the License, or |
| 10 | + * (at your option) any later version. |
| 11 | + * |
| 12 | + * JRakLib is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Lesser General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Lesser General Public License |
| 18 | + * along with JRakLib. If not, see <http://www.gnu.org/licenses/>. |
| 19 | + */ |
| 20 | +package net.beaconpe.jraklib.client; |
| 21 | + |
| 22 | +import net.beaconpe.jraklib.Binary; |
| 23 | +import net.beaconpe.jraklib.JRakLib; |
| 24 | +import net.beaconpe.jraklib.protocol.EncapsulatedPacket; |
| 25 | + |
| 26 | +import java.nio.ByteBuffer; |
| 27 | +import java.util.Arrays; |
| 28 | + |
| 29 | +/** |
| 30 | + * A handler class for handling the client. |
| 31 | + * |
| 32 | + * @author jython234 |
| 33 | + */ |
| 34 | +public class ClientHandler { |
| 35 | + protected JRakLibClient client; |
| 36 | + protected ClientInstance instance; |
| 37 | + |
| 38 | + public ClientHandler(JRakLibClient client, ClientInstance instance){ |
| 39 | + this.client = client; |
| 40 | + this.instance = instance; |
| 41 | + } |
| 42 | + |
| 43 | + public void sendEncapsulated(EncapsulatedPacket packet){ |
| 44 | + byte flags = JRakLib.PRIORITY_NORMAL; |
| 45 | + sendEncapsulated("", packet, flags); |
| 46 | + } |
| 47 | + |
| 48 | + public void sendEncapsulated(String identifier, EncapsulatedPacket packet, byte flags){ |
| 49 | + ByteBuffer bb = ByteBuffer.allocate(3+identifier.getBytes().length+packet.getTotalLength(true)); |
| 50 | + bb.put(JRakLib.PACKET_ENCAPSULATED).put((byte) identifier.getBytes().length).put(identifier.getBytes()).put(flags).put(packet.toBinary(true)); |
| 51 | + client.pushMainToThreadPacket(Arrays.copyOf(bb.array(), bb.position())); |
| 52 | + bb = null; |
| 53 | + } |
| 54 | + |
| 55 | + public void sendRaw(byte[] payload){ |
| 56 | + sendRaw(client.getServerIP(), (short) client.getServerPort(), payload); |
| 57 | + } |
| 58 | + |
| 59 | + public void sendRaw(String address, short port, byte[] payload){ |
| 60 | + ByteBuffer bb = ByteBuffer.allocate(4+address.getBytes().length+payload.length); |
| 61 | + bb.put(JRakLib.PACKET_RAW).put((byte) address.getBytes().length).put(address.getBytes()).put(Binary.writeShort(port)).put(payload); |
| 62 | + client.pushMainToThreadPacket(bb.array()); |
| 63 | + } |
| 64 | + |
| 65 | + public void sendOption(String name, String value){ |
| 66 | + ByteBuffer bb = ByteBuffer.allocate(2+name.getBytes().length+value.getBytes().length); |
| 67 | + bb.put(JRakLib.PACKET_SET_OPTION).put((byte) name.getBytes().length).put(name.getBytes()).put(value.getBytes()); |
| 68 | + client.pushMainToThreadPacket(bb.array()); |
| 69 | + } |
| 70 | + |
| 71 | + public void disconnectFromServer(){ |
| 72 | + shutdown(); |
| 73 | + } |
| 74 | + |
| 75 | + public void shutdown(){ |
| 76 | + client.shutdown(); |
| 77 | + client.pushMainToThreadPacket(new byte[] {JRakLib.PACKET_SHUTDOWN}); |
| 78 | + //TODO: Find a way to kill client after sleep. |
| 79 | + } |
| 80 | + |
| 81 | + public void emergencyShutdown(){ |
| 82 | + client.shutdown(); |
| 83 | + client.pushMainToThreadPacket(new byte[] {0x7f}); //JRakLib::PACKET_EMERGENCY_SHUTDOWN |
| 84 | + } |
| 85 | + |
| 86 | + public boolean handlePacket(){ |
| 87 | + byte[] packet = client.readThreadToMainPacket(); |
| 88 | + if(packet == null){ |
| 89 | + return false; |
| 90 | + } |
| 91 | + if(packet.length > 0){ |
| 92 | + byte id = packet[0]; |
| 93 | + int offset = 1; |
| 94 | + if(id == JRakLib.PACKET_ENCAPSULATED){ |
| 95 | + int len = packet[offset++]; |
| 96 | + String identifier = new String(Binary.subbytes(packet, offset, len)); |
| 97 | + offset += len; |
| 98 | + byte flags = packet[offset++]; |
| 99 | + byte[] buffer = Binary.subbytes(packet, offset); |
| 100 | + instance.handleEncapsulated(EncapsulatedPacket.fromBinary(buffer, true), flags); |
| 101 | + } else if(id == JRakLib.PACKET_RAW){ |
| 102 | + int len = packet[offset++]; |
| 103 | + String address = new String(Binary.subbytes(packet, offset, len)); |
| 104 | + offset += len; |
| 105 | + int port = Binary.readShort(Binary.subbytes(packet, offset, 2)); |
| 106 | + offset += 2; |
| 107 | + byte[] payload = Binary.subbytes(packet, offset); |
| 108 | + instance.handleRaw(payload); |
| 109 | + } else if(id == JRakLib.PACKET_SET_OPTION){ |
| 110 | + int len = packet[offset++]; |
| 111 | + String name = new String(Binary.subbytes(packet, offset, len)); |
| 112 | + offset += len; |
| 113 | + String value = new String(Binary.subbytes(packet, offset)); |
| 114 | + instance.handleOption(name, value); |
| 115 | + } else if(id == JRakLib.PACKET_OPEN_SESSION){ |
| 116 | + int len = packet[offset++]; |
| 117 | + String identifier = new String(Binary.subbytes(packet, offset, len)); |
| 118 | + offset += len; |
| 119 | + long serverID = Binary.readLong(Binary.subbytes(packet, offset, 8)); |
| 120 | + instance.connectionOpened(serverID); |
| 121 | + } else if(id == JRakLib.PACKET_CLOSE_SESSION){ |
| 122 | + int len = packet[offset++]; |
| 123 | + String identifier = new String(Binary.subbytes(packet, offset, len)); |
| 124 | + offset += len; |
| 125 | + len = packet[offset++]; |
| 126 | + String reason = new String(Binary.subbytes(packet, offset, len)); |
| 127 | + instance.connectionClosed(reason); |
| 128 | + } |
| 129 | + return true; |
| 130 | + } |
| 131 | + return false; |
| 132 | + } |
| 133 | +} |
0 commit comments