Packet Sending Buffering

This commit is contained in:
Shoghi Cervantes Pueyo 2013-03-16 00:09:00 +01:00
parent ffaaca6f2d
commit fc06e1bcaf
5 changed files with 86 additions and 46 deletions

View File

@ -29,7 +29,9 @@ the Free Software Foundation, either version 3 of the License, or
class Player{ class Player{
private $server; private $server;
private $queue = array(); private $queue = array();
private $buffer = array(); private $buffer = "";
private $lastBuffer = 0;
private $recovery = array();
private $evid = array(); private $evid = array();
public $timeout; public $timeout;
public $connected = true; public $connected = true;
@ -152,6 +154,10 @@ class Player{
if($time > $this->timeout){ if($time > $this->timeout){
$this->close("timeout"); $this->close("timeout");
}else{ }else{
if($this->lastBuffer <= $time and strlen($this->buffer) > 0){
$this->sendBuffer();
}
if(!empty($this->queue)){ if(!empty($this->queue)){
$cnt = 0; $cnt = 0;
while($cnt < 4){ while($cnt < 4){
@ -161,7 +167,7 @@ class Player{
} }
switch($p[0]){ switch($p[0]){
case 0: case 0:
$this->dataPacket($p[1], $p[2], false, $p[3]); $this->dataPacket($p[1]["id"], $p[1], false);
break; break;
case 1: case 1:
eval($p[1]); eval($p[1]);
@ -422,33 +428,33 @@ class Player{
$this->timeout = microtime(true) + 20; $this->timeout = microtime(true) + 20;
switch($pid){ switch($pid){
case 0xa0: //NACK case 0xa0: //NACK
if(isset($this->buffer[$data[2]])){ /*if(isset($this->recovery[$data[2]])){
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]));
} }
if(isset($data[3])){ if(isset($data[3])){
if(isset($this->buffer[$data[3]])){ if(isset($this->recovery[$data[3]])){
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]));
}
} }
}*/
break; break;
case 0xc0: //ACK case 0xc0: //ACK
$diff = $data[2] - $this->counter[2]; /*$diff = $data[2] - $this->counter[2];
if($diff > 8){ //Packet recovery 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->counter[2] = $data[2];
$this->buffer[$data[2]] = null; $this->recovery[$data[2]] = null;
unset($this->buffer[$data[2]]); unset($this->recovery[$data[2]]);
if(isset($data[3])){ if(isset($data[3])){
$diff = $data[3] - $this->counter[2]; $diff = $data[3] - $this->counter[2];
if($diff > 8){ //Packet recovery 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->counter[2] = $data[3];
$this->buffer[$data[3]] = null; $this->recovery[$data[3]] = null;
unset($this->buffer[$data[3]]); unset($this->recovery[$data[3]]);
} }*/
break; break;
case 0x07: case 0x07:
if($this->loggedIn === true){ if($this->loggedIn === true){
@ -956,25 +962,49 @@ class Player{
$this->queue[] = array(1, $code); $this->queue[] = array(1, $code);
} }
public function dataPacket($id, $data = array(), $queue = false, $count = false){ public function sendBuffer(){
if($queue === true){ if(strlen($this->buffer) > 0){
$this->queue[] = array(0, $id, $data, $count);
}else{
if($count === false){
$count = $this->counter[0]; $count = $this->counter[0];
++$this->counter[0]; ++$this->counter[0];
if(count($this->buffer) >= 512){ if(count($this->recovery) >= 512){
array_shift($this->buffer); array_shift($this->recovery);
} }
$this->buffer[$count] = array($id, $data); $this->recovery[$count] = $this->buffer;
$this->send(0x80, array(
$count,
0x00,
array("id" => false, "raw" => $this->buffer),
));
} }
$data["id"] = $id;
$this->buffer = "";
$this->lastBuffer = microtime(true) + 0.05;
}
public function directDataPacket($id, $data){
$this->send(0x80, array( $this->send(0x80, array(
$count, $count,
0x00, 0x00,
$data, $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(){ function __toString(){

View File

@ -26,7 +26,11 @@ the Free Software Foundation, either version 3 of the License, or
*/ */
class CustomPacketHandler{ 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){ private function get($len = true, $check = true){
if($len === true){ if($len === true){

View File

@ -69,24 +69,27 @@ class MinecraftInterface{
if($this->socket->connected === false){ if($this->socket->connected === false){
return false; return false;
} }
$data = $this->socket->read(); $buf = "";
if($data[3] === false){ $source = false;
$port = 1;
$len = $this->socket->read($buf, $source, $port);
if($len === false){
return false; return false;
} }
$pid = ord($data[0]); $pid = ord($buf{0});
$struct = $this->getStruct($pid); $struct = $this->getStruct($pid);
if($struct === false){ if($struct === false){
console("[ERROR] Unknown Packet ID 0x".Utils::strToHex(chr($pid)), true, true, 0); 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 = "[".(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($data[0]); $p .= Utils::hexdump($buf);
$p .= PHP_EOL; $p .= PHP_EOL;
logg($p, "packets", true, 2); logg($p, "packets", true, 2);
return false; return false;
} }
$packet = new Packet($pid, $struct, $data[0]); $packet = new Packet($pid, $struct, $buf);
@$packet->parse(); @$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(); return $this->popPacket();
} }

View File

@ -80,10 +80,15 @@ class Packet{
$this->addRaw($reply->raw); $this->addRaw($reply->raw);
break; break;
case 0x00: case 0x00:
$reply = new CustomPacketHandler($this->data[$field]["id"], "", $this->data[$field], true); if($this->data[$field]["id"] !== false){
$this->addRaw(Utils::writeShort((strlen($reply->raw) + 1) << 3)); $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(chr($this->data[$field]["id"]));
$this->addRaw($reply->raw); $this->addRaw($raw);
}else{
$this->addRaw($this->data[$field]["raw"]);
}
break; break;
} }
break; break;

View File

@ -76,14 +76,12 @@ class UDPSocket{
socket_set_nonblock($this->sock); socket_set_nonblock($this->sock);
} }
public function read(){ public function read(&$buf, &$source, &$port){
if($this->connected === false){ 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); $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){ public function write($data, $dest = false, $port = false){