저자: Vasily Zorin (maintainer@daemon.io)
상속: extends PHPDaemon\Request\Generic, use trait PHPDaemon\Traits\DeferredEventHandlers, use trait PHPDaemon\Traits\Sessions
예제 #1
0
 /**
  * Constructor
  * @param WakePHP $appInstance
  * @param IRequestUpstream $upstream.
  * @param $parent
  * @return \WakePHP\Core\Request
  */
 public function __construct($appInstance, $upstream, $parent = null)
 {
     if (self::$emulMode) {
         return;
     }
     parent::__construct($appInstance, $upstream, $parent);
 }
예제 #2
0
 /**
  * __construct
  * @param Application $appInstance [@todo description]
  * @param string $id [@todo description]
  * @param array $server [@todo description]
  * @return void
  */
 public function __construct($appInstance, $id, $server)
 {
     $this->onWrite = new StackCallbacks();
     $this->id = $id;
     $this->appInstance = $appInstance;
     $this->server = $server;
     if (isset($this->server['HTTP_COOKIE'])) {
         Generic::parseStr(strtr($this->server['HTTP_COOKIE'], Generic::$hvaltr), $this->cookie);
     }
     if (isset($this->server['QUERY_STRING'])) {
         Generic::parseStr($this->server['QUERY_STRING'], $this->get);
     }
     $this->addr = $server['REMOTE_ADDR'];
     $this->finishTimer = setTimeout(function ($timer) {
         $this->finish();
     }, $this->timeout * 1000000.0);
     $this->appInstance->subscribe('c2s:' . $this->id, [$this, 'c2s']);
     $this->appInstance->subscribe('poll:' . $this->id, [$this, 'poll'], function ($redis) {
         $this->appInstance->publish('state:' . $this->id, 'started', function ($redis) {
             // @TODO: remove this callback
         });
     });
 }
예제 #3
0
 /**
  * Process headers
  * @return bool
  */
 protected function httpProcessHeaders()
 {
     $this->state = self::STATE_PREHANDSHAKE;
     if (isset($this->server['HTTP_SEC_WEBSOCKET_EXTENSIONS'])) {
         $str = strtolower($this->server['HTTP_SEC_WEBSOCKET_EXTENSIONS']);
         $str = preg_replace($this->extensionsCleanRegex, '', $str);
         $this->extensions = explode(', ', $str);
     }
     if (!isset($this->server['HTTP_CONNECTION']) || !preg_match('~(?:^|\\W)Upgrade(?:\\W|$)~i', $this->server['HTTP_CONNECTION']) || !isset($this->server['HTTP_UPGRADE']) || strtolower($this->server['HTTP_UPGRADE']) !== 'websocket') {
         $this->finish();
         return false;
     }
     if (isset($this->server['HTTP_COOKIE'])) {
         Generic::parse_str(strtr($this->server['HTTP_COOKIE'], Generic::$hvaltr), $this->cookie);
     }
     if (isset($this->server['QUERY_STRING'])) {
         Generic::parse_str($this->server['QUERY_STRING'], $this->get);
     }
     // ----------------------------------------------------------
     // Protocol discovery, based on HTTP headers...
     // ----------------------------------------------------------
     if (isset($this->server['HTTP_SEC_WEBSOCKET_VERSION'])) {
         // HYBI
         if ($this->server['HTTP_SEC_WEBSOCKET_VERSION'] === '8') {
             // Version 8 (FF7, Chrome14)
             $this->protocol = new ProtocolV13($this);
         } elseif ($this->server['HTTP_SEC_WEBSOCKET_VERSION'] === '13') {
             // newest protocol
             $this->protocol = new ProtocolV13($this);
         } else {
             Daemon::$process->log(get_class($this) . '::' . __METHOD__ . " : Websocket protocol version " . $this->server['HTTP_SEC_WEBSOCKET_VERSION'] . ' is not yet supported for client "' . $this->addr . '"');
             $this->finish();
             return false;
         }
     } elseif (!isset($this->server['HTTP_SEC_WEBSOCKET_KEY1']) || !isset($this->server['HTTP_SEC_WEBSOCKET_KEY2'])) {
         $this->protocol = new ProtocolVE($this);
     } else {
         // Defaulting to HIXIE (Safari5 and many non-browser clients...)
         $this->protocol = new ProtocolV0($this);
     }
     // ----------------------------------------------------------
     // End of protocol discovery
     // ----------------------------------------------------------
     return true;
 }
