Location: PHPKode > projects > Switchport Map > switchportmap/libs/Net/Server/Driver/Multiprocess/remoteConsole.php
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +----------------------------------------------------------------------+
// | PHP Version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 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.               |
// +----------------------------------------------------------------------+
// | Author: Luca Mariano <hide@address.com>                         |
// +----------------------------------------------------------------------+
// $Id: remoteConsole.php
/**
 * This is a base class for a TCP based console listener; it manages by itself
 * the standard console operations:
 *
 * - help: generated from the options list given at console creation;
 * - quit: exit from the console;
 * - shutdown: request for server shutdown; close the listener itself and
 * calls (if exists) the class method shutdownActionPerformed().
 *
 * In order to use the class you must write your own class that extends remoteConsole;
 * into your constructor you must call the superclass constructor passing as args
 * at least an array of options that the console will support, the application name
 * (a random string if you've no idea...) and socket data (address & port to bind);
 * other options are avaible, see API for details.
 * Then you must implement into your class a method for each avaible option; this method
 * must have a name with the syntax: [choice]actionPerformed
 * When a client choose the option [choice], this method will be executed
 * (if exists),  and return string is sent back to the client
 *
 * (for example, if you have a menu like L -> list files in current dir
 * and you have defined the method LactionPerformed() this
 * method will be called)
 */
define('REMOTE_CONSOLE_MAXLINE', 1024); // how much to read from a socket at a time

class Net_Server_Driver_Multiprocess_remoteConsole extends PHP_Fork {
    /**
     * A list of all options avaible to clients; the format is
     * array('choice1'=>'description 1','choice2'=>'description 2')...
     *
     * @var array
     * @access private
     */
    var $_options;
    /**
     * The name of the application that uses this console
     * for reference only, no spaces
     *
     * @var string
     * @access private
     */
    var $_applicationName;
    /**
     * The IP address to bind
     *
     * @var integer
     * @access private
     */
    var $_address;
    /**
     * The port to bind
     *
     * @var integer
     * @access private
     */
    var $_port;
    /**
     * Listening queue
     *
     * @var integer
     * @access private
     */
    var $_listenq;
    /**
     * Max number of cuncurrent conenctions
     *
     * @var integer
     * @access private
     */
    var $_fd_set_size;
    /**
     * A list of IP address that are allowed to connect to the console
     * all other IP will be banned.
     *
     * @var array
     * @access private
     */
    var $_acl;

    /**
     * The master socket
     *
     * @var resource
     * @access private
     */
    var $_sock;
    /**
     * Array of client sockets in use
     *
     * @var array
     * @access private
     */
    var $_clientFD;
    /**
     * Array of client IP
     *
     * @var array
     * @access private
     */
    var $_remote_host;
    /**
     * Array of client ports
     *
     * @var array
     * @access private
     */
    var $_remote_port;
    /**
     * Console prompt
     *
     * @var string
     * @access private
     */
    var $_prompt = ">";

    function Net_Server_Driver_Multiprocess_remoteConsole($options, $applicationName, $address = "localhost", $port = "9999", $listenq = 100, $fd_set_size = 5, $acl = array("127.0.0.1"))
    {
  //      if (!is_array($options))
  //          die ("You should specify some options for your console!\n");

        $this->_options = $options;
        $this->_applicationName = $applicationName;
        $this->_address = $address;
        $this->_port = $port;
        $this->_listenq = $listenq;
        $this->_fd_set_size = $fd_set_size;
        $this->_acl = $acl;

        $this->PHP_Fork($this->_applicationName);
    }

    function run()
    {
        if (!$this->_openSocket()) {
            socket_close ($this->_sock);
            die ("Can't open listening socket\n");
        } else
            $this->_acceptCalls();
    }

