diff --git a/src/Player.php b/src/Player.php index f62dfa53b..80e69d860 100644 --- a/src/Player.php +++ b/src/Player.php @@ -29,7 +29,9 @@ the Free Software Foundation, either version 3 of the License, or class Player{ private $server; private $queue = array(); - private $buffer = array(); + private $buffer = ""; + private $lastBuffer = 0; + private $recovery = array(); private $evid = array(); public $timeout; public $connected = true; @@ -152,6 +154,10 @@ class Player{ if($time > $this->timeout){ $this->close("timeout"); }else{ + if($this->lastBuffer <= $time and strlen($this->buffer) > 0){ + $this->sendBuffer(); + } + if(!empty($this->queue)){ $cnt = 0; while($cnt < 4){ @@ -161,7 +167,7 @@ class Player{ } switch($p[0]){ case 0: - $this->dataPacket($p[1], $p[2], false, $p[3]); + $this->dataPacket($p[1]["id"], $p[1], false); break; case 1: eval($p[1]); @@ -422,33 +428,33 @@ class Player{ $this->timeout = microtime(true) + 20; switch($pid){ case 0xa0: //NACK - if(isset($this->buffer[$data[2]])){ - array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2])); + /*if(isset($this->recovery[$data[2]])){ + array_unshift($this->queue, array(0, $this->recovery[$data[2]][0], $this->recovery[$data[2]][1], $data[2])); } if(isset($data[3])){ - if(isset($this->buffer[$data[3]])){ - array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3])); + if(isset($this->recovery[$data[3]])){ + array_unshift($this->queue, array(0, $this->recovery[$data[3]][0], $this->recovery[$data[3]][1], $data[3])); } - } + }*/ break; case 0xc0: //ACK - $diff = $data[2] - $this->counter[2]; + /*$diff = $data[2] - $this->counter[2]; if($diff > 8){ //Packet recovery - array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2])); + array_unshift($this->queue, array(0, $this->recovery[$data[2]][0], $this->recovery[$data[2]][1], $data[2])); } $this->counter[2] = $data[2]; - $this->buffer[$data[2]] = null; - unset($this->buffer[$data[2]]); + $this->recovery[$data[2]] = null; + unset($this->recovery[$data[2]]); if(isset($data[3])){ $diff = $data[3] - $this->counter[2]; if($diff > 8){ //Packet recovery - array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3])); + array_unshift($this->queue, array(0, $this->recovery[$data[3]][0], $this->recovery[$data[3]][1], $data[3])); } $this->counter[2] = $data[3]; - $this->buffer[$data[3]] = null; - unset($this->buffer[$data[3]]); - } + $this->recovery[$data[3]] = null; + unset($this->recovery[$data[3]]); + }*/ break; case 0x07: if($this->loggedIn === true){ @@ -955,26 +961,50 @@ class Player{ public function actionQueue($code){ $this->queue[] = array(1, $code); } - - public function dataPacket($id, $data = array(), $queue = false, $count = false){ - if($queue === true){ - $this->queue[] = array(0, $id, $data, $count); - }else{ - if($count === false){ - $count = $this->counter[0]; - ++$this->counter[0]; - if(count($this->buffer) >= 512){ - array_shift($this->buffer); - } - $this->buffer[$count] = array($id, $data); + + public function sendBuffer(){ + if(strlen($this->buffer) > 0){ + $count = $this->counter[0]; + ++$this->counter[0]; + if(count($this->recovery) >= 512){ + array_shift($this->recovery); } - $data["id"] = $id; + $this->recovery[$count] = $this->buffer; $this->send(0x80, array( $count, 0x00, - $data, + array("id" => false, "raw" => $this->buffer), )); } + + $this->buffer = ""; + $this->lastBuffer = microtime(true) + 0.05; + } + + public function directDataPacket($id, $data){ + $this->send(0x80, array( + $count, + 0x00, + $data, + )); + } + + public function dataPacket($id, $data = array(), $queue = false){ + $data["id"] = $id; + if($queue === true){ + $this->queue[] = array(0, $data); + }else{ + $data = new CustomPacketHandler($id, "", $data, true); + $len = strlen($data->raw) + 1; + $MTU = $this->MTU - 7; + + if((strlen($this->buffer) + $len) >= $MTU){ + $this->sendBuffer(); + } + + $this->buffer .= ($this->buffer === "" ? "":"\x00").Utils::writeShort($len << 3) . chr($id) . $data->raw; + + } } function __toString(){ diff --git a/src/network/CustomPacketHandler.php b/src/network/CustomPacketHandler.php index d87539372..14ef5c033 100644 --- a/src/network/CustomPacketHandler.php +++ b/src/network/CustomPacketHandler.php @@ -26,7 +26,11 @@ the Free Software Foundation, either version 3 of the License, or */ class CustomPacketHandler{ - var $offset, $raw, $c, $data, $name = ""; + public $offset; + public $raw; + public $c; + public $data; + public $name = ""; private function get($len = true, $check = true){ if($len === true){ diff --git a/src/network/MinecraftInterface.php b/src/network/MinecraftInterface.php index a97d63374..ff6ef3fc3 100644 --- a/src/network/MinecraftInterface.php +++ b/src/network/MinecraftInterface.php @@ -69,24 +69,27 @@ class MinecraftInterface{ if($this->socket->connected === false){ return false; } - $data = $this->socket->read(); - if($data[3] === false){ + $buf = ""; + $source = false; + $port = 1; + $len = $this->socket->read($buf, $source, $port); + if($len === false){ return false; } - $pid = ord($data[0]); + $pid = ord($buf{0}); $struct = $this->getStruct($pid); if($struct === false){ console("[ERROR] Unknown Packet ID 0x".Utils::strToHex(chr($pid)), true, true, 0); - $p = "[".(microtime(true) - $this->start)."] [".((($origin === "client" and $this->client === true) or ($origin === "server" and $this->client === false)) ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: Error, bad packet id 0x".Utils::strTohex(chr($pid))." [length ".strlen($raw)."]".PHP_EOL; - $p .= Utils::hexdump($data[0]); + $p = "[".(microtime(true) - $this->start)."] [".((($origin === "client" and $this->client === true) or ($origin === "server" and $this->client === false)) ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: Error, bad packet id 0x".Utils::strToHex(chr($pid))." [length ".strlen($buf)."]".PHP_EOL; + $p .= Utils::hexdump($buf); $p .= PHP_EOL; logg($p, "packets", true, 2); return false; } - $packet = new Packet($pid, $struct, $data[0]); + $packet = new Packet($pid, $struct, $buf); @$packet->parse(); - $this->data[] = array($pid, $packet->data, $data[0], $data[1], $data[2]); + $this->data[] = array($pid, $packet->data, $buf, $source, $port); return $this->popPacket(); } diff --git a/src/network/Packet.php b/src/network/Packet.php index dc3f4db3b..764a70e9b 100644 --- a/src/network/Packet.php +++ b/src/network/Packet.php @@ -80,10 +80,15 @@ class Packet{ $this->addRaw($reply->raw); break; case 0x00: - $reply = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true); - $this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3)); - $this->addRaw(chr($this->data[$field]["id"])); - $this->addRaw($reply->raw); + if($this->data[$field]["id"] !== false){ + $raw = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true); + $raw = $raw->raw; + $this->addRaw(Utils::writeShort((strlen($raw) + 1) << 3)); + $this->addRaw(chr($this->data[$field]["id"])); + $this->addRaw($raw); + }else{ + $this->addRaw($this->data[$field]["raw"]); + } break; } break; diff --git a/src/network/UDPSocket.php b/src/network/UDPSocket.php index 9b5232f8f..7f20bc1c1 100644 --- a/src/network/UDPSocket.php +++ b/src/network/UDPSocket.php @@ -76,14 +76,12 @@ class UDPSocket{ socket_set_nonblock($this->sock); } - public function read(){ + public function read(&$buf, &$source, &$port){ if($this->connected === false){ - return array(3 => false); + return false; } - $source = false; - $port = 1; //$source and $port will be overwritten $len = @socket_recvfrom($this->sock, $buf, 65535, 0, $source, $port); - return array($buf, $source, $port, $len); + return $len; } public function write($data, $dest = false, $port = false){