<?php
if (!defined('WS_WEB') && !@$_SERVER['REQUEST_URI'] && @$argv[1]==='--test') {
define('WS_CONSOLE',1);
define('FIFO_TEST',1);
}
require_once("WSInit.php");
if (!function_exists('mkfifo')) {
function mkfifo($name, $mode = NULL) {
if (function_exists('posix_mkfifo')) {
if ($mode===NULL) $mode= '644';
return posix_mkfifo($name, $mode);
}
system('mkfifo '.escapeshellarg($name),$code);
if ($code) {
wsfLog("mkfifo failed for $name: code $code",LL_ERROR);
return false;
}
else {
if ($mode) chmod($name,$mode);
wsfLog("created fifo $name",LL_DEBUG);
return true;
}
}
}
class FifoResponse {
var $buffer;
var $inHeader;
function FifoResponse( $buffer ) {
$this->buffer= $buffer;
$this->inHeader= true;
}
function header($h, $override=true, $code=NULL) {
if (!$this->inHeader) {
trigger_error('Header already sent!',E_USER_ERROR);
return false;
}
if ($code) fwrite($this->buffer, "Status: $code\r\n");
$h= preg_replace('!^HTTP/\d\.\d\s+!','Status: ',$h);
fwrite($this->buffer, $h . "\r\n");
wsfLog("header: $h",LL_DEBUG);
return true;
}
function write($data) {
if ($this->inHeader) {
fwrite($this->buffer, "\r\n");
$this->flush($this->buffer);
$this->inHeader= false;
}
if ($data==='' || $data===NULL || $data===false) return;
fwrite($this->buffer, $data);
}
function flush() {
fflush($this->buffer);
}
}
class FifoServer {
var $sessionBufferSize;
var $sessionBuffers;
var $fifo;
function FifoServer( $fifo ) {
$this->fifo= $fifo;
$this->sessionBufferSize= 16;
$this->sessionBuffers= array();
}
function handleRequest( $req, &$response ) {
$response->header("Status: 200 OK",true,200);
foreach ($req as $k => $v) {
$response->write("$k: $v\n");
}
}
function handleSession( $req ) {
$this->inHeader= true;
if (!is_array($req)) {
$r= array();
$req= explode('&',$req);
foreach ($req as $s) {
$s= trim($s);
$s= explode('=',$s,2);
if (!$s) continue;
$k= strtolower(urldecode($s[0]));
$v= ( sizeof($s) > 1 ? urldecode($s[1]) : true );
$r[$k]= $v;
}
$req= $r;
}
$sessionBuffer= @$req['buffer'];
if (!$sessionBuffer) {
wsfLog("missing buffer field in request!",LL_WARN);
return false;
}
$connection= @$req['connection'];
if (!$connection) $connection= 'close';
else $connection= strtolower($connection);
$bufftype= @$req['buffer-type'];
if (!$bufftype) $bufftype= 'fifo';
$separator= NULL;
if ($connection==='keep-alive') {
$separator= @$req['separator'];
if (!$separator) $separator= "======== $sessionBuffer ========";
}
if ($bufftype=='fifo') {
if (!file_exists($sessionBuffer)) {
$ok= mkfifo($sessionBuffer,0644); #FIXME: mode!
if (!$ok) {
wsfLog("unable to create session-fifo $sessionBuffer",LL_WARN);
return false;
}
else {
wsfLog("created session-fifo $sessionBuffer",LL_DEBUG);
}
}
else {
if (is_file($sessionBuffer) || is_dir($sessionBuffer) || is_link($sessionBuffer)) {
wsfLog("not a fifo: $sessionBuffer",LL_WARN);
return false;
}
else {
wsfLog("re-using session-fifo $sessionBuffer",LL_DEBUG);
}
}
}
else if (file_exists($sessionBuffer)) {
if (!is_file($sessionBuffer)) {
wsfLog("not a file: $sessionBuffer",LL_WARN);
return false;
}
else {
$sz= filesize($sessionBuffer);
if ($sz) {
wsfLog("not empty ($sz bytes): $sessionBuffer",LL_WARN);
return false;
}
else {
wsfLog("using existing session-buffer file $sessionBuffer",LL_DEBUG);
}
}
}
else {
wsfLog("using new session-buffer file $sessionBuffer",LL_DEBUG);
}
$buffer= @$this->sessionBuffers[$sessionBuffer];
if ($buffer) {
if (feof($buffer)) $buffer= NULL;
else {
wsfLog("using open handle for session-buffer $sessionBuffer",LL_DEBUG);
#move to top of cache
unset($this->sessionBuffers[$sessionBuffer]);
$this->sessionBuffers[$sessionBuffer]= $buffer;
}
}
if (!$buffer) {
$buffer= fopen($sessionBuffer, 'w');
if (!$buffer) {
wsfLog("unable to open session-buffer $sessionBuffer for writing",LL_WARN);
return false;
}
else wsfLog("open handle for session-buffer $sessionBuffer",LL_DEBUG);
}
@touch($sessionBuffer);
$response= new FifoResponse( $buffer );
$method = @$req['method'];
if ($method==='open' || $method==='ping' || $method==='close') {
wsfLog("received close signal for $sessionBuffer",LL_VERBOSE);
if ($method==='close') {
if ($connection!='destroy') $connection= 'close';
}
$response->header("Status: 200 OK",true,200,$buffer);
}
else {
$this->handleRequest($req, $response);
}
wsfLog("response complete for $sessionBuffer",LL_VERBOSE);
if ($connection=='keep-alive' && !$separator) $separator= 'close';
if ($connection=='keep-alive') {
fwrite($buffer,"\r\n$separator\r\n");
fflush($buffer);
while (sizeof($this->sessionBuffers) > ($this->sessionBufferSize - 1)) {
$k= array_keys($this->sessionBuffers);
$k= $k[0];
$v= $this->sessionBuffers[$k];
@ fclose($v); #FIXME: delete if stale...
unset($this->sessionBuffers[$k]);
}
$this->sessionBuffers[$sessionBuffer]= $buffer;
wsfLog("keeping session-buffer $sessionBuffer in keep-alive buffer",LL_DEBUG);
}
else {
fflush($buffer);
fclose($buffer);
unset($this->sessionBuffers[$sessionBuffer]);
wsfLog("closed session-buffer $sessionBuffer",LL_DEBUG);
}
if ($connection=='destroy') {
unlink($sessionBuffer);
wsfLog("deleted session-buffer $sessionBuffer",LL_VERBOSE);
}
return true;
}
function runServer() {
if (!file_exists($this->fifo)) {
$ok= mkfifo($this->fifo,0622); #FIXME: mode!
if (!$ok) {
wsfLog("unable to create server-fifo $this->fifo",LL_WARN);
return false;
}
else {
wsfLog("created server-fifo $this->fifo",LL_INFO);
}
}
$fifo= NULL;
while (true) {
wsfLog("Waiting for request...",LL_DEBUG);
$s= ( $fifo===NULL ? NULL : fgets($fifo) );
if ($s===NULL || $s===false) {
#got eof. on some systems, this happens whenever the client closes the fifo.
#so, re-open it.
if ($fifo && !feof($fifo)) continue;
if ($fifo) fclose($fifo);
wsfLog("Opening fifo {$this->fifo} (waiting for request)...", $fifo==NULL ? LL_INFO : LL_DEBUG);
$fifo= fopen($this->fifo, 'r');
if (!$fifo) {
wsfLog("unable to open server-fifo $this->fifo for reading",LL_ERROR);
return false;
}
else wsfLog("opened server-fifo $this->fifo",LL_DEBUG);
}
$s= trim($s);
if ($s==='') continue;
$this->handleSession($s);
}
@ fclose($fifo);
wsfLog("Server terminated.",LL_INFO);
}
}
if (defined('FIFO_TEST')) {
$wsgLogLevel= LL_DEBUG;
$server= new FifoServer($args[0]);
$server->runServer();
}
?>FifoServer.php
application/x-php, 9270 bytes (load raw)