    function _openSocket()
    {
        $ret = true;
        if (($this->_sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
            echo "socket_create() fallito: motivo: " . socket_strerror ($this->_sock) . "\n";
            $ret = false;
        }
        socket_set_option($this->_sock, SOL_SOCKET, SO_REUSEADDR, 1);

        if (false == (@socket_bind ($this->_sock, $this->_address, $this->_port))) {
            echo "socket_bind() fallito: motivo: " . socket_strerror (socket_last_error($this->_sock)) . "\n";
            $ret = false;
        }

        if (($retcode = socket_listen ($this->_sock, $this->_listenq)) < 0) {
            echo "socket_listen() fallito: motivo: " . socket_strerror ($retcode) . "\n";
            $ret = false;
        }
        return $ret;
    }

    function _acceptCalls()
    {
        $maxi = -1;
        for ($i = 0; $i < $this->_fd_set_size; $i++)
        $this->_clientFD[$i] = null;

        while (true) {
            $rfds[0] = &$this->_sock;

            for ($i = 0; $i < $this->_fd_set_size; $i++) {
                if ($this->_clientFD[$i] != null)
                    $rfds[$i + 1] = $this->_clientFD[$i];
            }
            // block indefinitely until we receive a connection...
            $nready = socket_select($rfds, $null, $null, null);
            // if we have a new connection, stick it in the $client array,
            if (in_array($this->_sock, $rfds)) {
                //print "listenfd heard something, setting up new client\n";

                for ($i = 0; $i < $this->_fd_set_size; $i++) {
                    if ($this->_clientFD[$i] == null) {
                        $this->_clientFD[$i] = socket_accept($this->_sock);
                        socket_setopt($this->_clientFD[$i], SOL_SOCKET, SO_REUSEADDR, 1);
                        socket_getpeername($this->_clientFD[$i], $this->_remote_host[$i], $this->_remote_port[$i]);

                        if ($i == ($this->_fd_set_size - 1)) {
                            print ("too many clients, refusing {$this->_remote_host[$i]}\n");
                            socket_write($this->_clientFD[$i], "Sorry, too many clients" , 23);
                            $this->_closeClient($i);
                            break;
                        } else if (!in_array($this->_remote_host[$i], $this->_acl)) {
                            //print ("Refusing {$this->_remote_host[$i]} for ACL rules\n");
                            socket_write($this->_clientFD[$i], "Permission denied" , 17);
                            $this->_closeClient($i);
                            break;
                        }

                        //print "Accepted {$this->_remote_host[$i]}:{$this->_remote_port[$i]} as client[$i]\n";
                        $talkback = $this->_help();
                        socket_write($this->_clientFD[$i], $talkback , strlen($talkback));
                        break;
                    }
                }
                if ($i > $maxi)
                    $maxi = $i;

                if (--$nready <= 0)
                    continue;
            }
            // check the clients for incoming data.
            for ($i = 0; $i <= $maxi; $i++) {
                if ($this->_clientFD[$i] == null)
                    continue;

                if (in_array($this->_clientFD[$i], $rfds)) {
                    $n = trim(socket_read($this->_clientFD[$i], REMOTE_CONSOLE_MAXLINE));

                    if (!$n) {
                        $this->_closeClient($i);
                    } else {
                        // the request string is $n
                        // build the response and put in $talkback
                        if ($n == 'q') {
                            $this->_closeClient($i);
                            continue;
                            // print the help screen
                        } else if ($n == 'h') {
                            $talkback = $this->_help();
                            // quit the whole application
                        } else if ($n == 'x') {
                            $this->_stopApplication();
                            break;
                        } else {
                            // Here we manage all user-defined menu entries
                            // if a method exist with the name [choice]actionPerformed()
                            // this method will be executed and return string is sent
                            // back to the client
                            // (for example, if you have a menu like L -> list files in current dir
                            // and you have defined the method LactionPerformed() this
                            // method will be called)
                            $methodName = strtoupper($n) . "actionPerformed";
                            if (method_exists($this, $methodName)) {
                                $talkback = "\r\n" . $this->$methodName() . "\r\n" . $this->_prompt;
                            } else {
                                if (array_key_exists(strtoupper($n), $this->_options))
                                    $talkback = "Sorry, feature not yet implemented.\r\n" . $this->_prompt;
                                else
                                    $talkback = "\r\n" . $this->_prompt;
                            }
                        }
                        // send out $talkback to client
                        //print "From {$this->_remote_host[$i]}:{$this->_remote_port[$i]},   client[$i]: $n\n";

                        if ($this->_clientFD[$i] != null) {
                            socket_write($this->_clientFD[$i], $talkback , strlen($talkback));
                        }
                    }

                    if (--$nready <= 0)
                        break;
                }
            }
        }
        print(time() . " - You should never read this...\n");
        exit(1);
    }

    function _help()
    {
        $msg = "\r\n" . $this->_applicationName . " Remote Console\r\n";

        $msg .= str_repeat("-", (strlen($msg)-4)) . "\r\n";
        $msg .= "Avaible commands follows:\r\n\r\n";

        foreach($this->_options as $key => $option) {
            $msg .= strtoupper($key) . " -> " . $option . "\r\n";
        }
        $msg .= "H -> this help\r\n";
        $msg .= "Q -> quit console\r\n";
        $msg .= "X -> stop application (CAUTION!!!)\r\n\r\n";
        $msg .= $this->_prompt;

        return $msg;
    }

    function _closeClient($i)
    {
        //print "closing client[$i] ({$this->_remote_host[$i]}:{$this->_remote_port[$i]})\n";

        socket_close($this->_clientFD[$i]);
        $this->_clientFD[$i] = null;
        unset($this->_remote_host[$i]);
        unset($this->_remote_port[$i]);
    }

    function _stopApplication()
    {
        // call to application shutdown...
        if (method_exists($this, 'shutdownActionPerformed')) {
            $this->shutdownActionPerformed();
        }
        socket_close($this->_sock);
        $msg = "Remote console is going down!\n";
        for ($i = 0; $i < $this->_fd_set_size; $i++) {
            if ($this->_clientFD[$i] != null) {
                socket_write($this->_clientFD[$i], $msg, strlen($msg));
                socket_close($this->_clientFD[$i]);
            }
        }
        exit(0);
    }
}

Return current item: Switchport Map