예제 #4
0
 /**
  * Parses multipart
  * @return void
  */
 public function parseMultipart()
 {
     start:
     if ($this->frozen) {
         return;
     }
     if ($this->state === self::STATE_SEEKBOUNDARY) {
         // seek to the nearest boundary
         if (($p = $this->search('--' . $this->boundary . "\r\n")) === false) {
             return;
         }
         // we have found the nearest boundary at position $p
         if ($p > 0) {
             $extra = $this->read($p);
             if ($extra !== "\r\n") {
                 $this->log('parseBody(): SEEKBOUNDARY: got unexpected data before boundary (length = ' . $p . '): ' . Debug::exportBytes($extra));
             }
         }
         $this->drain(strlen($this->boundary) + 4);
         // drain
         $this->state = self::STATE_HEADERS;
     }
     if ($this->state === self::STATE_HEADERS) {
         // parse the part's headers
         $this->curPartDisp = false;
         $i = 0;
         do {
             $l = $this->readline(\EventBuffer::EOL_CRLF);
             if ($l === null) {
                 return;
             }
             if ($l === '') {
                 break;
             }
             $e = explode(':', $l, 2);
             $e[0] = strtr(strtoupper($e[0]), Generic::$htr);
             if (isset($e[1])) {
                 $e[1] = ltrim($e[1]);
             }
             if ($e[0] === 'CONTENT_DISPOSITION' && isset($e[1])) {
                 Generic::parse_str($e[1], $this->curPartDisp, true);
                 if (!isset($this->curPartDisp['form-data'])) {
                     break;
                 }
                 if (!isset($this->curPartDisp['name'])) {
                     break;
                 }
                 $this->curPartDisp['name'] = trim($this->curPartDisp['name'], '"');
                 $name = $this->curPartDisp['name'];
                 if (isset($this->curPartDisp['filename'])) {
                     $this->curPartDisp['filename'] = trim($this->curPartDisp['filename'], '"');
                     if (!ini_get('file_uploads')) {
                         break;
                     }
                     $this->req->attrs->files[$name] = ['name' => $this->curPartDisp['filename'], 'type' => '', 'tmp_name' => null, 'fp' => null, 'error' => UPLOAD_ERR_OK, 'size' => 0];
                     $this->curPart =& $this->req->attrs->files[$name];
                     $this->req->onUploadFileStart($this);
                     $this->state = self::STATE_UPLOAD;
                 } else {
                     $this->curPart =& $this->req->attrs->post[$name];
                     $this->curPart = '';
                 }
             } elseif ($e[0] === 'CONTENT_TYPE' && isset($e[1])) {
                 if (isset($this->curPartDisp['name']) && isset($this->curPartDisp['filename'])) {
                     $this->curPart['type'] = $e[1];
                 }
             }
         } while ($i++ < 10);
         if ($this->state === self::STATE_HEADERS) {
             $this->state = self::STATE_BODY;
         }
         goto start;
     }
     if ($this->state === self::STATE_BODY || $this->state === self::STATE_UPLOAD) {
         // process the body
         $chunkEnd1 = $this->search("\r\n--" . $this->boundary . "\r\n");
         $chunkEnd2 = $this->search("\r\n--" . $this->boundary . "--\r\n");
         if ($chunkEnd1 === false && $chunkEnd2 === false) {
             /*  we have only piece of Part in buffer */
             $l = $this->length - strlen($this->boundary) - 8;
             if ($l <= 0) {
                 return;
             }
             if ($this->state === self::STATE_BODY && isset($this->curPartDisp['name'])) {
                 $this->curPart .= $this->read($l);
             } elseif ($this->state === self::STATE_UPLOAD && isset($this->curPartDisp['filename'])) {
                 $this->curPart['size'] += $l;
                 if ($this->req->getUploadMaxSize() < $this->curPart['size']) {
                     $this->curPart['error'] = UPLOAD_ERR_INI_SIZE;
                     $this->req->header('413 Request Entity Too Large');
                     $this->req->out('');
                     $this->req->finish();
                 } elseif ($this->maxFileSize && $this->maxFileSize < $this->curPart['size']) {
                     $this->curPart['error'] = UPLOAD_ERR_FORM_SIZE;
                     $this->req->header('413 Request Entity Too Large');
                     $this->req->out('');
                     $this->req->finish();
                 } else {
                     $this->curChunkSize = $l;
                     $this->req->onUploadFileChunk($this);
                 }
             }
         } else {
             /* we have entire Part in buffer */
             if ($chunkEnd1 === false) {
                 $l = $chunkEnd2;
                 $endOfMsg = true;
             } else {
                 $l = $chunkEnd1;
                 $endOfMsg = false;
             }
             if ($this->state === self::STATE_BODY && isset($this->curPartDisp['name'])) {
                 $this->curPart .= $this->read($l);
                 if ($this->curPartDisp['name'] === 'MAX_FILE_SIZE') {
                     $this->maxFileSize = (int) $this->curPart;
                 }
             } elseif ($this->state === self::STATE_UPLOAD && isset($this->curPartDisp['filename'])) {
                 $this->curPart['size'] += $l;
                 $this->curChunkSize = $l;
                 $this->req->onUploadFileChunk($this, true);
             }
             $this->state = self::STATE_SEEKBOUNDARY;
             if ($endOfMsg) {
                 // end of whole message
                 $this->sendEOF();
             } else {
                 goto start;
                 // let's read the next part
             }
         }
     }
 }
예제 #5
0
 /**
  * On finish
  * @return void
  */
 public function onFinish()
 {
     $this->appInstance->unsubscribe('s2c:' . $this->sessId, [$this, 's2c']);
     $this->appInstance->unsubscribe('w8in:' . $this->sessId, [$this, 'w8in']);
     Timer::remove($this->heartbeatTimer);
     if ($this->heartbeatOnFinish) {
         $this->sendFrame('h');
     }
     parent::onFinish();
 }
예제 #6
0
 /**
  * Get cookie by name
  * @param  string $name Name of cookie
  * @return string       Contents
  */
 protected function getCookieStr($name)
 {
     return \PHPDaemon\HTTPRequest\Generic::getString($this->attrs->cookie[$name]);
 }