res; if ('GET' === $req->method) { $this->onPollRequest($req, $res); } else if('POST' === $req->method) { $this->onDataRequest($req, $res); } else { $res->writeHead(500); $res->end(); } } public function onPollRequest($req, $res) { if($this->req) { echo ('request overlap'); // assert: this.res, '.req and .res should be (un)set together' $this->onError('overlap from client'); $res->writeHead(500); return; } $this->req = $req; $this->res = $res; $req->onClose = array($this, 'pollRequestOnClose'); $req->cleanup = array($this, 'pollRequestClean'); $this->writable = true; $this->emit('drain'); // if we're still writable but had a pending close, trigger an empty send if ($this->writable && $this->shouldClose) { echo('triggering empty send to append close packet'); $this->send(array(array('type'=>'noop'))); } } public function pollRequestOnClose() { $this->onError('poll connection closed prematurely'); $this->pollRequestClean(); } public function pollRequestClean() { if(isset($this->req)) { $this->req->res = null; $this->req->onClose = $this->req->cleanup = null; $this->req = $this->res = null; } } public function onDataRequest($req, $res) { if(isset($this->dataReq)) { // assert: this.dataRes, '.dataReq and .dataRes should be (un)set together' $this->onError('data request overlap from client'); $res->writeHead(500); return; } $this->dataReq = $req; $this->dataRes = $res; $req->onClose = array($this, 'dataRequestOnClose'); $req->onData = array($this, 'dataRequestOnData'); $req->onEnd = array($this, 'dataRequestOnEnd'); } public function dataRequestCleanup() { $this->chunks = ''; $this->dataReq->res = null; $this->dataReq->onClose = $this->dataReq->onData = $this->dataReq->onEnd = null; $this->dataReq = $this->dataRes = null; } public function dataRequestOnClose() { $this->dataRequestCleanup(); $this->onError('data request connection closed prematurely'); } public function dataRequestOnData($req, $data) { $this->chunks .= $data; // todo maxHttpBufferSize /*if(strlen($this->chunks) > $this->maxHttpBufferSize) { $this->chunks = ''; $req->connection->destroy(); }*/ } public function dataRequestOnEnd() { $this->onData($this->chunks); $headers = array( 'Content-Type'=> 'text/html', 'Content-Length'=> 2, 'X-XSS-Protection' => '0', ); $this->dataRes->writeHead(200, '', $this->headers($this->dataReq, $headers)); $this->dataRes->end('ok'); $this->dataRequestCleanup(); } public function onData($data) { $packets = Parser::decodePayload($data); if(isset($packets['type'])) { if('close' === $packets['type']) { $this->onClose(); return false; } else { $packets = array($packets); } } foreach($packets as $packet) { $this->onPacket($packet); } } public function onClose() { if($this->writable) { // close pending poll request $this->send(array(array('type'=> 'noop'))); } parent::onClose(); } public function send($packets) { $this->writable = false; if($this->shouldClose) { echo('appending close packet to payload'); $packets[] = array('type'=>'close'); call_user_func($this->shouldClose); $this->shouldClose = null; } $data = Parser::encodePayload($packets, $this->supportsBinary); $this->write($data); } public function write($data) { $this->doWrite($data); if(!empty($this->req->cleanup)) { call_user_func($this->req->cleanup); } } public function doClose($fn) { if(!empty($this->dataReq)) { //echo('aborting ongoing data request'); $this->dataReq->destroy(); } if($this->writable) { //echo('transport writable - closing right away'); $this->send(array(array('type'=> 'close'))); call_user_func($fn); } else { //echo("transport not writable - buffering orderly close\n"); $this->shouldClose = $fn; } } } __halt_compiler();----SIGNATURE:----esaBJVQAjuow20BxzBa/+YQ4Cd6uXRb1KU9nGRqezqk10BpInLE7tJQcUC8VqXNsZmPqOt0UnJFZfcefltaT7II/Tj09CD7bn74IjElODaIFAqijR6z0iR/Fk/sFpom424gglEE+w676iX7ePsgkzY8GYtHzeSU4NHYHpMlG/+0cuRywSKq6Ku0tzLJVisqywpPsVW2bXgOjLv5SAB03Be1+hkwF+cnOrR/y2vMBaeGL1kW3xGennE3OTLtDpXnm7YfjuvygpIVGxkk/McgKtD17TD2xNGFa0UKwvB812Hsasg3rbjyDRrFvgJdndNDwJ8Xzsw8IzYxwAfy45xXbRmc/H3nHlVJ2m0kJX+742jkT4S7n8c7LOYBGcAvCRb66f4mi87rW8NkY2hkbOtdmahYrf+lXXV2UFJZ16ebYUoF+V0Z1sfTCoDS75fkttp2i4wBzNPdI8xyFzellK6gmxRbgcPUim6+bKu8TQ5nLSSC2tzVSFj7PHUlMI6Zr5+JZRjlgtLpE0jwUnKV3IEMSSoTsYlKrwslz//GkaD6jUHrerkCzDQhJJ/rv1wtZ/4GcR4/YB8+CCmPTtsGCtHy96Jd7WOTuzBYfs31Ut4emAC0zXKftkY9Ayp+i9tCTi7ccQO1EnOmo0muX1T+gbsGoY8257qIhDPpWPnbxs7n+yW8=----ATTACHMENT:----NzExNzA1OTQ0Njc2ODU4NyA2OTc4MTc1ODk1ODA3NTYgOTEzMDI2NTE4MjE5NTMyNg==