Location: PHPKode > projects > Switchport Map > switchportmap/libs/Net/Server/Driver.php
<?PHP
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/2_02.txt.                                 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | hide@address.com so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Authors: Stephan Schmidt <hide@address.com>                             |
// +----------------------------------------------------------------------+
//
//    $Id: Driver.php,v 1.15 2006/06/27 10:40:44 cweiske Exp $

/**
 * Base class for all drivers
 *
 * @category    Networking
 * @package     Net_Server
 * @author      Stephan Schmidt <hide@address.com>
 */

/**
 * uses PEAR's error handling and the destructors
 */
require_once 'PEAR.php';

/**
 * Base class for all drivers
 *
 * This class provides methods, can be used by all
 * server implementations.
 *
 * @category    Networking
 * @package     Net_Server
 * @author      Stephan Schmidt <hide@address.com>
 * @author      Christian Weiske <hide@address.com>
 */
class Net_Server_Driver extends PEAR {
   /**
    * port to listen
    * @access private
    * @var    integer        $port
    */
    var $port = 10000;

   /**
    * domain to bind to
    * @access private
    * @var    string    $domain
    */
    var $domain = "localhost";

   /**
    * The connection protocol:
    * AF_INET, AF_INET6, AF_UNIX
    *
    * @access private
    * @var integer
    */
    var $protocol = AF_INET;

   /**
    * all file descriptors are stored here
    * @access private
    * @var    array    $clientFD
    */
    var $clientFD = array();

   /**
    * maximum amount of clients
    * @access private
    * @var    integer    $maxClients
    */
    var $maxClients = -1;

   /**
    * buffer size for socket_read
    * @access private
    * @var    integer    $readBufferSize
    */
    var $readBufferSize = 128;

   /**
    * end character for socket_read
    * @access private
    * @var    integer    $readEndCharacter
    */
    var $readEndCharacter = "\n";

   /**
    * maximum of backlog in queue
    * @access private
    * @var    integer    $maxQueue
    */
    var $maxQueue = 500;

   /**
    * debug mode
    * @access private
    * @var    boolean    $_debug
    */
    var $_debug = true;

   /**
    * debug mode, normally only text is needed, as servers should not be run in a browser
    * @access private
    * @var    string    $_debugMode
    */
    var $_debugMode = "text";

   /**
    * debug destination (filename or stdout)
    * @access private
    * @var    string    $_debugDest
    */
    var $_debugDest = "stdout";

   /**
    * empty array, used for socket_select
    * @access private
    * @var    array    $null
    */
    var $null = array();

   /**
    * needed to store client information
    * @access private
    * @var    array    $clientInfo
    */
    var $clientInfo = array();

    /**
     * Part of the string that has been read via socket_read
     * but came after the readEndCharacter char.
     *
     * This can happen if the server gets hammered with > 100 requests
     * per second - multiple requests are delivered on the same connection
     * then. We need to supply a way to split the single packages, and
     * _readLeftOver is the solution.
     *
     * @access private
     * @var string
     */
    var $_readLeftOver = null;

   /**
    * constructor _MUST_ not be called directly
    *
    * Please use the Net_Server::create() method instead
    * that can be called statically and will return a server
    * of the specified type.
    *
    * @access   private
    * @param    string   $domain      domain to bind to
    * @param    integer  $port        port to listen to
    * @param    integer  $protocol    protocol type: AF_INET (default), AF_INET6, AF_UNIX
    * @see      Net_Server::create()
    */
    function Net_Server_Driver($domain = "localhost", $port = 10000, $protocol = AF_INET)
    {
        $this->PEAR();

        $this->domain   = $domain;
        $this->port     = $port;
        $this->protocol = (int)$protocol;
    }

   /**
    * destructor
    *
    * Will shutdown the server if the script is abborted.
    *
    * @access   private
    */
    function _Net_Server_Driver()
    {
        $this->shutdown();
    }

   /**
    * Set debug mode
    *
    * Debug information can either be written
    * to a logfile or standard out (= the console).
    *
    * To disable debugging, pass false as first parameter.
    *
    * @access   public
    * @param    mixed    $debug   [text|html|false]
    * @param    string   $dest    destination of debug message (stdout to output or filename if log should be written)
    */
    function setDebugMode($debug, $dest = "stdout")
    {
        if ($debug === false) {
            $this->_debug = false;
            return true;
        }

        $this->_debug     = true;
        $this->_debugMode = $debug;
        $this->_debugDest = $dest;
    }

