-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
1,186 additions
and
1,186 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,36 @@ | ||
<?php | ||
declare(strict_types=1); | ||
declare(strict_types=1); | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
use xPaw\SourceQuery\SourceQuery; | ||
use xPaw\SourceQuery\SourceQuery; | ||
|
||
// For the sake of this example | ||
header( 'Content-Type: text/plain' ); | ||
header( 'X-Content-Type-Options: nosniff' ); | ||
// For the sake of this example | ||
header( 'Content-Type: text/plain' ); | ||
header( 'X-Content-Type-Options: nosniff' ); | ||
|
||
// Edit this -> | ||
define( 'SQ_SERVER_ADDR', 'localhost' ); | ||
define( 'SQ_SERVER_PORT', 27015 ); | ||
define( 'SQ_TIMEOUT', 1 ); | ||
define( 'SQ_ENGINE', SourceQuery::SOURCE ); | ||
// Edit this <- | ||
// Edit this -> | ||
define( 'SQ_SERVER_ADDR', 'localhost' ); | ||
define( 'SQ_SERVER_PORT', 27015 ); | ||
define( 'SQ_TIMEOUT', 1 ); | ||
define( 'SQ_ENGINE', SourceQuery::SOURCE ); | ||
// Edit this <- | ||
|
||
$Query = new SourceQuery( ); | ||
$Query = new SourceQuery( ); | ||
|
||
try | ||
{ | ||
$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE ); | ||
try | ||
{ | ||
$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE ); | ||
|
||
print_r( $Query->GetInfo( ) ); | ||
print_r( $Query->GetPlayers( ) ); | ||
print_r( $Query->GetRules( ) ); | ||
} | ||
catch( Exception $e ) | ||
{ | ||
echo $e->getMessage( ); | ||
} | ||
finally | ||
{ | ||
$Query->Disconnect( ); | ||
} | ||
print_r( $Query->GetInfo( ) ); | ||
print_r( $Query->GetPlayers( ) ); | ||
print_r( $Query->GetRules( ) ); | ||
} | ||
catch( Exception $e ) | ||
{ | ||
echo $e->getMessage( ); | ||
} | ||
finally | ||
{ | ||
$Query->Disconnect( ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,36 @@ | ||
<?php | ||
declare(strict_types=1); | ||
declare(strict_types=1); | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
use xPaw\SourceQuery\SourceQuery; | ||
use xPaw\SourceQuery\SourceQuery; | ||
|
||
// For the sake of this example | ||
header( 'Content-Type: text/plain' ); | ||
header( 'X-Content-Type-Options: nosniff' ); | ||
// For the sake of this example | ||
header( 'Content-Type: text/plain' ); | ||
header( 'X-Content-Type-Options: nosniff' ); | ||
|
||
// Edit this -> | ||
define( 'SQ_SERVER_ADDR', 'localhost' ); | ||
define( 'SQ_SERVER_PORT', 27015 ); | ||
define( 'SQ_TIMEOUT', 1 ); | ||
define( 'SQ_ENGINE', SourceQuery::SOURCE ); | ||
// Edit this <- | ||
// Edit this -> | ||
define( 'SQ_SERVER_ADDR', 'localhost' ); | ||
define( 'SQ_SERVER_PORT', 27015 ); | ||
define( 'SQ_TIMEOUT', 1 ); | ||
define( 'SQ_ENGINE', SourceQuery::SOURCE ); | ||
// Edit this <- | ||
|
||
$Query = new SourceQuery( ); | ||
$Query = new SourceQuery( ); | ||
|
||
try | ||
{ | ||
$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE ); | ||
try | ||
{ | ||
$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE ); | ||
|
||
$Query->SetRconPassword( 'my_awesome_password' ); | ||
$Query->SetRconPassword( 'my_awesome_password' ); | ||
|
||
var_dump( $Query->Rcon( 'say hello' ) ); | ||
} | ||
catch( Exception $e ) | ||
{ | ||
echo $e->getMessage( ); | ||
} | ||
finally | ||
{ | ||
$Query->Disconnect( ); | ||
} | ||
var_dump( $Query->Rcon( 'say hello' ) ); | ||
} | ||
catch( Exception $e ) | ||
{ | ||
echo $e->getMessage( ); | ||
} | ||
finally | ||
{ | ||
$Query->Disconnect( ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,141 +1,141 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
/** | ||
* @author Pavel Djundik | ||
* | ||
* @link https://xpaw.me | ||
* @link https://github.com/xPaw/PHP-Source-Query | ||
* | ||
* @license GNU Lesser General Public License, version 2.1 | ||
* | ||
* @internal | ||
*/ | ||
|
||
namespace xPaw\SourceQuery; | ||
|
||
use xPaw\SourceQuery\Exception\InvalidPacketException; | ||
use xPaw\SourceQuery\Exception\SocketException; | ||
|
||
/** | ||
* Base socket interface | ||
* | ||
* @package xPaw\SourceQuery | ||
* | ||
* @uses xPaw\SourceQuery\Exception\InvalidPacketException | ||
* @uses xPaw\SourceQuery\Exception\SocketException | ||
*/ | ||
abstract class BaseSocket | ||
/** | ||
* @author Pavel Djundik | ||
* | ||
* @link https://xpaw.me | ||
* @link https://github.com/xPaw/PHP-Source-Query | ||
* | ||
* @license GNU Lesser General Public License, version 2.1 | ||
* | ||
* @internal | ||
*/ | ||
|
||
namespace xPaw\SourceQuery; | ||
|
||
use xPaw\SourceQuery\Exception\InvalidPacketException; | ||
use xPaw\SourceQuery\Exception\SocketException; | ||
|
||
/** | ||
* Base socket interface | ||
* | ||
* @package xPaw\SourceQuery | ||
* | ||
* @uses xPaw\SourceQuery\Exception\InvalidPacketException | ||
* @uses xPaw\SourceQuery\Exception\SocketException | ||
*/ | ||
abstract class BaseSocket | ||
{ | ||
/** @var ?resource */ | ||
public $Socket; | ||
public int $Engine; | ||
|
||
public string $Address; | ||
public int $Port; | ||
public int $Timeout; | ||
|
||
public function __destruct( ) | ||
{ | ||
/** @var ?resource */ | ||
public $Socket; | ||
public int $Engine; | ||
$this->Close( ); | ||
} | ||
|
||
public string $Address; | ||
public int $Port; | ||
public int $Timeout; | ||
abstract public function Close( ) : void; | ||
abstract public function Open( string $Address, int $Port, int $Timeout, int $Engine ) : void; | ||
abstract public function Write( int $Header, string $String = '' ) : bool; | ||
abstract public function Read( ) : Buffer; | ||
|
||
public function __destruct( ) | ||
protected function ReadInternal( Buffer $Buffer, callable $SherlockFunction ) : Buffer | ||
{ | ||
if( $Buffer->Remaining( ) === 0 ) | ||
{ | ||
$this->Close( ); | ||
throw new InvalidPacketException( 'Failed to read any data from socket', InvalidPacketException::BUFFER_EMPTY ); | ||
} | ||
|
||
abstract public function Close( ) : void; | ||
abstract public function Open( string $Address, int $Port, int $Timeout, int $Engine ) : void; | ||
abstract public function Write( int $Header, string $String = '' ) : bool; | ||
abstract public function Read( ) : Buffer; | ||
$Header = $Buffer->ReadInt32( ); | ||
|
||
protected function ReadInternal( Buffer $Buffer, callable $SherlockFunction ) : Buffer | ||
if( $Header === -1 ) // Single packet | ||
{ | ||
if( $Buffer->Remaining( ) === 0 ) | ||
{ | ||
throw new InvalidPacketException( 'Failed to read any data from socket', InvalidPacketException::BUFFER_EMPTY ); | ||
} | ||
|
||
$Header = $Buffer->ReadInt32( ); | ||
// We don't have to do anything | ||
} | ||
else if( $Header === -2 ) // Split packet | ||
{ | ||
$Packets = []; | ||
$IsCompressed = false; | ||
$ReadMore = false; | ||
$PacketChecksum = null; | ||
|
||
if( $Header === -1 ) // Single packet | ||
{ | ||
// We don't have to do anything | ||
} | ||
else if( $Header === -2 ) // Split packet | ||
do | ||
{ | ||
$Packets = []; | ||
$IsCompressed = false; | ||
$ReadMore = false; | ||
$PacketChecksum = null; | ||
$RequestID = $Buffer->ReadInt32( ); | ||
|
||
do | ||
switch( $this->Engine ) | ||
{ | ||
$RequestID = $Buffer->ReadInt32( ); | ||
case SourceQuery::GOLDSOURCE: | ||
{ | ||
$PacketCountAndNumber = $Buffer->ReadByte( ); | ||
$PacketCount = $PacketCountAndNumber & 0xF; | ||
$PacketNumber = $PacketCountAndNumber >> 4; | ||
|
||
switch( $this->Engine ) | ||
break; | ||
} | ||
case SourceQuery::SOURCE: | ||
{ | ||
case SourceQuery::GOLDSOURCE: | ||
{ | ||
$PacketCountAndNumber = $Buffer->ReadByte( ); | ||
$PacketCount = $PacketCountAndNumber & 0xF; | ||
$PacketNumber = $PacketCountAndNumber >> 4; | ||
$IsCompressed = ( $RequestID & 0x80000000 ) !== 0; | ||
$PacketCount = $Buffer->ReadByte( ); | ||
$PacketNumber = $Buffer->ReadByte( ) + 1; | ||
|
||
break; | ||
} | ||
case SourceQuery::SOURCE: | ||
if( $IsCompressed ) | ||
{ | ||
$IsCompressed = ( $RequestID & 0x80000000 ) !== 0; | ||
$PacketCount = $Buffer->ReadByte( ); | ||
$PacketNumber = $Buffer->ReadByte( ) + 1; | ||
|
||
if( $IsCompressed ) | ||
{ | ||
$Buffer->ReadInt32( ); // Split size | ||
|
||
$PacketChecksum = $Buffer->ReadUInt32( ); | ||
} | ||
else | ||
{ | ||
$Buffer->ReadInt16( ); // Split size | ||
} | ||
|
||
break; | ||
$Buffer->ReadInt32( ); // Split size | ||
|
||
$PacketChecksum = $Buffer->ReadUInt32( ); | ||
} | ||
default: | ||
else | ||
{ | ||
throw new SocketException( 'Unknown engine.', SocketException::INVALID_ENGINE ); | ||
$Buffer->ReadInt16( ); // Split size | ||
} | ||
|
||
break; | ||
} | ||
default: | ||
{ | ||
throw new SocketException( 'Unknown engine.', SocketException::INVALID_ENGINE ); | ||
} | ||
} | ||
|
||
$Packets[ $PacketNumber ] = $Buffer->Read( ); | ||
$Packets[ $PacketNumber ] = $Buffer->Read( ); | ||
|
||
$ReadMore = $PacketCount > sizeof( $Packets ); | ||
} | ||
while( $ReadMore && $SherlockFunction( $Buffer ) ); | ||
$ReadMore = $PacketCount > sizeof( $Packets ); | ||
} | ||
while( $ReadMore && $SherlockFunction( $Buffer ) ); | ||
|
||
$Data = implode( $Packets ); | ||
$Data = implode( $Packets ); | ||
|
||
// TODO: Test this | ||
if( $IsCompressed ) | ||
// TODO: Test this | ||
if( $IsCompressed ) | ||
{ | ||
// Let's make sure this function exists, it's not included in PHP by default | ||
if( !function_exists( 'bzdecompress' ) ) | ||
{ | ||
// 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.' ); | ||
} | ||
throw new \RuntimeException( 'Received compressed packet, PHP doesn\'t have Bzip2 library installed, can\'t decompress.' ); | ||
} | ||
|
||
$Data = bzdecompress( $Data ); | ||
$Data = bzdecompress( $Data ); | ||
|
||
if( !is_string( $Data ) || crc32( $Data ) !== $PacketChecksum ) | ||
{ | ||
throw new InvalidPacketException( 'CRC32 checksum mismatch of uncompressed packet data.', InvalidPacketException::CHECKSUM_MISMATCH ); | ||
} | ||
if( !is_string( $Data ) || crc32( $Data ) !== $PacketChecksum ) | ||
{ | ||
throw new InvalidPacketException( 'CRC32 checksum mismatch of uncompressed packet data.', InvalidPacketException::CHECKSUM_MISMATCH ); | ||
} | ||
|
||
$Buffer->Set( substr( $Data, 4 ) ); | ||
} | ||
else | ||
{ | ||
throw new InvalidPacketException( 'Socket read: Raw packet header mismatch. (0x' . dechex( $Header ) . ')', InvalidPacketException::PACKET_HEADER_MISMATCH ); | ||
} | ||
|
||
return $Buffer; | ||
$Buffer->Set( substr( $Data, 4 ) ); | ||
} | ||
else | ||
{ | ||
throw new InvalidPacketException( 'Socket read: Raw packet header mismatch. (0x' . dechex( $Header ) . ')', InvalidPacketException::PACKET_HEADER_MISMATCH ); | ||
} | ||
|
||
return $Buffer; | ||
} | ||
} |
Oops, something went wrong.