1
0
mirror of https://github.com/xPaw/PHP-Source-Query.git synced 2026-07-05 06:54:49 +02:00

8 Commits

Author SHA1 Message Date
Pavel Djundik cd3624704e Use Valve's packet names (proto_oob.h) 2020-12-08 11:59:45 +02:00
Pavel Djundik e96807bb24 Correct const for request value (it is still same value) 2020-12-05 12:31:51 +02:00
Pavel Djundik 7f2e4484d5 Update README.md 2020-12-05 12:16:45 +02:00
Pavel Djundik 673e572233 Use challenge straight away if available 2020-12-04 10:20:42 +02:00
Pavel Djundik 7c8e5add77 Support challenges in A2S_INFO 2020-12-04 10:18:46 +02:00
Pavel Djundik fbabd440da Fix variable 2020-12-04 10:14:45 +02:00
Pavel Djundik bbb6c4c23e Revert "Add 1200 byte padding to all requests"
This reverts commit 7231921b0b.
2020-12-04 10:05:37 +02:00
Pavel Djundik 9da781a993 Remove old badges 2020-12-03 13:01:53 +02:00
8 changed files with 38 additions and 52 deletions
+2 -1
View File
@@ -17,6 +17,7 @@
$Info = Array( ); $Info = Array( );
$Rules = Array( ); $Rules = Array( );
$Players = Array( ); $Players = Array( );
$Exception = null;
try try
{ {
@@ -87,7 +88,7 @@
</div> </div>
<div class="container"> <div class="container">
<?php if( $Exception !== '' ): ?> <?php if( $Exception !== null ): ?>
<div class="panel panel-error"> <div class="panel panel-error">
<pre class="panel-body"><?php echo htmlspecialchars( $Exception->__toString( ) ); ?></pre> <pre class="panel-body"><?php echo htmlspecialchars( $Exception->__toString( ) ); ?></pre>
</div> </div>
+2 -4
View File
@@ -1,7 +1,5 @@
# PHP Source Query # PHP Source Query
[![Build Status](https://img.shields.io/travis/com/xPaw/PHP-Source-Query.svg)](https://travis-ci.com/xPaw/PHP-Source-Query)
[![Test Coverage](https://img.shields.io/coveralls/github/xPaw/PHP-Source-Query/master.svg)](https://coveralls.io/github/xPaw/PHP-Source-Query)
[![Packagist Downloads](https://img.shields.io/packagist/dt/xpaw/php-source-query-class.svg)](https://packagist.org/packages/xpaw/php-source-query-class) [![Packagist Downloads](https://img.shields.io/packagist/dt/xpaw/php-source-query-class.svg)](https://packagist.org/packages/xpaw/php-source-query-class)
[![Packagist Version](https://img.shields.io/packagist/v/xpaw/php-source-query-class.svg)](https://packagist.org/packages/xpaw/php-source-query-class) [![Packagist Version](https://img.shields.io/packagist/v/xpaw/php-source-query-class.svg)](https://packagist.org/packages/xpaw/php-source-query-class)
@@ -11,12 +9,12 @@ The class also allows you to query servers using RCON although this only works f
[Minecraft](http://www.minecraft.net) also uses Source RCON protocol, and this means you can use this class to send commands to your minecraft server while having engine set to Source engine. [Minecraft](http://www.minecraft.net) also uses Source RCON protocol, and this means you can use this class to send commands to your minecraft server while having engine set to Source engine.
**:warning: Please do not create issues when you are unable to retrieve information from a server, unless you can prove that there is a bug within the library.** **:warning: Do not send me emails if this does not work for you, I will not help you.**
## Requirements ## Requirements
* [Modern PHP version](https://php.net/supported-versions.php) (7.4 or newer) * [Modern PHP version](https://php.net/supported-versions.php) (7.4 or newer)
* 64-bit PHP or [gmp module](https://secure.php.net/manual/en/book.gmp.php) * 64-bit PHP or [gmp module](https://secure.php.net/manual/en/book.gmp.php)
* Web server must allow UDP connections * Your server must allow UDP connections
## Protocol Specifications ## Protocol Specifications
* https://developer.valvesoftware.com/wiki/Server_queries * https://developer.valvesoftware.com/wiki/Server_queries
-1
View File
@@ -41,7 +41,6 @@
abstract public function Close( ) : void; abstract public function Close( ) : void;
abstract public function Open( string $Address, int $Port, int $Timeout, int $Engine ) : 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 Write( int $Header, string $String = '' ) : bool;
abstract public function WritePadded( int $Header, string $String = '' ) : bool;
abstract public function Read( int $Length = 1400 ) : Buffer; abstract public function Read( int $Length = 1400 ) : Buffer;
protected function ReadInternal( Buffer $Buffer, int $Length, callable $SherlockFunction ) : Buffer protected function ReadInternal( Buffer $Buffer, int $Length, callable $SherlockFunction ) : Buffer
-20
View File
@@ -61,26 +61,6 @@
return $Length === FWrite( $this->Socket, $Command, $Length ); return $Length === FWrite( $this->Socket, $Command, $Length );
} }
/**
* Write a request packge to the socket. Pads it up to 1200 bytes to prevent reflective DoS.
*
* @see https://steamcommunity.com/discussions/forum/14/2989789048633291344/
* @return bool Whether fwrite succeeded.
*/
public function WritePadded( int $Header, string $String = '' ) : bool
{
$Command = pack( 'ccccca*', 0xFF, 0xFF, 0xFF, 0xFF, $Header, $String );
$Length = strlen( $Command );
if( $Length < 1200 )
{
$Command .= str_repeat( "\0", 1200 - $Length );
$Length = 1200;
}
return $Length === fwrite( $this->Socket, $Command, $Length );
}
/** /**
* Reads from socket and returns Buffer. * Reads from socket and returns Buffer.
* *
+32 -18
View File
@@ -38,7 +38,7 @@
/** /**
* Packets sent * Packets sent
*/ */
const A2S_PING = 0x69; const A2A_PING = 0x69;
const A2S_INFO = 0x54; const A2S_INFO = 0x54;
const A2S_PLAYER = 0x55; const A2S_PLAYER = 0x55;
const A2S_RULES = 0x56; const A2S_RULES = 0x56;
@@ -47,10 +47,10 @@
/** /**
* Packets received * Packets received
*/ */
const S2A_PING = 0x6A; const A2A_ACK = 0x6A;
const S2A_CHALLENGE = 0x41; const S2C_CHALLENGE = 0x41;
const S2A_INFO = 0x49; const S2A_INFO_SRC = 0x49;
const S2A_INFO_OLD = 0x6D; // Old GoldSource, HLTV uses it const S2A_INFO_OLD = 0x6D; // Old GoldSource, HLTV uses it (actually called S2A_INFO_DETAILED)
const S2A_PLAYER = 0x44; const S2A_PLAYER = 0x44;
const S2A_RULES = 0x45; const S2A_RULES = 0x45;
const S2A_RCON = 0x6C; const S2A_RCON = 0x6C;
@@ -58,6 +58,7 @@
/** /**
* Source rcon sent * Source rcon sent
*/ */
const SERVERDATA_REQUESTVALUE = 0;
const SERVERDATA_EXECCOMMAND = 2; const SERVERDATA_EXECCOMMAND = 2;
const SERVERDATA_AUTH = 3; const SERVERDATA_AUTH = 3;
@@ -179,10 +180,10 @@
throw new SocketException( 'Not connected.', SocketException::NOT_CONNECTED ); throw new SocketException( 'Not connected.', SocketException::NOT_CONNECTED );
} }
$this->Socket->Write( self::A2S_PING ); $this->Socket->Write( self::A2A_PING );
$Buffer = $this->Socket->Read( ); $Buffer = $this->Socket->Read( );
return $Buffer->GetByte( ) === self::S2A_PING; return $Buffer->GetByte( ) === self::A2A_ACK;
} }
/** /**
@@ -200,12 +201,28 @@
throw new SocketException( 'Not connected.', SocketException::NOT_CONNECTED ); throw new SocketException( 'Not connected.', SocketException::NOT_CONNECTED );
} }
$this->Socket->WritePadded( self::A2S_INFO, "Source Engine Query\0" ); if( $this->Challenge )
$Buffer = $this->Socket->Read( ); {
$this->Socket->Write( self::A2S_INFO, "Source Engine Query\0" . $this->Challenge );
}
else
{
$this->Socket->Write( self::A2S_INFO, "Source Engine Query\0" );
}
$Buffer = $this->Socket->Read( );
$Type = $Buffer->GetByte( ); $Type = $Buffer->GetByte( );
$Server = []; $Server = [];
if( $Type === self::S2C_CHALLENGE )
{
$this->Challenge = $Buffer->Get( 4 );
$this->Socket->Write( self::A2S_INFO, "Source Engine Query\0" . $this->Challenge );
$Buffer = $this->Socket->Read( );
$Type = $Buffer->GetByte( );
}
// Old GoldSource protocol, HLTV still uses it // Old GoldSource protocol, HLTV still uses it
if( $Type === self::S2A_INFO_OLD && $this->Socket->Engine === self::GOLDSOURCE ) if( $Type === self::S2A_INFO_OLD && $this->Socket->Engine === self::GOLDSOURCE )
{ {
@@ -247,7 +264,7 @@
return $Server; return $Server;
} }
if( $Type !== self::S2A_INFO ) if( $Type !== self::S2A_INFO_SRC )
{ {
throw new InvalidPacketException( 'GetInfo: Packet header mismatch. (0x' . DecHex( $Type ) . ')', InvalidPacketException::PACKET_HEADER_MISMATCH ); throw new InvalidPacketException( 'GetInfo: Packet header mismatch. (0x' . DecHex( $Type ) . ')', InvalidPacketException::PACKET_HEADER_MISMATCH );
} }
@@ -365,7 +382,7 @@
$this->GetChallenge( self::A2S_PLAYER, self::S2A_PLAYER ); $this->GetChallenge( self::A2S_PLAYER, self::S2A_PLAYER );
$this->Socket->WritePadded( self::A2S_PLAYER, $this->Challenge ); $this->Socket->Write( self::A2S_PLAYER, $this->Challenge );
$Buffer = $this->Socket->Read( 14000 ); // Moronic Arma 3 developers do not split their packets, so we have to read more data $Buffer = $this->Socket->Read( 14000 ); // Moronic Arma 3 developers do not split their packets, so we have to read more data
// This violates the protocol spec, and they probably should fix it: https://developer.valvesoftware.com/wiki/Server_queries#Protocol // This violates the protocol spec, and they probably should fix it: https://developer.valvesoftware.com/wiki/Server_queries#Protocol
@@ -411,7 +428,7 @@
$this->GetChallenge( self::A2S_RULES, self::S2A_RULES ); $this->GetChallenge( self::A2S_RULES, self::S2A_RULES );
$this->Socket->WritePadded( self::A2S_RULES, $this->Challenge ); $this->Socket->Write( self::A2S_RULES, $this->Challenge );
$Buffer = $this->Socket->Read( ); $Buffer = $this->Socket->Read( );
$Type = $Buffer->GetByte( ); $Type = $Buffer->GetByte( );
@@ -452,20 +469,17 @@
if( $this->UseOldGetChallengeMethod ) if( $this->UseOldGetChallengeMethod )
{ {
$this->Socket->Write( self::A2S_SERVERQUERY_GETCHALLENGE, "\xFF\xFF\xFF\xFF" ); $Header = self::A2S_SERVERQUERY_GETCHALLENGE;
}
else
{
$this->Socket->WritePadded( $Header, "\xFF\xFF\xFF\xFF" );
} }
$this->Socket->Write( $Header, "\xFF\xFF\xFF\xFF" );
$Buffer = $this->Socket->Read( ); $Buffer = $this->Socket->Read( );
$Type = $Buffer->GetByte( ); $Type = $Buffer->GetByte( );
switch( $Type ) switch( $Type )
{ {
case self::S2A_CHALLENGE: case self::S2C_CHALLENGE:
{ {
$this->Challenge = $Buffer->Get( 4 ); $this->Challenge = $Buffer->Get( 4 );
+1 -1
View File
@@ -145,7 +145,7 @@
// See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Multiple-packet_Responses // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Multiple-packet_Responses
if( StrLen( $Data ) >= 4000 ) if( StrLen( $Data ) >= 4000 )
{ {
$this->Write( SourceQuery::SERVERDATA_RESPONSE_VALUE ); $this->Write( SourceQuery::SERVERDATA_REQUESTVALUE );
do do
{ {
-5
View File
@@ -38,11 +38,6 @@
return true; return true;
} }
public function WritePadded( int $Header, string $String = '' ) : bool
{
return true;
}
public function Read( int $Length = 1400 ) : Buffer public function Read( int $Length = 1400 ) : Buffer
{ {
$Buffer = new Buffer( ); $Buffer = new Buffer( );
+1 -2
View File
@@ -23,8 +23,7 @@
"require-dev": "require-dev":
{ {
"phpunit/phpunit": "9.2", "phpunit/phpunit": "9.2",
"vimeo/psalm": "^3.12", "vimeo/psalm": "^3.12"
"php-coveralls/php-coveralls": "^2.2"
}, },
"autoload": "autoload":
{ {