Location: PHPKode > scripts > srcds rcon > srcds-rcon/clsRcon.php
<?php
/**
 * clsRcon
 * Connects with a Source dedicated server and allows you to execute rcon commands
 *
 * @author Geert Broekmans <php [at] madclog [dot] nl>
 * @copyright 2008 Geert Broekmans
 * @license GNU GPL
 * @version 1.0
 * ========================================================================
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * ========================================================================
 */
class clsRcon {
    /**
     * Address of the server
     *
     * @var string
     */
    protected $m_sAddress;
    /**
     * Port number of the server
     *
     * @var int
     */
    protected $m_iPort;
    /**
     * rcon password
     *
     * @var string
     */
    protected $m_sPassword;
    /**
     * TCP socket for communication
     *
     * @var object
     */
    protected $m_oSocket = false;
    /**
     * rcon request id
     *
     * @var int
     */
    protected $m_iRequestId = 0;
    /**
     * timeout in usec
     *
     * @var int
     */
    protected $m_iReadTimeout = 150000;

    const SERVERDATA_EXECCOMMAND = 2;
    const SERVERDATA_AUTH = 3;
    const SERVERDATA_RESPONSE_VALUE = 0;
    const SERVERDATA_AUTH_RESPONSE = 2;

    /**
     * __construct
     * Set the variables used to connect
     *
     * @access public
     * @param string $p_sAddress
     * @param int $p_iPort
     * @param string $p_sPassword
     * @return clsRcon
     */
    public function __construct($p_sAddress, $p_iPort, $p_sPassword) {
        $this->m_sAddress = $p_sAddress;
        $this->m_iPort = $p_iPort;
        $this->m_sPassword = $p_sPassword;
    }

    /**
     * __destruct
     * closes the socket
     *
     * @access public
     * @return void
     */
    public function __destruct() {
        if ($this->m_oSocket !== false) {
            socket_close($this->m_oSocket);
            $this->m_oSocket = false;
        }
    }

    /**
     * connect
     * Connects the socket and authenticates with the server
     *
     * @access public
     * @return boolean
     */
    public function connect() {
        // create a socket
        if (($this->m_oSocket = socket_create(AF_INET,SOCK_STREAM, SOL_TCP)) === false) {
            return false;
        }
        // connect it
        if (socket_connect($this->m_oSocket, $this->m_sAddress, $this->m_iPort) === false) {
            $this->m_oSocket = false;
            return false;
        }
        // send authentication request
        $this->rawPacketSend($this->m_sPassword, null, self::SERVERDATA_AUTH);
        // read the response
        $aResult = $this->rawPacketRead();
        // check if we authenticated succesfully
        if ($aResult[0]['CommandResponse'] != self::SERVERDATA_AUTH_RESPONSE) {
            $this->__destruct();
            return false;
        } else {
            return true;
        }
    }

    /**
     * rcon
     * execute an rcon command
     *
     * @access public
     * @param string $p_sCommand
     * @return array
     */
    public function rcon($p_sCommand) {
        // check connection
        if($this->m_oSocket === false) {
            return false;
        }
        $this->rawPacketSend($p_sCommand);

        return $this->rawPacketRead();
    }

    /**
     * rawPacketSend
     * Builds up a packet and sends it to the server
     *
     * @access protected
     * @param string $p_sString1
     * @param string $p_sString2
     * @param int $p_iCommand
     * @return void
     */
    protected function rawPacketSend($p_sString1, $p_sString2 = NULL, $p_iCommand = self::SERVERDATA_EXECCOMMAND) {
        // build the packet backwards
        $sPacket = $p_sString1 . "\x00" . $p_sString2 . "\x00";
        // build the Request ID and Command into the Packet
        $sPacket = pack('VV',++$this->m_iRequestID, $p_iCommand) . $sPacket;
        // add the length
        $sPacket = pack('V',strlen($sPacket)) . $sPacket;
        // send the packet.
        socket_send($this->m_oSocket, $sPacket, strlen($sPacket), 0x00);
    }

    /**
     * rawPacketRead
     * reads and parses the rcon response
     *
     * @access protected
     * @return array
     */
    protected function rawPacketRead() {
        // the packets
        $aPackets = array();
        // our reading socket
        $aRead = array($this->m_oSocket);
        // we need to use a buffer cause sometimes a packet is send over more then 1 'read request'
        $sBuffer = '';
        while (socket_select($aRead, $aWrite = NULL, $aExcept = NULL, 0, $this->m_iReadTimeout)) {
            // get the packet length
            if (strlen($sBuffer) == 0) {
                $aPacketLength = unpack('V1PacketLength', socket_read($aRead[0], 4));
            }

            // read some data
            $sBuffer .= socket_read($aRead[0], $aPacketLength['PacketLength'] - strlen($sBuffer));
            // if the package is complete parse it
            if (strlen($sBuffer) == $aPacketLength['PacketLength']) {
                // read the actuall packet
                $aPacket = unpack('V1RequestID/V1CommandResponse/a*String1/a*String2', $sBuffer);
                $sBuffer = '';

                if (isset($aPackets[$aPacket['RequestID']]) && $aPacket['CommandResponse'] != self::SERVERDATA_AUTH_RESPONSE) {
                    // existing reply, append the data
                    $aPackets[$aPacket['RequestID']]['String1'] .= $aPacket['String1'];
                    $aPackets[$aPacket['RequestID']]['String2'] .= $aPacket['String2'];
                } else {
                    // new reply
                    $aPackets[$aPacket['RequestID']] = $aPacket;
                }
            }
        }
        return array_values($aPackets);
    }
}

/**
 * test case below
 */
//$oTest = new clsRcon('1.2.3.4', 27015, 'mypass');
//$oTest->connect();
//$aResponse = $oTest->rcon('cvarlist');
//var_dump($aResponse[0]['String1']);

?> 
Return current item: srcds rcon