[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)
{
|