/** * @param string $binary * @param bool $internal * @param int &$offset * * @return EncapsulatedPacket */ public static function fromBinary($binary, $internal = false, &$offset = null) { $packet = new EncapsulatedPacket(); $flags = ord($binary[0]); $packet->reliability = $reliability = ($flags & 0b11100000) >> 5; $packet->hasSplit = $hasSplit = ($flags & 0b10000) > 0; if ($internal) { $length = Binary::readInt(substr($binary, 1, 4)); $packet->identifierACK = Binary::readInt(substr($binary, 5, 4)); $offset = 9; } else { $length = (int) ceil(Binary::readShort(substr($binary, 1, 2)) / 8); $offset = 3; $packet->identifierACK = null; } /* * From http://www.jenkinssoftware.com/raknet/manual/reliabilitytypes.html * * Default: 0b010 (2) or 0b011 (3) * * 0: UNRELIABLE * 1: UNRELIABLE_SEQUENCED * 2: RELIABLE * 3: RELIABLE_ORDERED * 4: RELIABLE_SEQUENCED * 5: UNRELIABLE_WITH_ACK_RECEIPT * 6: RELIABLE_WITH_ACK_RECEIPT * 7: RELIABLE_ORDERED_WITH_ACK_RECEIPT */ if ($reliability > 0) { if ($reliability >= 2 and $reliability !== 5) { $packet->messageIndex = Binary::readLTriad(substr($binary, $offset, 3)); $offset += 3; } if ($reliability <= 4 and $reliability !== 2) { $packet->orderIndex = Binary::readLTriad(substr($binary, $offset, 3)); $offset += 3; $packet->orderChannel = ord($binary[$offset++]); } } if ($hasSplit) { $packet->splitCount = Binary::readInt(substr($binary, $offset, 4)); $offset += 4; $packet->splitID = Binary::readShort(substr($binary, $offset, 2)); $offset += 2; $packet->splitIndex = Binary::readInt(substr($binary, $offset, 4)); $offset += 4; } $packet->buffer = substr($binary, $offset, $length); $offset += $length; return $packet; }
/** * @param string $binary * @param bool $internal * @param int &$offset * * @return EncapsulatedPacket */ public static function fromBinary($binary, $internal = false, &$offset = null) { $packet = new EncapsulatedPacket(); $flags = ord($binary[0]); $packet->reliability = $reliability = ($flags & 0b11100000) >> 5; $packet->hasSplit = $hasSplit = ($flags & 0b10000) > 0; if ($internal) { $length = Binary::readInt(substr($binary, 1, 4)); $packet->identifierACK = Binary::readInt(substr($binary, 5, 4)); $offset = 9; } else { $length = (int) ceil(Binary::readShort(substr($binary, 1, 2)) / 8); $offset = 3; $packet->identifierACK = null; } if ($reliability > PacketReliability::UNRELIABLE) { if ($reliability >= PacketReliability::RELIABLE and $reliability !== PacketReliability::UNRELIABLE_WITH_ACK_RECEIPT) { $packet->messageIndex = Binary::readLTriad(substr($binary, $offset, 3)); $offset += 3; } if ($reliability <= PacketReliability::RELIABLE_SEQUENCED and $reliability !== PacketReliability::RELIABLE) { $packet->orderIndex = Binary::readLTriad(substr($binary, $offset, 3)); $offset += 3; $packet->orderChannel = ord($binary[$offset++]); } } if ($hasSplit) { $packet->splitCount = Binary::readInt(substr($binary, $offset, 4)); $offset += 4; $packet->splitID = Binary::readShort(substr($binary, $offset, 2)); $offset += 2; $packet->splitIndex = Binary::readInt(substr($binary, $offset, 4)); $offset += 4; } $packet->buffer = substr($binary, $offset, $length); $offset += $length; return $packet; }
public function receiveStream() { if (strlen($packet = $this->server->readMainToThreadPacket()) > 0) { $id = ord($packet[0]); $offset = 1; if ($id === RakLib::PACKET_ENCAPSULATED) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; if (isset($this->sessions[$identifier])) { $flags = ord($packet[$offset++]); $buffer = substr($packet, $offset); $this->sessions[$identifier]->addEncapsulatedToQueue(EncapsulatedPacket::fromBinary($buffer, true), $flags); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_RAW) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = Binary::readShort(substr($packet, $offset, 2)); $offset += 2; $payload = substr($packet, $offset); $this->socket->writePacket($payload, $address, $port); } elseif ($id === RakLib::PACKET_CLOSE_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_INVALID_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } } elseif ($id === RakLib::PACKET_SET_OPTION) { $len = ord($packet[$offset++]); $name = substr($packet, $offset, $len); $offset += $len; $value = substr($packet, $offset); switch ($name) { case "name": $this->name = $value; break; case "portChecking": $this->portChecking = (bool) $value; break; case "packetLimit": $this->packetLimit = (int) $value; break; } } elseif ($id === RakLib::PACKET_BLOCK_ADDRESS) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $timeout = Binary::readInt(substr($packet, $offset, 4)); $this->blockAddress($address, $timeout); } elseif ($id === RakLib::PACKET_SHUTDOWN) { foreach ($this->sessions as $session) { $this->removeSession($session); } $this->socket->close(); $this->shutdown = true; } elseif ($id === RakLib::PACKET_EMERGENCY_SHUTDOWN) { $this->shutdown = true; } else { return false; } return true; } return false; }
protected function getInt() { return Binary::readInt($this->get(4)); }
/** * @return bool */ public function handlePacket() { if (strlen($packet = $this->server->readThreadToMainPacket()) > 0) { $id = ord($packet[0]); $offset = 1; if ($id === RakLib::PACKET_ENCAPSULATED) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $flags = ord($packet[$offset++]); $buffer = substr($packet, $offset); $this->instance->handleEncapsulated($identifier, EncapsulatedPacket::fromBinary($buffer, true), $flags); } elseif ($id === RakLib::PACKET_RAW) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = Binary::readShort(substr($packet, $offset, 2)); $offset += 2; $payload = substr($packet, $offset); $this->instance->handleRaw($address, $port, $payload); } elseif ($id === RakLib::PACKET_SET_OPTION) { $len = ord($packet[$offset++]); $name = substr($packet, $offset, $len); $offset += $len; $value = substr($packet, $offset); $this->instance->handleOption($name, $value); } elseif ($id === RakLib::PACKET_OPEN_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = Binary::readShort(substr($packet, $offset, 2)); $offset += 2; $clientID = Binary::readLong(substr($packet, $offset, 8)); $this->instance->openSession($identifier, $address, $port, $clientID); } elseif ($id === RakLib::PACKET_CLOSE_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $len = ord($packet[$offset++]); $reason = substr($packet, $offset, $len); $this->instance->closeSession($identifier, $reason); } elseif ($id === RakLib::PACKET_INVALID_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $this->instance->closeSession($identifier, "Invalid session"); } elseif ($id === RakLib::PACKET_ACK_NOTIFICATION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; $identifierACK = Binary::readInt(substr($packet, $offset, 4)); $this->instance->notifyACK($identifier, $identifierACK); } return true; } return false; }
public function receiveStream() { if (strlen($packet = $this->server->readMainToThreadPacket()) > 0) { $id = ord($packet[0]); $offset = 1; if ($id === RakLib::PACKET_ENCAPSULATED) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); $offset += $len; if (isset($this->sessions[$identifier])) { $flags = ord($packet[$offset++]); $buffer = substr($packet, $offset); $this->sessions[$identifier]->addEncapsulatedToQueue(EncapsulatedPacket::fromBinary($buffer, true), $flags); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_RAW) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $port = Binary::readShort(substr($packet, $offset, 2)); $offset += 2; $payload = substr($packet, $offset); $this->socket->writePacket($payload, $address, $port); } elseif ($id === RakLib::PACKET_TICK) { $time = microtime(true); foreach ($this->sessions as $session) { $session->update($time); } foreach ($this->ipSec as $address => $count) { if ($count >= $this->packetLimit) { $this->blockAddress($address); } } $this->ipSec = []; if (($this->ticks & 0b1111) === 0) { $diff = max(0.005, $time - $this->lastMeasure); $this->streamOption("bandwidth", serialize(["up" => $this->sendBytes / $diff, "down" => $this->receiveBytes / $diff])); $this->lastMeasure = $time; $this->sendBytes = 0; $this->receiveBytes = 0; if (count($this->block) > 0) { asort($this->block); $now = microtime(true); foreach ($this->block as $address => $timeout) { if ($timeout <= $now) { unset($this->block[$address]); } else { break; } } } gc_collect_cycles(); } ++$this->ticks; } elseif ($id === RakLib::PACKET_CLOSE_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } else { $this->streamInvalid($identifier); } } elseif ($id === RakLib::PACKET_INVALID_SESSION) { $len = ord($packet[$offset++]); $identifier = substr($packet, $offset, $len); if (isset($this->sessions[$identifier])) { $this->removeSession($this->sessions[$identifier]); } } elseif ($id === RakLib::PACKET_SET_OPTION) { $len = ord($packet[$offset++]); $name = substr($packet, $offset, $len); $offset += $len; $value = substr($packet, $offset); switch ($name) { case "name": $this->name = $value; break; case "portChecking": $this->portChecking = (bool) $value; break; case "packetLimit": $this->packetLimit = (int) $value; break; } } elseif ($id === RakLib::PACKET_BLOCK_ADDRESS) { $len = ord($packet[$offset++]); $address = substr($packet, $offset, $len); $offset += $len; $timeout = Binary::readInt(substr($packet, $offset, 4)); $this->blockAddress($address, $timeout); } elseif ($id === RakLib::PACKET_SHUTDOWN) { foreach ($this->sessions as $session) { $this->removeSession($session); } $this->socket->close(); $this->shutdown = true; } elseif ($id === RakLib::PACKET_EMERGENCY_SHUTDOWN) { $this->shutdown = true; } else { return false; } return true; } return false; }