Thread: [Phpfwconfsys-submits] Daemon-Alpha DaemonSession.Class.php,NONE,1.1 Config.php,1.3,1.4 Daemon.Class
Status: Planning
Brought to you by:
piotrbanasik
From: <pio...@us...> - 2003-01-08 02:50:57
|
Update of /cvsroot/phpfwconfsys/Daemon-Alpha In directory sc8-pr-cvs1:/tmp/cvs-serv379 Modified Files: Config.php Daemon.Class.php Server.Class.php Socket.Class.php Added Files: DaemonSession.Class.php Log Message: - split the Session handling to a new class - added ability to register signal handers in the Server class - SIGUSR1 now gracefuly kills a child - children should not bail on a sys call interrupted error (since its necesary to interrupt the sys calls in order to get signal handlers to work) - basic structure in place to handle xml sessions --- NEW FILE: DaemonSession.Class.php --- <?php /* Error Codes: 100 - Invalid Session Start Tag 101 - Start/End Tag Mismatch 102 - Invalid Element 200 - XML Parse Error */ // the class responsible for the actual management of the transactions between the // server and the client class DaemonSession { var $Socket; var $Daemon; var $XMLParser; var $State; var $Error = false; var $ElementStack = array(); var $ClientElementStack = array(); var $CharData = ""; function DaemonSession(&$daemon, &$sock) { $this->Socket =& $sock; $this->Daemon =& $daemon; $this->XMLParser = xml_parser_create(); xml_set_object($this->XMLParser, $this); xml_set_element_handler($this->XMLParser,"Handle_StartElement","Handle_EndElement"); xml_set_character_data_handler($this->XMLParser,"Handle_CharData"); $this->State = "none"; } function SocketWrite($msg) { $r = $this->Socket->Write($msg); if ($r === false) $this->Error = true; } function SocketError($msg) { dprint("DaemonSession::SocketError($msg)"); dprint("Msg: $msg"); $this->Socket->Close(); $this->Daemon->Active = false; } function CloseClientStack() { foreach($this->ClientElementStack as $e) { $this->SocketWrite("</$e>\n"); } } function XMLError() { dprint("DaemonSession::XMLError()"); $s = sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($this->XMLParser)), xml_get_current_line_number($this->XMLParser)); $this->SendToClient("Error",$s,array( id=>200 )); dprint($s); } function RcvData($data) { $r = xml_parse($this->XMLParser,$data); if (!$r) { $this->XMLError(); return false; } if ($this->Error) { return false; } return true; } function EndOfData() { $r = xml_parse($this->XMLParser,"",true); if (!$r) $this->XMLError(); } function Handle_CharData($parser, $data) { $this->CharData .= $data; } function SendToClient($element, $data="", $args=array()) { dprint("DaemonSession::SendToClient($element, $data, $args)"); print_r($args); $shorttag = ($data=="")?true:false; $out = "<".strtoupper($element)." "; foreach ($args as $k=>$v) { $out .= "$k=\"$v\" "; } if ($shorttag) { $out .= "/>\n"; } else { $out .= ">"; $out .= $data; $out .= "</".strtoupper($element).">\n"; } $this->SocketWrite($out); dprint("Sent:\n$out"); } function Handle_StartElement($parser, $name, $attrs) { dprint("Daemon::StartElement($parser, $name, $attrs)"); print_r($attrs); while($once = true) { $once = false; if (count($this->ElementStack) == 0) { // first element // open a client session tag on the client side $this->SocketWrite("<CLIENTSESSION>\n"); array_push($this->ClientElementStack,"CLIENTSESSION"); // make sure its SESSION if ($name == "SESSION") { $this->SendToClient("Message","\nAvailible Commands: shutdown, quit, echo\n"); } else { $this->SendToClient("Error","Invalid Session Start Tag", array( id=>100 )); $this->Error = true; } break; } if ($this->ElementStack[0] == "SESSION") { if ($name == "ECHO") { $this->ChatData = ""; } else if ($name == "SHUTDOWN") { } else if ($name == "QUIT") { } else { $this->SendToClient("Error","Invalid Element", array( id=>102 )); $this->Error = true; return; } break; } } array_push($this->ElementStack,$name); dprint("ElementStack: ".implode(", ",$this->ElementStack)); } function Handle_EndElement($parser, $name) { dprint("Daemon::EndElement($parser, $name)"); dprint("ElementStack: ".implode(", ",$this->ElementStack)); $last = array_pop($this->ElementStack); if ($last != $name) { // mismatched start/end tags $this->SendToClient("Error","Mismatched Start/End Element Tags", array( id=>101 )); $this->Error = true; return; } $LastIndex = count($this->ElementStack)-1; dprint("LastIndex: $LastIndex"); if ($LastIndex == -1) { // document element closed .. tell the parser its the end too xml_parse($this->XMLParser,"",true); } if (($LastIndex == 0) && ($this->ElementStack[0] == "SESSION")) { // valid place for elements rooting from session to end if ($name == "ECHO") { $this->SendToClient("Reply",$this->CharData); } if ($name == "QUIT") { $this->Daemon->Active = false; } if ($name == "SHUTDOWN") { posix_kill(posix_getppid(),SIGTERM); } } } function Close() { $this->CloseClientStack(); xml_parser_free($this->XMLParser); } } ?> Index: Config.php =================================================================== RCS file: /cvsroot/phpfwconfsys/Daemon-Alpha/Config.php,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Config.php 7 Jan 2003 13:31:19 -0000 1.3 --- Config.php 8 Jan 2003 02:50:54 -0000 1.4 *************** *** 17,21 **** "Port" => -1, // TCP Port to bind to (ignored when domain is AF_UNIX) "Address" => "/tmp/._phpFWConfigDaemon_", // the IP or path (in case of AF_UNIX) to bind to ! "PreforkCount" => 10 // number of processes to fork and maintain ); --- 17,21 ---- "Port" => -1, // TCP Port to bind to (ignored when domain is AF_UNIX) "Address" => "/tmp/._phpFWConfigDaemon_", // the IP or path (in case of AF_UNIX) to bind to ! "PreforkCount" => 1 // number of processes to fork and maintain ); Index: Daemon.Class.php =================================================================== RCS file: /cvsroot/phpfwconfsys/Daemon-Alpha/Daemon.Class.php,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Daemon.Class.php 7 Jan 2003 13:31:19 -0000 1.1 --- Daemon.Class.php 8 Jan 2003 02:50:54 -0000 1.2 *************** *** 7,10 **** --- 7,11 ---- include_once("SocketClone.Class.php"); include_once("Server.Class.php"); + include_once("DaemonSession.Class.php"); class Daemon *************** *** 13,18 **** var $Server; var $DaemonSettings; - var $CharData = ""; var $ChildSock; function Daemon($settings) --- 14,19 ---- var $Server; var $DaemonSettings; var $ChildSock; + var $Session; function Daemon($settings) *************** *** 55,128 **** } ! function Handle_CharData($parser, $data) ! { ! $this->CharData .= $data; ! } ! ! function Handle_StartElement($parser, $name, $attrs) ! { ! dprint("Daemon::StartElement($parser, $name, $attrs)"); ! print_r($attrs); ! ! if ($name == "ECHO") { ! xml_set_character_data_handler($parser,"Handle_CharData"); ! $this->CharData = ""; ! } ! ! } ! ! function Handle_EndElement($parser, $name) { ! dprint("Daemon::EndElement($parser, $name)"); ! if ($name == "SHUTDOWN") { ! posix_kill(posix_getppid(),SIGTERM); ! } ! if ($name == "QUIT") { ! $this->Active = false; ! } ! if ($name == "ECHO") { ! xml_set_character_data_handler($parser,""); ! $this->ChildSock->Write("<Result>".$this->CharData."</Result>"); ! } } function HandleConnection($Sock) { $this->ChildSock =& $Sock; - $XML = xml_parser_create(); - xml_set_object($XML,$this); - xml_set_element_handler($XML,"Handle_StartElement","Handle_EndElement"); - - $msg = "<Greeting>\nAvailible Commands: shutdown, quit, echo\n</Greeting>\n"; - $r = $Sock->Write($msg); - if ($r === false) { $Sock->Close(); return false; } $this->Active = true; while ($this->Active) { $len = $Sock->Read(2048, $buf); // Error Occured ! if ($len === false) { xml_parser_free($XML); return false; } // End of Communication if ($len == 0) { ! xml_parse($XML,"",true); break; } echo "Client: $buf"; ! $r = xml_parse($XML,$buf); if (!$r) { ! $s = sprintf("XML error: %s at line %d", ! xml_error_string(xml_get_error_code($XML)), ! xml_get_current_line_number($XML)); ! $e = "<Error>$s</Error>"; ! $Sock->Write($e); ! dprint($s); break; } } ! xml_parser_free($XML); return true; } --- 56,109 ---- } ! function Hook_SIGUSR1() { ! dprint("Daemon::Hook_SIGUSR1()"); ! $this->Active = false; } function HandleConnection($Sock) { + dprint("Daemon::HandleConnection(&$Sock)"); $this->ChildSock =& $Sock; $this->Active = true; + $this->Session = new DaemonSession(&$this, &$Sock); + + $this->Server->AddHook(SIGUSR1,array(&$this,"Hook_SIGUSR1")); while ($this->Active) { $len = $Sock->Read(2048, $buf); + $errno = $Sock->GetLastErrorNumber(); + // Error Occured ! if ( $len == false ) { ! $errno = $Sock->GetLastErrorNumber(); ! if ($errno != 4) { ! // ignoring error 4 (interrupted system call) ! $this->Session->Close(); ! return false; ! } else { ! $len = -1; ! $buf = ""; ! } ! } // End of Communication if ($len == 0) { ! // end of communication ! $this->Session->EndOfData(); break; } echo "Client: $buf"; ! ! $r = $this->Session->RcvData($buf); if (!$r) { ! dprint("Session->RcvData() failed!"); break; } } ! $this->Session->Close(); return true; } Index: Server.Class.php =================================================================== RCS file: /cvsroot/phpfwconfsys/Daemon-Alpha/Server.Class.php,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Server.Class.php 7 Jan 2003 13:31:19 -0000 1.2 --- Server.Class.php 8 Jan 2003 02:50:54 -0000 1.3 *************** *** 13,16 **** --- 13,17 ---- var $Running = true; var $ChildSock = null; + var $SIGNALHooks = array(); function Server($socket, &$handler, $prefork=10) *************** *** 41,44 **** --- 42,57 ---- } + function AddHook($sig, $handler) + { + @$this->SIGNALHooks[$sig] = $handler; + } + + function RemoveHook($sig) + { + if (isset($this->SIGNALHooks[$sig])) { + $this->SIGNALHooks[$sig] = null; + } + } + function Sentinel() { *************** *** 88,91 **** --- 101,121 ---- } break; + case SIGUSR1: + // graceful shutdown + break; + } + if (isset($this->SIGNALHooks[$sig])) { + $handler =& $this->SIGNALHooks[$sig]; + // call the hook + if (is_array($handler)) { + // object ref + $obj = &$handler[0]; + $func = $handler[1]; + $obj->$func(); + } else { + $func = $handler; + $func(); + } + } } *************** *** 107,110 **** --- 137,142 ---- dprint("Installing Child SIGTERM Handler..."); pcntl_signal(SIGTERM,array(&$this,"Child_Handler"),false); + dprint("Installing Child SIGUSR1 Handler..."); + pcntl_signal(SIGUSR1,array(&$this,"Child_Handler"),false); $this->StartListen(); *************** *** 182,186 **** dprint("Server::Shutdown()"); $this->Running = false; ! $this->KillChildren(SIGTERM,true); } --- 214,218 ---- dprint("Server::Shutdown()"); $this->Running = false; ! $this->KillChildren(SIGUSR1,true); } Index: Socket.Class.php =================================================================== RCS file: /cvsroot/phpfwconfsys/Daemon-Alpha/Socket.Class.php,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Socket.Class.php 7 Jan 2003 13:31:19 -0000 1.2 --- Socket.Class.php 8 Jan 2003 02:50:54 -0000 1.3 *************** *** 39,42 **** --- 39,48 ---- } + function GetLastErrorNumber() + { + $errno = socket_last_error($this->Socket); + return $errno; + } + function Bind($address, $port = -1) { |