예제 #1
0
 /**
  * @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;
 }
예제 #2
0
 /**
  * @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;
 }
예제 #3
0
 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;
 }
예제 #4
0
 protected function getInt()
 {
     return Binary::readInt($this->get(4));
 }
예제 #5
0
 /**
  * @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;
 }
예제 #6
0
 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;
 }