   /**
    * read from a socket
    *
    * @access   private
    * @param    integer         $clientId    internal id of the client to read from
    * @return   string|boolean  $data        data that was read
    */
    function readFromSocket($clientId = 0)
    {
        //    start with empty string
        $data = '';

        // There are problems when readEndCharacter is longer than
        // readBufferSize - endings won't be detected.
        $lookInData = strlen($this->readEndCharacter) > $this->readBufferSize;
        if ($lookInData) {
            $extraDataLength = strlen($this->readEndCharacter) - $this->readBufferSize;
        }

        //    read data from socket
        while (true) {
            if ($this->_readLeftOver == null) {
                $buf = socket_read($this->clientFD[$clientId], $this->readBufferSize);
            } else {
                $buf = $this->_readLeftOver;
                $this->_readLeftOver = null;
            }

            if ($this->readEndCharacter != null) {
                if (strlen($buf) == 0) {
                    break;
                }

                if (!$lookInData) {
                    $posEndChar = strpos($buf, $this->readEndCharacter);
                } else {
                    $posEndChar = strpos(substr($data, - $extraDataLength) . $buf, $this->readEndCharacter);
                }
                if ($posEndChar === false) {
                    $data .= $buf;
                } else {
                    $posEndChar += strlen($this->readEndCharacter);
                    $data .= substr($buf, 0, $posEndChar);
                    if ($posEndChar < strlen($buf)) {
                        $this->_readLeftOver = substr($buf, $posEndChar);
                    }
                    break;
                }
            } else {
                /**
                 * readEndCharacter is set to null => autodetect
                 */
                if (strlen($buf) < $this->readBufferSize) {
                    $data .= $buf;
                    break;
                }
            }
        }

        if ($buf === false) {
            $this->_sendDebugMessage("Could not read from client ".$clientId." (".$this->getLastSocketError($this->clientFD[$clientId]).").");
            return false;
        }
        if ((string)$data === '') {
            return false;
        }
        return $data;
    }

   /**
    * send a debug message
    *
    * Debug messages will be either sent to standard out
    * or written to a logfile, depending on debug settings.
    *
    * @access public
    * @param  string    $msg    message to debug
    * @see    setDebugMode()
    * @todo   remove underscore from method name as the method now is public.
    */
    function _sendDebugMessage($msg)
    {
        if (!$this->_debug) {
            return false;
        }

        $msg    =    date("Y-m-d H:i:s", time()) . " " . $msg;    

        switch ($this->_debugMode) {
            case    "text":
                $msg    =    $msg."\n";
                break;
            case    "html":
                $msg    =    htmlspecialchars($msg) . "<br />\n";
                break;
        }

        if ($this->_debugDest == "stdout" || empty($this->_debugDest)) {
            echo    $msg;
            flush();
            return true;
        }

        error_log($msg, 3, $this->_debugDest);
        return true;
    }

   /**
    * register a callback object
    *
    * The callback object is the actual server,
    * that contains the logic to process the events
    * triggered by the driver class.
    *
    * The best way to create a callback object is to
    * extend the Net_Server_Handler class.
    *
    * @access public
    * @param  object    $object     callback object
    * @see    Net_Server_Handler
    */
    function setCallbackObject(&$object)
    {
        $this->callbackObj = &$object;
        if (method_exists($this->callbackObj,'setServerReference')) {
            $this->callbackObj->setServerReference($this);
        }
    }

   /**
    * return string for last socket error
    *
    * @access   public
    * @return string    $error    last error
    */
    function getLastSocketError(&$fd)
    {
        if (!is_resource($fd)) {
            return '';
        }
        $lastError    =    socket_last_error($fd);
        return 'Msg: ' . socket_strerror($lastError) . ' / Code: '.$lastError;
    }

   /**
    * Sets the readEndCharacter setting.
    *
    * @access public
    * @param  string $readEndCharacter The new end character
    */
    function setEndCharacter($readEndCharacter)
    {
        $this->readEndCharacter = $readEndCharacter;
    }

   /**
    * Returns the readEndCharacter setting.
    *
    * @access public
    * @return string    The readEndCharacter setting
    */
    function getEndCharacter($readEndCharacter)
    {
        return $this->readEndCharacter;
    }
}
?>
Return current item: Switchport Map