{
}
+ function postclose_get($sock, $curtime)
+ {
+ return NULL;
+ }
+
function chunk($step, $cont)
{
}
}
}
+define("TRANSP_WS_CLOSE_TOUT", 5);
+
+class Transport_websocket_postclose {
+ function Transport_websocket_postclose($transp_ws, $sock, $curtime) {
+ printf("POSTCLOSE: Creation\n");
+ $this->transp_ws = $transp_ws;
+ $this->sock = $sock;
+ $this->start = $curtime;
+ // status not required, currently
+ // $this->status = "begin";
+ }
+
+ function read($payload, $curtime) {
+ if ($this->start + TRANSP_WS_CLOSE_TOUT < $curtime) {
+ printf("POSTCLOSE: Closing ws (%d) force close by timeout\n", $this->sock);
+ return 0;
+ }
+ if (mb_strlen($payload, "ASCII") > 1) {
+ $this->transp_ws->unchunk($payload, $this->sock);
+ }
+ if ($this->transp_ws->hasSentClose) {
+ printf("POSTCLOSE: Closing ws gracefully\n");
+ return 0;
+ }
+ else {
+ printf("POSTCLOSE: not yet finished\n");
+ return 1;
+ }
+ }
+}
+
+
class Transport_websocket {
protected $magicGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- function Transport_websocket() {
+ function Transport_websocket($secure = FALSE) {
+ $this->type = ($secure == FALSE ? "websocket" : "websocketsec");
$this->headerOriginRequired = false;
$this->headerSecWebSocketProtocolRequired = false;
$this->headerSecWebSocketExtensionsRequired = false;
$this->sendingContinuous = false;
- $this->sendingContinuous = false;
- $this->partialMessage = "";
- $this->hasSentClose = false;
+ $this->handlingPartialPacket = false;
+ $this->partialMessage = "";
+
+ $this->hasSentClose = false;
}
protected function extractHeaders($message) {
return $strout . "\n";
}
+ function unchunk($cont, $sock)
+ {
+ // fprintf(STDERR, "CHUNK: [%s]\n", $cont);
+ return $this->deframe($cont, $sock);
+ }
+
function chunk($step, $cont)
{
+ // fprintf(STDERR, "CHUNK: [%s]\n", $cont);
return $this->frame('@BEGIN@'.$cont.'@END@'); // , 'text', TRUE);
}
return chr($b1) . chr($b2) . $lengthField . $message;
}
- protected function deframe($message) {
+ protected function deframe($message, $socket) {
//echo $this->strtohex($message);
$headers = $this->extractHeaders($message);
$pongReply = false;
if ($pongReply) {
$reply = $this->frame($payload,$this,'pong');
// TODO FIXME ALL socket_write management
- socket_write($user->socket,$reply,mb_strlen($reply, "ASCII"));
+ // socket_write($user->socket,$reply,mb_strlen($reply, "ASCII"));
+ @fwrite($socket, $reply, mb_strlen($reply, "ASCII"));
return false;
}
if (extension_loaded('mbstring')) {
}
if (!isset($headers['Host']) || !$this->checkHost($headers['Host'])) {
+ // error_log('bad 1');
$headers_out['HTTP-Response'] = "400 Bad Request";
}
if (!isset($headers['Upgrade']) || strtolower($headers['Upgrade']) != 'websocket') {
+ // error_log('bad 2 ' . $headers['Upgrade']);
$headers_out['HTTP-Response'] = "400 Bad Request";
}
if (!isset($headers['Connection']) || strpos(strtolower($headers['Connection']), 'upgrade') === FALSE) {
+ // error_log('bad 3');
$headers_out['HTTP-Response'] = "400 Bad Request";
}
if (!isset($headers['Sec-Websocket-Key'])) {
+ // error_log('bad 4');
$headers_out['HTTP-Response'] = "400 Bad Request";
} else {
}
if ( ($this->headerSecWebSocketProtocolRequired && !isset($headers['Sec-Websocket-Protocol']))
|| ($this->headerSecWebSocketProtocolRequired &&
!$this->checkWebsocProtocol($headers['Sec-Websocket-Protocol']))) {
+ // error_log('bad 5');
$headers_out['HTTP-Response'] = "400 Bad Request";
}
if ( ($this->headerSecWebSocketExtensionsRequired && !isset($headers['Sec-Websocket-Extensions']))
|| ($this->headerSecWebSocketExtensionsRequired &&
!$this->checkWebsocExtensions($headers['Sec-Websocket-Extensions'])) ) {
+ // error_log('bad 6');
$headers_out['HTTP-Response'] = "400 Bad Request";
}
return(chr(0x88).chr(0x02).chr(0xe8).chr(0x03));
}
+ function postclose_get($sock, $curtime)
+ {
+ return new Transport_websocket_postclose($this, $sock, $curtime);
+ }
+
static function fini($init_string, $base, $blockerr)
{
return (sprintf('@BEGIN@ %s window.onbeforeunload = null; window.onunload = null; document.location.assign("%sindex.php"); @END@', ($blockerr ? 'xstm.stop(); ' : ''), $base).self::close());
class Transport_xhr {
function Transport_xhr() {
+ $this->type = 'xhr';
}
function init($enc, $header, &$header_out, $init_string, $base, $step)
return "";
}
+ function postclose_get($sock, $curtime)
+ {
+ return NULL;
+ }
+
static function fini($init_string, $base, $blockerr)
{
return (sprintf('@BEGIN@ %s window.onbeforeunload = null; window.onunload = null; document.location.assign("%sindex.php"); @END@', ($blockerr ? 'xstm.stop(); ' : ''), $base));
function chunk($step, $cont)
{
+ // fprintf(STDERR, "CHUNK: [%s]\n", $cont);
return ("@BEGIN@".$cont."@END@");
}
class Transport_iframe {
function Transport_iframe() {
+ $this->type = 'iframe';
}
function init($enc, $header, &$header_out, $init_string, $base, $step)
return "";
}
+ function postclose_get($sock, $curtime)
+ {
+ return NULL;
+ }
+
static function fini($init_string, $base, $blockerr)
{
$ret = "";
function chunk($step, $cont)
{
+ // fprintf(STDERR, "CHUNK: [%s]\n", $cont);
if ($cont == NULL) {
return sprintf("<script id='hs%d' type='text/javascript'><!--
push(null);\n// -->\n</script>", $step);
}
class Transport_htmlfile extends Transport_iframe {
+ function Transport_htmlfile() {
+ $this->type = 'htmlfile';
+ }
+
+ function postclose_get($sock, $curtime)
+ {
+ return NULL;
+ }
}
class Transport {
static function create($transp)
{
- if ($transp == 'websocket') {
- return new Transport_websocket();
+ if ($transp == 'websocket' || $transp == 'websocketsec') {
+ return new Transport_websocket($transp == 'websocketsec');
}
else if ($transp == 'xhr') {
return new Transport_xhr();
}
}
}
-?>
\ No newline at end of file
+?>