/** * @param int $Length * @throws AuthenticationException */ public function Read($Length = 1400) { // GoldSource RCON has same structure as Query $this->Socket->Read(); if ($this->Buffer->GetByte() !== SourceQuery::S2A_RCON) { return false; } $Buffer = $this->Buffer->Get(); $Trimmed = Trim($Buffer); if ($Trimmed === 'Bad rcon_password.') { throw new AuthenticationException($Trimmed, AuthenticationException::BAD_PASSWORD); } else { if ($Trimmed === 'You have been banned from this server.') { throw new AuthenticationException($Trimmed, AuthenticationException::BANNED); } } $ReadMore = false; // There is no indentifier of the end, so we just need to continue reading // TODO: Needs to be looked again, it causes timeouts do { $this->Socket->Read(); $ReadMore = $this->Buffer->Remaining() > 0 && $this->Buffer->GetByte() === SourceQuery::S2A_RCON; if ($ReadMore) { $Packet = $this->Buffer->Get(); $Buffer .= SubStr($Packet, 0, -2); // Let's assume if this packet is not long enough, there are no more after this one $ReadMore = StrLen($Packet) > 1000; // use 1300? } } while ($ReadMore); $this->Buffer->Set(Trim($Buffer)); }
public function Read($Length = 1400) { $this->Buffer->Set(FRead($this->Socket, $Length)); if ($this->Buffer->Remaining() === 0) { // TODO: Should we throw an exception here? return; } $Header = $this->Buffer->GetLong(); if ($Header === -1) { // We don't have to do anything } else { if ($Header === -2) { $Packets = array(); $IsCompressed = false; $ReadMore = false; do { $RequestID = $this->Buffer->GetLong(); switch ($this->Engine) { case SourceQuery::GOLDSOURCE: $PacketCountAndNumber = $this->Buffer->GetByte(); $PacketCount = $PacketCountAndNumber & 0xf; $PacketNumber = $PacketCountAndNumber >> 4; break; case SourceQuery::SOURCE: $IsCompressed = ($RequestID & 0x80000000) !== 0; $PacketCount = $this->Buffer->GetByte(); $PacketNumber = $this->Buffer->GetByte() + 1; if ($IsCompressed) { $this->Buffer->GetLong(); // Split size $PacketChecksum = $this->Buffer->GetUnsignedLong(); } else { $this->Buffer->GetShort(); // Split size } break; } $Packets[$PacketNumber] = $this->Buffer->Get(); $ReadMore = $PacketCount > sizeof($Packets); } while ($ReadMore && $this->Sherlock($Length)); $Buffer = Implode($Packets); // TODO: Test this if ($IsCompressed) { // Let's make sure this function exists, it's not included in PHP by default if (!Function_Exists('bzdecompress')) { throw new RuntimeException('Received compressed packet, PHP doesn\'t have Bzip2 library installed, can\'t decompress.'); } $Buffer = bzdecompress($Buffer); if (CRC32($Buffer) !== $PacketChecksum) { throw new InvalidPacketException('CRC32 checksum mismatch of uncompressed packet data.', InvalidPacketException::CHECKSUM_MISMATCH); } } $this->Buffer->Set(SubStr($Buffer, 4)); } else { throw new InvalidPacketException('Socket read: Raw packet header mismatch. (0x' . DecHex($Header) . ')', InvalidPacketException::PACKET_HEADER_MISMATCH); } } }
public function Read($Length = 1400) { $this->Buffer->Set(FRead($this->RconSocket, $Length)); if ($this->Buffer->Remaining() < 4) { throw new InvalidPacketException('Rcon read: Failed to read any data from socket', InvalidPacketException::BUFFER_EMPTY); } $PacketSize = $this->Buffer->GetLong(); $Buffer = $this->Buffer->Get(); $Remaining = $PacketSize - StrLen($Buffer); while ($Remaining > 0) { $Buffer2 = FRead($this->RconSocket, $Length); $Buffer .= $Buffer2; $Remaining -= StrLen($Buffer2); } $this->Buffer->Set($Buffer); }
/** * Get rules (cvars) from the server * * @throws SourceQueryException * * @return bool|array Returns array with rules on success, false on failure */ public function GetRules() { if (!$this->Connected) { return false; } switch ($this->GetChallenge(self::A2S_RULES, self::S2A_RULES)) { case self::GETCHALLENGE_FAILED: return false; case self::GETCHALLENGE_ALL_CLEAR: $this->Socket->Write(self::A2S_RULES, $this->Challenge); $this->Socket->Read(); $Type = $this->Buffer->GetByte(); if ($Type == 0) { return false; } else { if ($Type != self::S2A_RULES) { throw new SourceQueryException('GetRules: Packet header mismatch. (0x' . DecHex($Type) . ')'); } } break; } $Rules = array(); $Count = $this->Buffer->GetShort(); while ($Count-- > 0 && $this->Buffer->Remaining() > 0) { $Rule = $this->Buffer->GetString(); $Value = $this->Buffer->GetString(); if (!empty($Rule)) { $Rules[$Rule] = $Value; } } return $Rules; }
public function Read($Length = 1400) { $this->Buffer->Set(FRead($this->Socket, $Length)); if ($this->Buffer->Remaining() > 0 && $this->Buffer->GetLong() == -2) { $Packets = array(); $IsCompressed = false; $ReadMore = false; do { $RequestID = $this->Buffer->GetLong(); switch ($this->Engine) { case SourceQuery::GOLDSOURCE: $PacketCountAndNumber = $this->Buffer->GetByte(); $PacketCount = $PacketCountAndNumber & 0xf; $PacketNumber = $PacketCountAndNumber >> 4; break; case SourceQuery::SOURCE: $IsCompressed = ($RequestID & 0x80000000) != 0; $PacketCount = $this->Buffer->GetByte(); $PacketNumber = $this->Buffer->GetByte() + 1; if ($IsCompressed) { $this->Buffer->GetLong(); // Split size $PacketChecksum = $this->Buffer->GetUnsignedLong(); } else { $this->Buffer->GetShort(); // Split size } break; } $Packets[$PacketNumber] = $this->Buffer->Get(); $ReadMore = $PacketCount > sizeof($Packets); } while ($ReadMore && $this->Sherlock($Length)); $Buffer = Implode($Packets); // TODO: Test this if ($IsCompressed) { // Let's make sure this function exists, it's not included in PHP by default if (!Function_Exists('bzdecompress')) { throw new RuntimeException('Received compressed packet, PHP doesn\'t have Bzip2 library installed, can\'t decompress.'); } $Data = bzdecompress($Data); if (CRC32($Data) != $PacketChecksum) { throw new SourceQueryException('CRC32 checksum mismatch of uncompressed packet data.'); } } $this->Buffer->Set(SubStr($Buffer, 4)); } }
public function Read() { $this->Buffer->Set(FRead($this->RconSocket, 4)); if ($this->Buffer->Remaining() < 4) { throw new InvalidPacketException('Rcon read: Failed to read any data from socket', InvalidPacketException::BUFFER_EMPTY); } $PacketSize = $this->Buffer->GetLong(); $this->Buffer->Set(FRead($this->RconSocket, $PacketSize)); $Buffer = $this->Buffer->Get(); $Remaining = $PacketSize - StrLen($Buffer); while ($Remaining > 0) { $Buffer2 = FRead($this->RconSocket, $Remaining); $PacketSize = StrLen($Buffer2); if ($PacketSize === 0) { throw new InvalidPacketException('Read ' . strlen($Buffer) . ' bytes from socket, ' . $Remaining . ' remaining', InvalidPacketException::BUFFER_EMPTY); break; } $Buffer .= $Buffer2; $Remaining -= $PacketSize; } $this->Buffer->Set($Buffer); }
public function Read($Length = 1400) { switch ($this->Socket->Engine) { case CI_SourceQuery::GOLDSOURCE: // GoldSource RCON has same structure as Query $this->Socket->Read(); if ($this->Buffer->GetByte() != SourceQuery::S2A_RCON) { return false; } $Buffer = $this->Buffer->Get(); $Trimmed = Trim($Buffer); if ($Trimmed == 'Bad rcon_password.' || $Trimmed == 'You have been banned from this server.') { throw new SourceQueryException($Trimmed); } $ReadMore = false; // There is no indentifier of the end, so we just need to continue reading // TODO: Needs to be looked again, it causes timeouts do { $this->Socket->Read(); $ReadMore = $this->Buffer->Remaining() > 0 && $this->Buffer->GetByte() == SourceQuery::S2A_RCON; if ($ReadMore) { $Packet = $this->Buffer->Get(); $Buffer .= SubStr($Packet, 0, -2); // Let's assume if this packet is not long enough, there are no more after this one $ReadMore = StrLen($Packet) > 1000; // use 1300? } } while ($ReadMore); $this->Buffer->Set(Trim($Buffer)); break; case CI_SourceQuery::SOURCE: $this->Buffer->Set(FRead($this->RconSocket, $Length)); $Buffer = ""; $PacketSize = $this->Buffer->GetLong(); $Buffer .= $this->Buffer->Get(); // TODO: multi packet reading $this->Buffer->Set($Buffer); break; } }