public function handlePacket(Packet $packet)
{
$this->isActive = true;
$this->lastUpdate = microtime(true);
if ($this->state === self::STATE_CONNECTED or $this->state === self::STATE_CONNECTING_2) {
if ($packet::$ID >= 0x80 and $packet::$ID <= 0x8f and $packet instanceof DataPacket) {
//Data packet
$packet->decode();
if ($packet->seqNumber < $this->windowStart or $packet->seqNumber > $this->windowEnd or isset($this->receivedWindow[$packet->seqNumber])) {
return;
}
$diff = $packet->seqNumber - $this->lastSeqNumber;
unset($this->NACKQueue[$packet->seqNumber]);
$this->ACKQueue[$packet->seqNumber] = $packet->seqNumber;
$this->receivedWindow[$packet->seqNumber] = $packet->seqNumber;
if ($diff !== 1) {
for ($i = $this->lastSeqNumber + 1; $i < $packet->seqNumber; ++$i) {
if (!isset($this->receivedWindow[$i])) {
$this->NACKQueue[$i] = $i;
}
}
}
if ($diff >= 1) {
$this->lastSeqNumber = $packet->seqNumber;
$this->windowStart += $diff;
$this->windowEnd += $diff;
}
foreach ($packet->packets as $pk) {
$this->handleEncapsulatedPacket($pk);
}
} else {
if ($packet instanceof ACK) {
$packet->decode();
foreach ($packet->packets as $seq) {
if (isset($this->recoveryQueue[$seq])) {
foreach ($this->recoveryQueue[$seq]->packets as $pk) {
if ($pk instanceof EncapsulatedPacket and $pk->needACK and $pk->messageIndex !== null) {
unset($this->needACK[$pk->identifierACK][$pk->messageIndex]);
}
}
unset($this->recoveryQueue[$seq]);
}
}
} elseif ($packet instanceof NACK) {
$packet->decode();
foreach ($packet->packets as $seq) {
if (isset($this->recoveryQueue[$seq])) {
$pk = $this->recoveryQueue[$seq];
$pk->seqNumber = $this->sendSeqNumber++;
$this->packetToSend[] = $pk;
unset($this->recoveryQueue[$seq]);
}
}
}
}
} elseif ($packet::$ID > 0x0 and $packet::$ID < 0x80) {
//Not Data packet :)
$packet->decode();
if ($packet instanceof OPEN_CONNECTION_REQUEST_1) {
$packet->protocol;
//TODO: check protocol number and refuse connections
$pk = new OPEN_CONNECTION_REPLY_1();
$pk->mtuSize = $packet->mtuSize;
$pk->serverID = $this->sessionManager->getID();
$this->sendPacket($pk);
$this->state = self::STATE_CONNECTING_1;
} elseif ($this->state === self::STATE_CONNECTING_1 and $packet instanceof OPEN_CONNECTION_REQUEST_2) {
$this->id = $packet->clientID;
if ($packet->serverPort === $this->sessionManager->getPort() or !$this->sessionManager->portChecking) {
$this->mtuSize = min(abs($packet->mtuSize), 1432);
//MTU — (Max IP Header Size) — (UDP Header Size) = 1500 — 60 — 8 = 1432
$pk = new OPEN_CONNECTION_REPLY_2();
$pk->mtuSize = $this->mtuSize;
$pk->serverID = $this->sessionManager->getID();
$pk->clientAddress = $this->address;
$pk->clientPort = $this->port;
$this->sendPacket($pk);
$this->state = self::STATE_CONNECTING_2;
}
}
}
}