Your browser must have JavaScript enabled in order to view this page.
 >  >
 
Welcome Guest#217 Login/register    Go to Bottom
Go to Top

Source for file dpserver.php

Documentation is available at dpserver.php

  1. <?php
  2. /**
  3.  * Provides 'DpServer' class to answer normal and AJAX requests from web clients
  4.  *
  5.  * DutchPIPE version 0.4; PHP version 5
  6.  *
  7.  * LICENSE: This source file is subject to version 1.0 of the DutchPIPE license.
  8.  * If you did not receive a copy of the DutchPIPE license, you can obtain one at
  9.  * http://dutchpipe.org/license/1_0.txt or by sending a note to
  10.  * license@dutchpipe.org, in which case you will be mailed a copy immediately.
  11.  *
  12.  * @package    DutchPIPE
  13.  * @subpackage lib
  14.  * @author     Lennert Stock <ls@dutchpipe.org>
  15.  * @copyright  2006, 2007 Lennert Stock
  16.  * @license    http://dutchpipe.org/license/1_0.txt  DutchPIPE License
  17.  * @version    Subversion: $Id: dpserver.php 278 2007-08-19 22:52:25Z ls $
  18.  * @link       http://dutchpipe.org/manual/package/DutchPIPE
  19.  * @see        dpclient.php, dpuniverse.php
  20.  */
  21.  
  22. /* Shows all possible errors */
  23. error_reporting(E_ALL E_STRICT);
  24.  
  25. /**
  26.  * A DutchPIPE server to answer normal and AJAX requests from web clients
  27.  *
  28.  * The DutchPIPE server which can be started and then keeps running while
  29.  * accepting socket connections. Waits for and accepts socket requests from
  30.  * users connected through dpclient.php, and returns output to dpclient.php,
  31.  * which returns it to the end user. If there are 10 users on the site, it will
  32.  * loop through the main code for each user at a time.
  33.  *
  34.  * To answer each request, the server passes the request on to the persistent
  35.  * DbUniverse object, where the real processing takes place.
  36.  *
  37.  * @package    DutchPIPE
  38.  * @subpackage lib
  39.  * @author     Lennert Stock <ls@dutchpipe.org>
  40.  * @copyright  2006, 2007 Lennert Stock
  41.  * @license    http://dutchpipe.org/license/1_0.txt  DutchPIPE License
  42.  * @version    Release: 0.2.1
  43.  * @link       http://dutchpipe.org/manual/package/DutchPIPE
  44.  * @see        dpclient.php, dpuniverse.php
  45.  */
  46. final class DpServer
  47. {
  48.     /**
  49.      * @var         resource  The socket the server has opened to a client
  50.      * @access      private
  51.      */
  52.      private $mMsgsock;
  53.  
  54.     /**
  55.      * @var         resource  Used to show server status info on the cmd line
  56.      * @access      private
  57.      */
  58.     private $mShowedStatusHeader 0;
  59.  
  60.     /**
  61.      * Used to show server status info based on getrusage, start "user" time of
  62.      * script
  63.      *
  64.      * @var         resource  Start 'user' time of script
  65.      * @access      private
  66.      */
  67.     private $mUtimeBefore;
  68.  
  69.     /**
  70.      * Used to show server status info based on getrusage, start "system" time
  71.      * of script
  72.      *
  73.      * @var         resource  Start "system" time of script
  74.      * @access      private
  75.      */
  76.     private $mStimeBefore;
  77.  
  78.     /**
  79.      * Sets up the server at object creation time based on your settings
  80.      *
  81.      * @param       string    $iniFile    Path to a dpserver-ini.php like file
  82.      */
  83.     function __construct($iniFile 'dpserver-ini.php')
  84.     {
  85.         /* Used by showStatus() further below */
  86.         if (function_exists('getrusage')) {
  87.             $rusage getrusage();
  88.             $this->mUtimeBefore = (int)$rusage["ru_utime.tv_sec"1e6 +
  89.                 (int)$rusage["ru_utime.tv_usec"];
  90.             $this->mStimeBefore = (int)$rusage["ru_stime.tv_sec"1e6 +
  91.                 (int)$rusage["ru_stime.tv_usec"];
  92.         }
  93.  
  94.         /* Get the server settings */
  95.         require_once($iniFile);
  96.  
  97.         require_once(DPSERVER_LIB_PATH 'dpmbstring_'
  98.             . (!DPSERVER_ENABLE_MBSTRING || !function_exists('mb_strlen')
  99.             ? 'disabled' 'enabled''.php');
  100.  
  101.  
  102.         ini_set('memory_limit'DPSERVER_MEMORY_LIMIT);
  103.  
  104.         /* Allow the script to hang around waiting for connections */
  105.  
  106.         /* See what we're getting as it comes in */
  107.         ob_implicit_flush();
  108.  
  109.     }
  110.  
  111.     /**
  112.      * Starts the DutchPIPE server, using a specific 'universe' object
  113.      *
  114.      * Also see: http://www.php.net/sockets
  115.      *
  116.      * @param       object    &$universe   An instance of DpUniverse
  117.      */
  118.     function runDpServer(&$universe)
  119.     {
  120.         /* Check if the server is already running */
  121.         if (file_exists(DPSERVER_SOCKET_PATH)) {
  122.             /* :KLUDGE: should be improved */
  123.             unlink(DPSERVER_SOCKET_PATH);
  124.             //die(dp_text("Cannot start server: server already running\n"));
  125.         }
  126.  
  127.         if (DPSERVER_SOCKET_TYPE === AF_UNIX{
  128.             /* Initialize the server, first create a socket */
  129.             if (FALSE === ($socket socket_create(AF_UNIXSOCK_STREAM0))) {
  130.                 die(sprintf(dp_text(
  131.                     "socket_create(): unable to create socket [%u]: %s\n"),
  132.                     socket_last_error()socket_strerror(socket_last_error())));
  133.             }
  134.  
  135.             /* Bind the socket to a file, for example /tmp/dutchpipesock */
  136.             if (FALSE === socket_bind($socketDPSERVER_SOCKET_PATH)) {
  137.                 die(sprintf(dp_text(
  138.                     "socket_bind() unable to bind socket [%u]: %s\n"),
  139.                     socket_last_error()socket_strerror(socket_last_error())));
  140.             }
  141.             if (FALSE === chmod(DPSERVER_SOCKET_PATH0777)) {
  142.                 die(sprintf(dp_text(
  143.                     "Cannot start server: reason: chmod on %s failed\n"),
  144.                     DPSERVER_SOCKET_PATH));
  145.             }
  146.         elseif (DPSERVER_SOCKET_TYPE === AF_INET{
  147.             /* Initialize the server, first create a socket */
  148.             if (FALSE === ($socket socket_create(AF_INETSOCK_STREAM,
  149.                     SOL_TCP))) {
  150.                 die(sprintf(dp_text(
  151.                     "socket_create(): unable to create socket [%u]: %s\n"),
  152.                     socket_last_error()socket_strerror(socket_last_error())));
  153.             }
  154.  
  155.             /* Reuse the port in case it was not properly closed */
  156.             socket_set_option($socketSOL_SOCKETSO_REUSEADDR1);
  157.  
  158.             /* Bind the socket to a file, for example /tmp/dutchpipesock */
  159.             if (FALSE === socket_bind($socketDPSERVER_SOCKET_ADDRESS,
  160.                     DPSERVER_SOCKET_PORT)) {
  161.                 die(sprintf(dp_text(
  162.                     "socket_bind() unable to bind socket [%u]: %s\n"),
  163.                     socket_last_error()socket_strerror(socket_last_error())));
  164.             }
  165.         else {
  166.             die(dp_text("Invalid socket protocol.\n"));
  167.         }
  168.         /* Start listening to the socket which dpclient.php talks to */
  169.         if (FALSE === socket_listen($socketDPSERVER_MAX_SOCKET_BACKLOG)) {
  170.             die(sprintf(dp_text("socket_listen(): failure [%u]: %s\n"),
  171.                 socket_last_error()socket_strerror(socket_last_error())));
  172.         }
  173.  
  174.         /* Accept connections and loop for each request */
  175.         do {
  176.             if (FALSE === ($this->mMsgsock socket_accept($socket))) {
  177.                 echo sprintf(dp_text("socket_accept(): failure [%u]: %s\n"),
  178.                     socket_last_error()socket_strerror(socket_last_error()));
  179.                 break;
  180.             }
  181.  
  182.             /*
  183.              * We got a connection with a user client through dpclient.php,
  184.              * dpclient.php should send some serialized arrays with variables.
  185.              * These are the PHP global $_SERVER, $_COOKIE, ... arrays.
  186.              * All client info, including input and AJAX parameters, are send
  187.              * through these arrays.
  188.              */
  189.             $allbuf '';
  190.             do {
  191.                 if (DPSERVER_SOCKET_TYPE === AF_UNIX{
  192.                     /* Read in what dpclient.php is telling us in chunks */
  193.                     if (FALSE === ($buf socket_read($this->mMsgsock,
  194.                             DPSERVER_SERVER_CHUNKPHP_NORMAL_READ))) {
  195.                         echo sprintf(dp_text(
  196.                             "socket_read(): failure [%u]: %s\n"),
  197.                             socket_last_error(),
  198.                             socket_strerror(socket_last_error()));
  199.                         break 2;
  200.                     }
  201.                     if (!dp_strlen($buf trim($buf))) {
  202.                         continue;
  203.                     }
  204.                     /* This can be used to shutdown the server */
  205.                     if ($buf == 'shutdown'{
  206.                         socket_close($this->mMsgsock);
  207.                         break 2;
  208.                     }
  209.  
  210.                     /*
  211.                      * Read the 2KB blocks until dpclient.php sends us a 'quit'
  212.                      */
  213.                     if ($buf <> 'quit'{
  214.                         $allbuf .= $buf;
  215.                         continue;
  216.                     }
  217.                 else {
  218.                     /* Read in what dpclient.php is telling us in chunks */
  219.                     if (FALSE === ($buf socket_read($this->mMsgsock,
  220.                             DPSERVER_SERVER_CHUNK))) {
  221.                         echo sprintf(dp_text(
  222.                             "socket_read(): failure [%u]: %s\n"),
  223.                             socket_last_error(),
  224.                             socket_strerror(socket_last_error()));
  225.                         break 2;
  226.                     }
  227.                     if (!dp_strlen($buf trim($buf))) {
  228.                         continue;
  229.                     }
  230.                     $allbuf .= $buf;
  231.                     /* This can be used to shutdown the server */
  232.                     if (dp_strlen($allbuf>= &&
  233.                             dp_substr($allbuf-7== 'shutdown'{
  234.                         socket_close($this->mMsgsock);
  235.                         break 2;
  236.                     }
  237.                     /*
  238.                      * Read the 2KB blocks until dpclient.php sends us a 'quit'
  239.                      */
  240.                     if (dp_strlen($allbuf4
  241.                             || dp_substr($allbuf-4!= 'quit'{
  242.                         continue;
  243.                     }
  244.                     //$allbuf = dp_substr($allbuf, 0, dp_strlen($allbuf - 4));
  245.                 }
  246.  
  247.                 /* Check for invalid input from dpclient.php */
  248.                 if (dp_strlen($allbuf<= 6
  249.                         || FALSE === ($pos1 dp_strpos($allbuf"<vars>"))
  250.                         || FALSE === ($pos2 dp_strpos($allbuf"</vars>"))
  251.                         || $pos2 <= $pos1 7{
  252.                     echo 'allbuf: ' $allbuf "\n";
  253.                     break;
  254.                 }
  255.  
  256.                 /*
  257.                  * Cut out and unserialize the three global PHP vars
  258.                  * dpclient.php passed on
  259.                  */
  260.                 $vars dp_substr($allbuf0$pos2);
  261.                 $vars dp_substr($vars$pos1 6);
  262.                 if (TRUE === DPSERVER_BASE64_CLIENT2SERVER{
  263.                     $vars base64_decode($vars);
  264.                 }
  265.                 $tmp unserialize($vars);
  266.  
  267.                 if (FALSE === $tmp{
  268.                     //$handle = fopen('/tmp/dpserver.log', 'a');
  269.                     //fwrite($handle, sprintf(dp_text("No unserialize: %s\n"),
  270.                     //$vars));
  271.                     //fclose($handle);
  272.                     echo sprintf(dp_text("No unserialize: %s\n")$vars);
  273.                     $__SERVER $__SESSION $__COOKIE $__GET $__POST =
  274.                         $__FILES array();
  275.                 }
  276.  
  277.                 list($__SERVER$__SESSION$__COOKIE$__GET$__POST,
  278.                     $__FILES$tmp;
  279.                 /*
  280.                  * Pass on the request to the universe object. The universe
  281.                  * object can response by calling tellCurrentDpUserRequest()
  282.                  * below
  283.                  */
  284.                 $universe->handleCurrentDpUserRequest($this$__SERVER,
  285.                     $__SESSION$__COOKIE$__GET$__POST$__FILES);
  286.  
  287.                 /*
  288.                  * :KLUDGE: Shows server status once in a while. The ticks
  289.                  * system or external cron triggered calls should be used in the
  290.                  * future
  291.                  */
  292.                 if (=== mt_rand(1$universe->getNrOfUsers())) {
  293.                     $this->_showStatus($universe);
  294.                 }
  295.                 break;
  296.             while (true);
  297.             socket_close($this->mMsgsock);
  298.         while (true);
  299.  
  300.         socket_close($sock);
  301.     }
  302.  
  303.     /**
  304.      * Closes the socket when the server is destroyed.
  305.      */
  306.     function __destruct()
  307.     {
  308.         if ($this->mMsgsock{
  309.             socket_close($this->mMsgsock);
  310.         }
  311.     }
  312.  
  313.     /**
  314.      * Tells a string to the current user request through dpclient.php
  315.      *
  316.      * Called from 'the universe' to talk back to the client, messages are
  317.      * typically XML with something like '<message>Lennert says: hi</message>'.
  318.      *
  319.      * @param       string    $talkback   String to send to current user client
  320.      */
  321.     function tellCurrentDpUserRequest($talkback)
  322.     {
  323.         if (=== dp_strlen($talkback)) {
  324.             return;
  325.         }
  326.  
  327.         if (TRUE === DPSERVER_BASE64_SERVER2CLIENT{
  328.             $talkback base64_encode($talkback);
  329.         }
  330.         $talkback .= chr(0);
  331.  
  332.         if (FALSE === socket_write($this->mMsgsock$talkback,
  333.                 dp_strlen($talkback))) {
  334.             echo sprintf(dp_text("socket_write(): failure [%u]: %s\n"),
  335.                 socket_last_error()socket_strerror(socket_last_error()));
  336.         }
  337.     }
  338.  
  339.     /**
  340.      * Shows some server info on the command line
  341.      *
  342.      * @param       object    &$universe  An instance of DpUniverse
  343.      */
  344.     private function _showStatus(&$universe)
  345.     {
  346.             $universe->showStatusMemoryGetUsage();
  347.         elseif (DPSERVER_DEBUG_TYPE_GETRUSAGE === DPSERVER_DEBUG_TYPE{
  348.             $this->_showStatusMemoryGetrusage($universe);
  349.         }
  350.     }
  351.  
  352.     /**
  353.      * Shows a line with getrusage info, see man getrusage
  354.      *
  355.      * @param       object    &$universe  An instance of DpUniverse
  356.      */
  357.     private function _showStatusMemoryGetrusage(&$universe)
  358.     {
  359.         if (!function_exists('getrusage')) {
  360.             return;
  361.         }
  362.  
  363.         $dat getrusage();
  364.  
  365.         $utime_after = (int)$dat["ru_utime.tv_sec"]*1e6 +
  366.             (int)$dat["ru_utime.tv_usec"];
  367.         $stime_after = (int)$dat["ru_stime.tv_sec"]*1e6 +
  368.             (int)$dat["ru_stime.tv_usec"];
  369.  
  370.         $dat["ru_utime"number_format(($utime_after $this->mUtimeBefore/
  371.             10000002's';
  372.         $dat["ru_stime"number_format(($stime_after $this->mStimeBefore/
  373.             10000002's';
  374.         $dat["ru_maxrss"$dat["ru_maxrss"'kb';
  375.         unset($dat['ru_oublock']);
  376.         unset($dat['ru_inblock']);
  377.         unset($dat['ru_nswap']);
  378.         unset($dat['ru_nsignals']);
  379.         unset($dat['ru_utime.tv_sec']);
  380.         unset($dat['ru_utime.tv_usec']);
  381.         unset($dat['ru_stime.tv_sec']);
  382.         unset($dat['ru_stime.tv_usec']);
  383.  
  384.         if (=== (int)$this->mShowedStatusHeader{
  385.             $keys array_keys($dat);
  386.             foreach ($keys as $i => $k{
  387.                 $keys[$idp_substr($keys[$i]3);
  388.                 if (dp_strlen($keys[$i]7{
  389.                     $keys[$idp_substr($keys[$i]07);
  390.                 }
  391.             }
  392.             $this->mShowedStatusHeader 30;
  393.  
  394.             echo sprintf(dp_text("Memory\t%s\n")implode("\t"$keys));
  395.         }
  396.  
  397.         echo sprintf(dp_text("%uKB\t%s\n")round(memory_get_usage(1024),
  398.             implode("\t"$dat));
  399.         $this->mShowedStatusHeader--;
  400.     }
  401. }
  402. ?>

Documentation generated on Mon, 03 Sep 2007 22:20:40 +0200 by phpDocumentor 1.3.0RC6

Click me!
Guest#217
 
 
 
  Go to Top
 
 
Input Field OptionsClose Input Field Go to Top
 
Legal Notices | Copyright © 2006, 2007 Lennert Stock. All rights reserved. Last update: Mon Sep 03 2007, 21:50 CET.