public function receive($fd, $data) { if (!isset($this->connections[$fd]['buff'])) { $this->connections[$fd]['buff'] = ''; } else { $data = $this->connections[$fd]['buff'] . $data; } if (!isset($this->connections[$fd]['length'])) { $pack = substr($data, 4, 3); $info = unpack('ncontentLength/CpaddingLength', $pack); $this->connections[$fd]['length'] = 8 + $info['contentLength'] + $info['paddingLength']; } if ($this->connections[$fd]['length'] <= strlen($data)) { $result = $this->parseRecord($data); $this->connections[$fd]['buff'] = $result['remainder']; $this->connections[$fd]['length'] = null; } else { $this->connections[$fd]['buff'] = $data; return; } if (count($result['records']) == 0) { fwrite(STDOUT, "Bad Request. data length: " . strlen($data)); $this->closeConnection($fd); return; } foreach ($result['records'] as $record) { $rid = $record['requestId']; $type = $record['type']; if ($type == $this->FCGI_BEGIN_REQUEST) { $req = $this->requests[$rid] = new Request($fd); $req->id = $rid; $u = unpack('nrole/Cflags', $record['contentData']); $req->attrs->role = $this->roles[$u['role']]; $req->attrs->flags = $u['flags']; $this->connections[$fd]['request'] = $req; } elseif (isset($this->requests[$rid])) { $req = $this->requests[$rid]; } else { fwrite(STDOUT, "Unexpected FastCGI-record #. Request ID: {$fd}\n"); return; } if ($type == $this->FCGI_ABORT_REQUEST) { $req->destoryTempFiles(); $this->closeConnection($fd); } elseif ($type == $this->FCGI_PARAMS) { if (!$record['contentLength']) { $req->finishParams(); } else { $p = 0; while ($p < $record['contentLength']) { if (($namelen = ord($record['contentData'][$p])) < 128) { ++$p; } else { $u = unpack('Nlen', chr(ord($record['contentData'][$p]) & 0x7f) . substr($record['contentData'], $p + 1, 3)); $namelen = $u['len']; $p += 4; } if (($vlen = ord($record['contentData'][$p])) < 128) { ++$p; } else { $u = unpack('Nlen', chr(ord($record['contentData'][$p]) & 0x7f) . substr($record['contentData'], $p + 1, 3)); $vlen = $u['len']; $p += 4; } $req->server[substr($record['contentData'], $p, $namelen)] = substr($record['contentData'], $p + $namelen, $vlen); $p += $namelen + $vlen; } } } elseif ($type === $this->FCGI_STDIN) { if ($record['contentLength']) { $req->setRawContent($record['contentData']); continue; } else { $req->finishRawContent(); } } if ($req->attrs->paramsDone && $req->attrs->inputDone) { $header = []; foreach ($req->server as $k => $v) { if (strncmp($k, 'HTTP_', 5) === 0) { $header[strtr(ucwords(strtolower(substr($k, 5)), '_'), '_', '-')] = $v; } } $req->header = $header; Parser::parseCookie($req); Parser::parseBody($req); $response = new Response($this, $req); $this->onRequest($req, $response); // destory tmp files $req->destoryTempFiles(); } } }