public function onRead()
{
start:
if ($this->state === self::STATE_ROOT) {
$header = $this->readExact(8);
if ($header === false) {
return;
}
$this->header = unpack('Cver/Ctype/nreqid/nconlen/Cpadlen/Creserved', $header);
if ($this->header['conlen'] > 0) {
$this->setWatermark($this->header['conlen'], $this->header['conlen']);
}
$type = $this->header['type'];
$this->header['ttype'] = isset(self::$requestTypes[$type]) ? self::$requestTypes[$type] : $type;
$rid = $this->header['reqid'];
$this->state = self::STATE_CONTENT;
} else {
$type = $this->header['type'];
$rid = $this->header['reqid'];
}
if ($this->state === self::STATE_CONTENT) {
$this->content = $this->readExact($this->header['conlen']);
if ($this->content === false) {
$this->setWatermark($this->header['conlen'], $this->header['conlen']);
return;
}
if ($this->header['padlen'] > 0) {
$this->setWatermark($this->header['padlen'], $this->header['padlen']);
}
$this->state = self::STATE_PADDING;
}
if ($this->state === self::STATE_PADDING) {
$pad = $this->readExact($this->header['padlen']);
if ($pad === false) {
return;
}
}
$this->setWatermark(8, 0xffffff);
$this->state = self::STATE_ROOT;
// /*Daemon::log('[DEBUG] FastCGI-record ' . $this->header['ttype'] . '). Request ID: ' . $rid
// . '. Content length: ' . $this->header['conlen'] . ' (' . mb_orig_strlen($this->content) . ') Padding length: ' . $this->header['padlen']
// . ' (' . mb_orig_strlen($pad) . ')');*/
if ($type === self::FCGI_BEGIN_REQUEST) {
$u = unpack('nrole/Cflags', $this->content);
$req = new \stdClass();
$req->attrs = new \stdClass();
$req->attrs->request = [];
$req->attrs->get = [];
$req->attrs->post = [];
$req->attrs->cookie = [];
$req->attrs->server = [];
$req->attrs->files = [];
$req->attrs->session = null;
$req->attrs->role = self::$roles[$u['role']];
$req->attrs->flags = $u['flags'];
$req->attrs->id = $this->header['reqid'];
$req->attrs->paramsDone = false;
$req->attrs->inputDone = false;
$req->attrs->input = new \PHPDaemon\HTTPRequest\Input();
$req->attrs->chunked = false;
$req->attrs->noHttpVer = true;
$req->queueId = $rid;
$this->requests[$rid] = $req;
} elseif (isset($this->requests[$rid])) {
$req = $this->requests[$rid];
} else {
Daemon::log('Unexpected FastCGI-record #' . $this->header['type'] . ' (' . $this->header['ttype'] . '). Request ID: ' . $rid . '.');
return;
}
if ($type === self::FCGI_ABORT_REQUEST) {
$req->abort();
} elseif ($type === self::FCGI_PARAMS) {
if ($this->content === '') {
if (!isset($req->attrs->server['REQUEST_TIME'])) {
$req->attrs->server['REQUEST_TIME'] = time();
}
if (!isset($req->attrs->server['REQUEST_TIME_FLOAT'])) {
$req->attrs->server['REQUEST_TIME_FLOAT'] = microtime(true);
}
$req->attrs->paramsDone = true;
$req = Daemon::$appResolver->getRequest($req, $this);
if ($req instanceof \stdClass) {
$this->endRequest($req, 0, 0);
unset($this->requests[$rid]);
} else {
if ($this->pool->config->sendfile->value && (!$this->pool->config->sendfileonlybycommand->value || isset($req->attrs->server['USE_SENDFILE'])) && !isset($req->attrs->server['DONT_USE_SENDFILE'])) {
$fn = tempnam($this->pool->config->sendfiledir->value, $this->pool->config->sendfileprefix->value);
$req->sendfp = fopen($fn, 'wb');
$req->header('X-Sendfile: ' . $fn);
}
$this->requests[$rid] = $req;
$req->callInit();
}
} else {
$p = 0;
while ($p < $this->header['conlen']) {
if (($namelen = ord($this->content[$p])) < 128) {
++$p;
} else {
$u = unpack('Nlen', chr(ord($this->content[$p]) & 0x7f) . mb_orig_substr($this->content, $p + 1, 3));
$namelen = $u['len'];
$p += 4;
}
if (($vlen = ord($this->content[$p])) < 128) {
++$p;
} else {
$u = unpack('Nlen', chr(ord($this->content[$p]) & 0x7f) . mb_orig_substr($this->content, $p + 1, 3));
$vlen = $u['len'];
$p += 4;
}
$req->attrs->server[mb_orig_substr($this->content, $p, $namelen)] = mb_orig_substr($this->content, $p + $namelen, $vlen);
$p += $namelen + $vlen;
}
}
} elseif ($type === self::FCGI_STDIN) {
if (!$req->attrs->input) {
goto start;
}
if ($this->content === '') {
$req->attrs->input->sendEOF();
} else {
$req->attrs->input->readFromString($this->content);
}
}
if ($req->attrs->inputDone && $req->attrs->paramsDone) {
$order = $this->pool->variablesOrder ?: 'GPC';
for ($i = 0, $s = mb_orig_strlen($order); $i < $s; ++$i) {
$char = $order[$i];
if ($char === 'G' && is_array($req->attrs->get)) {
$req->attrs->request += $req->attrs->get;
} elseif ($char === 'P' && is_array($req->attrs->post)) {
$req->attrs->request += $req->attrs->post;
} elseif ($char === 'C' && is_array($req->attrs->cookie)) {
$req->attrs->request += $req->attrs->cookie;
}
}
Daemon::$process->timeLastActivity = time();
}
goto start;
}