From e0b852756086a49b1fa0d5b5e5df7c2188e396d5 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Mon, 16 Dec 2013 13:06:01 +0100 Subject: [PATCH] First changes --- src/PocketMinecraftServer.php | 4 +- src/network/MinecraftInterface.php | 157 +----------------- .../{ => protocol}/CustomPacketHandler.php | 0 src/network/protocol/ProtocolInfo.php | 94 +++++++++++ src/network/{ => raknet}/Packet.php | 0 .../RakNetInfo.php} | 100 ++++------- src/network/raknet/RakNetPacket.php | 30 ++++ src/network/raknet/RakNetParser.php | 93 +++++++++++ 8 files changed, 255 insertions(+), 223 deletions(-) rename src/network/{ => protocol}/CustomPacketHandler.php (100%) create mode 100644 src/network/protocol/ProtocolInfo.php rename src/network/{ => raknet}/Packet.php (100%) rename src/network/{ProtocolInfo.php => raknet/RakNetInfo.php} (56%) create mode 100644 src/network/raknet/RakNetPacket.php create mode 100644 src/network/raknet/RakNetParser.php diff --git a/src/PocketMinecraftServer.php b/src/PocketMinecraftServer.php index 06df08961..4fbddbf95 100644 --- a/src/PocketMinecraftServer.php +++ b/src/PocketMinecraftServer.php @@ -533,10 +533,10 @@ class PocketMinecraftServer{ case 0x05: $version = $data[1]; $size = strlen($data[2]); - if($version !== CURRENT_STRUCTURE){ + if($version !== RAKNET_STRUCTURE){ console("[DEBUG] Incorrect structure #$version from ".$packet["ip"].":".$packet["port"], true, true, 2); $this->send(0x1a, array( - CURRENT_STRUCTURE, + RAKNET_STRUCTURE, RAKNET_MAGIC, $this->serverID, ), false, $packet["ip"], $packet["port"]); diff --git a/src/network/MinecraftInterface.php b/src/network/MinecraftInterface.php index f3288c9e4..69fd82441 100644 --- a/src/network/MinecraftInterface.php +++ b/src/network/MinecraftInterface.php @@ -70,7 +70,7 @@ class MinecraftInterface{ return ($pk !== false ? $pk : $this->popPacket()); } - private function parsePacket($buf, $source, $port){ + private function parsePacket($buffer, $source, $port){ $pid = ord($buf{0}); $struct = $this->getStruct($pid); if($struct === false){ @@ -86,136 +86,11 @@ class MinecraftInterface{ return false; } - $packet = new Packet($pid, $struct, $buf); + $packet = new RakNetParser($buffer); @$packet->parse(); - if($pid === 0x99){ - $CID = PocketMinecraftServer::clientID($source, $port); - if(!isset($this->chunked[$CID]) and $packet->data[0] !== 0){ //Drop packet - return false; - } - switch($packet->data[0]){ - case 0: - $this->initChunked($CID, $source, $port); - return false; - case 1: - $this->stopChunked($CID); - return false; - case 3: - $this->ackChunked($CID, $data[1]["id"], $data[1]["index"]); - return false; - case 4: - $this->receiveChunked($CID, $data[1]["id"], $data[1]["index"], $data[1]["count"], $data[1]["data"]); - return true; - } - } - $this->data[] = array($pid, $packet->data, $buf, $source, $port); + $this->data[] = array($pid, $packet->data, $buffer, $source, $port); return true; } - - public function checkChunked($CID){ - $time = microtime(true); - foreach($this->needCheck as $CID => $packets){ - if($packets[-1] < $time){ - $d = $this->chunked[$CID]; - unset($packets[-1]); - foreach($packets as $packet){ - $this->writePacket(0x99, $packet, true, $d[1], $d[2], true); - } - $this->needCheck[$CID][-1] = $time + 5; - } - } - foreach($this->toChunk as $CID => $packets){ - $d = $this->chunked[$CID]; - $raw = ""; - $MTU = 512; - foreach($packets as $packet){ - $raw .= $packet; - if(($len = strlen($packet)) > $MTU){ - $MTU = $len; - } - } - if($MTU > $d[0][2]){ - $this->chunked[$CID][0][2] = $MTU; - }else{ - $MTU = $d[0][2]; - } - $raw = str_split(gzdeflate($raw, DEFLATEPACKET_LEVEL), $MTU - 9); // - 1 - 2 - 2 - 2 - 2 - $count = count($raw); - $messageID = $this->chunked[$CID][0][0]++; - $this->chunked[$CID][0][0] &= 0xFFFF; - if(!isset($this->needCheck[$CID])){ - $this->needCheck[$CID] = array(); - } - $this->needCheck[$CID][$messageID] = array(-1 => $time + 1); - foreach($raw as $index => $r){ - $p = "\x99\x02".Utils::writeShort($messageID).Utils::writeShort($index).Utils::writeShort($count).Utils::writeShort(strlen($r)).$r; - $this->needCheck[$CID][$messageID][$index] = $p; - $this->writePacket(0x99, $p, true, $d[1], $d[2], true); - } - unset($this->toChunk[$CID]); - } - } - - public function isChunked($CID){ - return isset($this->chunked[$CID]); - } - - private function initChunked($CID, $source, $port){ - console("[DEBUG] Starting DEFLATEPacket for $source:$port", true, true, 2); - $this->chunked[$CID] = array( - 0 => array(0, 0, 0), //index, sent/received; MTU - 1 => $source, - 2 => $port, - 3 => array(), //Received packets - ); - $this->writePacket(0x99, array( - 0 => 0, //start - ), false, $source, $port, true); - } - - public function stopChunked($CID){ - if(!isset($this->chunked[$CID])){ - return false; - } - $this->writePacket(0x99, array( - 0 => 1, //stop - ), false, $this->chunked[$CID][1], $this->chunked[$CID][2], true); - console("[DEBUG] Stopping DEFLATEPacket for ".$this->chunked[$CID][1].":".$this->chunked[$CID][2], true, true, 2); - $this->chunked[$CID][3] = null; - $this->chunked[$CID][4] = null; - unset($this->chunked[$CID]); - unset($this->toChunk[$CID]); - unset($this->needCheck[$CID]); - } - - private function ackChunked($CID, $ID, $index){ - unset($this->needCheck[$CID][$ID][$index]); - if(count($this->needCheck[$CID][$ID]) <= 1){ - unset($this->needCheck[$CID][$ID]); - } - } - - private function receiveChunked($CID, $ID, $index, $count, $data){ - if(!isset($this->chunked[$CID][3][$ID])){ - $this->chunked[$CID][3][$ID] = array(); - } - $this->chunked[$CID][3][$ID][$index] = $data; - - if(count($this->chunked[$CID][3][$ID]) === $count){ - ksort($this->chunked[$CID][3][$ID]); - $data = gzinflate(implode($this->chunked[$CID][3][$ID]), 524280); - unset($this->chunked[$CID][3][$ID]); - if($data === false or strlen($data) === 0){ - console("[ERROR] Invalid DEFLATEPacket for ".$this->chunked[$CID][1].":".$this->chunked[$CID][2], true, true, 2); - } - $offset = 0; - while(($plen = Utils::readShort(substr($data, $offset, 2), false)) !== 0xFFFF or $offset >= $len){ - $offset += 2; - $packet = substr($data, $offset, $plen); - $this->parsePacket($packet, $this->chunked[$CID][1], $this->chunked[$CID][2]); - } - } - } public function popPacket(){ if(count($this->data) > 0){ @@ -232,28 +107,12 @@ class MinecraftInterface{ if($raw === false){ $packet = new Packet($pid, $this->getStruct($pid)); $packet->data = $data; - @$packet->create(); - if($force === false and $this->isChunked($CID)){ - if(!isset($this->toChunk[$CID])){ - $this->toChunk[$CID] = array(); - } - $this->toChunk[$CID][] = $packet->raw; - $write = strlen($packet->raw); - }else{ - $write = $this->socket->write($packet->raw, $dest, $port); - $this->bandwidth[1] += $write; - } + @$packet->create(); + $write = $this->socket->write($packet->raw, $dest, $port); + $this->bandwidth[1] += $write; }else{ - if($force === false and $this->isChunked($CID)){ - if(!isset($this->toChunk[$CID])){ - $this->toChunk[$CID] = array(); - } - $this->toChunk[$CID][] = $data; - $write = strlen($data); - }else{ - $write = $this->socket->write($data, $dest, $port); - $this->bandwidth[1] += $write; - } + $write = $this->socket->write($data, $dest, $port); + $this->bandwidth[1] += $write; } return $write; } diff --git a/src/network/CustomPacketHandler.php b/src/network/protocol/CustomPacketHandler.php similarity index 100% rename from src/network/CustomPacketHandler.php rename to src/network/protocol/CustomPacketHandler.php diff --git a/src/network/protocol/ProtocolInfo.php b/src/network/protocol/ProtocolInfo.php new file mode 100644 index 000000000..58a176e92 --- /dev/null +++ b/src/network/protocol/ProtocolInfo.php @@ -0,0 +1,94 @@ +id = (int) $packetID; + } + + public function __destruct(){} +} \ No newline at end of file diff --git a/src/network/raknet/RakNetParser.php b/src/network/raknet/RakNetParser.php new file mode 100644 index 000000000..bbdaa884d --- /dev/null +++ b/src/network/raknet/RakNetParser.php @@ -0,0 +1,93 @@ +buffer = $buffer; + $this->offset = 0; + if(strlen($this->buffer) > 0){ + $this->parse(ord($this->get(1))); + }else{ + $this->packet = false; + } + } + + private function get($len){ + if($len === true){ + return substr($this->buffer, $this->offset); + } + $this->offset += $len; + return substr($this->buffer, $this->offset - $len, $len); + } + + private function getLong($unsigned = false){ + return Utils::readLong($this->get(8), $unsigned); + } + + private function getShort($unsigned = false){ + return Utils::readShort($this->get(2), $unsigned); + } + + private function getByte(){ + return ord($this->get(1)); + } + + + private function feof(){ + return !isset($this->buffer{$this->offset}); + } + + private function parse($packetID){ + $this->packet = new RakNetPacket($packetID); + $this->packet->length = strlen($this->buffer); + switch($packetID){ + case RAKNET_UNCONNECTED_PING: + $this->packet->pingID = $this->getLong(); + $this->offset += 16; //Magic + break; + case RAKNET_UNCONNECTED_PING_OPEN_CONNECTIONS: + $this->packet->pingID = $this->getLong(); + $this->offset += 16; //Magic + break; + case RAKNET_OPEN_CONNECTION_REQUEST_1: + $this->offset += 16; //Magic + $this->packet->structure = $this->getByte(); + $this->packet->MTU = strlen($this->get(true)); + break; + case RAKNET_OPEN_CONNECTION_REQUEST_2: + $this->offset += 16; //Magic + $this->packet->securoty = $this->get(5); + $this->packet->port = $this->getShort(false); + $this->packet->MTU = $this->getShort(false); + $this->packet->clientGUID = $this->getLong(); + break; + default: + $this->packet = false; + break; + } + } + +} \ No newline at end of file