Skip to content

Commit

Permalink
Normalized FastCGI a bit more.
Browse files Browse the repository at this point in the history
  • Loading branch information
cubiclesoft committed Oct 5, 2018
1 parent 83175e3 commit c7ec494
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 23 deletions.
8 changes: 4 additions & 4 deletions server.php
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ function SendHTTPErrorResponse($client)
if ($client->appdata["fcgi"]["conn"]->NeedsWrite()) $writefps["fcgi_send_" . $id] = $client->appdata["fcgi"]["fp"];

$request = $client->appdata["fcgi"]["request"];
if ((!$request->stdoutcompleted || !$request->stderrcompleted) && strlen($client->writedata) + strlen($request->stdout) < 262144) $readfps["fcgi_recv_" . $id] = $client->appdata["fcgi"]["fp"];
if (($request->stdoutopen || $request->stderropen) && strlen($client->writedata) + strlen($request->stdout) < 262144) $readfps["fcgi_recv_" . $id] = $client->appdata["fcgi"]["fp"];
}

$result = @stream_select($readfps, $writefps, $exceptfps, $timeout);
Expand Down Expand Up @@ -1080,7 +1080,7 @@ function SendHTTPErrorResponse($client)
if ($result2["success"] && !$request->ended)
{
$cmd = "ProcessQueues";
$read = ((!$request->stdoutcompleted || !$request->stderrcompleted) && strlen($client->writedata) + strlen($request->stdout) < 262144);
$read = (($request->stdoutopen || $request->stderropen) && strlen($client->writedata) + strlen($request->stdout) < 262144);
$write = $client->appdata["fcgi"]["conn"]->NeedsWrite();

$result2 = $client->appdata["fcgi"]["conn"]->ProcessQueues($read, $write);
Expand Down Expand Up @@ -1153,9 +1153,9 @@ function SendHTTPErrorResponse($client)
}

// When stdout and stderr are both closed, the response is complete.
if ($request->stdoutcompleted && $request->stderrcompleted) $client->FinalizeResponse();
if (!$request->stdoutopen && !$request->stderropen) $client->FinalizeResponse();
}
else if ($request->stdoutcompleted && $request->stderrcompleted)
else if (!$request->stdoutopen && !$request->stderropen)
{
// For some reason, both stdout and stderr are closed and no headers were sent.
$request->stdout = "";
Expand Down
69 changes: 50 additions & 19 deletions support/fastcgi.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,11 @@ public function BeginRequest($role, $keepalive = true)
$request->role = (int)$role;
$request->flags = ($keepalive ? 0x01 : 0x00);
$request->stdinopen = true;
$request->stdoutopen = true;
$request->stderropen = true;
$request->dataopen = ($request->role === self::ROLE_FILTER);
$request->stdout = "";
$request->stdoutcompleted = false;
$request->stderr = "";
$request->stderrcompleted = false;
$request->ended = false;

$this->requests[$request->id] = $request;
Expand Down Expand Up @@ -260,11 +260,21 @@ public function EndRequest($requestid, $appstatus, $protocolstatus = self::PROTO
{
if ($this->fp === false) return array("success" => false, "error" => self::FCGITranslate("Connection not established."), "errorcode" => "no_connection");
if ($this->client) return array("success" => false, "error" => self::FCGITranslate("The EndRequest() function is only available in server mode."), "errorcode" => "server_mode_only");
if (isset($this->requests[$requestid]) && $this->requests[$requestid]->ended) return array("success" => false, "error" => self::FCGITranslate("The EndRequest() function has already been called for this request."), "errorcode" => "already_ended");

// 4 bytes application status, 1 byte protocol status, 3 bytes reserved.
$content = pack("N", (int)$appstatus) . chr($protocolstatus) . "\x00\x00\x00";
$this->WriteRecord(self::RECORD_TYPE_END_REQUEST, $requestid, $content);

if (isset($this->requests[$requestid]))
{
$this->requests[$requestid]->stdinopen = false;
$this->requests[$requestid]->stdoutopen = false;
$this->requests[$requestid]->stderropen = false;
$this->requests[$requestid]->dataopen = false;
$this->requests[$requestid]->ended = true;
}

return array("success" => true);
}

Expand All @@ -284,11 +294,9 @@ public function SendParams($requestid, $params)
return array("success" => true);
}

// Client only.
public function IsStdinOpen($requestid)
{
if ($this->fp === false) return false;
if (!$this->client) return false;
if (!isset($this->requests[$requestid])) return false;

return $this->requests[$requestid]->stdinopen;
Expand All @@ -315,12 +323,21 @@ public function SendStdin($requestid, $data)
return array("success" => true);
}

public function IsStdoutOpen($requestid)
{
if ($this->fp === false) return false;
if (!isset($this->requests[$requestid])) return false;

return $this->requests[$requestid]->stdoutopen;
}

// Server only.
public function SendStdout($requestid, $data)
{
if ($this->fp === false) return array("success" => false, "error" => self::FCGITranslate("Connection not established."), "errorcode" => "no_connection");
if ($this->client) return array("success" => false, "error" => self::FCGITranslate("The SendStdout() function is only available in server mode."), "errorcode" => "server_mode_only");
if (!isset($this->requests[$requestid])) return array("success" => false, "error" => self::FCGITranslate("The specified request ID does not exist."), "errorcode" => "invalid_request_id");
if (!$this->requests[$requestid]->stdoutopen) return array("success" => false, "error" => self::FCGITranslate("The specified request ID has already closed stdout."), "errorcode" => "stdout_closed");

$y = strlen($data);
for ($x = 0; $x + 65535 < $y; $x += 65535)
Expand All @@ -330,15 +347,26 @@ public function SendStdout($requestid, $data)

if ($x < $y || !$y) $this->WriteRecord(self::RECORD_TYPE_STDOUT, $requestid, (string)substr($data, $x));

if (!$y) $this->requests[$requestid]->stdoutopen = false;

return array("success" => true);
}

public function IsStderrOpen($requestid)
{
if ($this->fp === false) return false;
if (!isset($this->requests[$requestid])) return false;

return $this->requests[$requestid]->stderropen;
}

// Server only.
public function SendStderr($requestid, $data)
{
if ($this->fp === false) return array("success" => false, "error" => self::FCGITranslate("Connection not established."), "errorcode" => "no_connection");
if ($this->client) return array("success" => false, "error" => self::FCGITranslate("The SendStderr() function is only available in server mode."), "errorcode" => "server_mode_only");
if (!isset($this->requests[$requestid])) return array("success" => false, "error" => self::FCGITranslate("The specified request ID does not exist."), "errorcode" => "invalid_request_id");
if (!$this->requests[$requestid]->stderropen) return array("success" => false, "error" => self::FCGITranslate("The specified request ID has already closed stderr."), "errorcode" => "stderr_closed");

$y = strlen($data);
for ($x = 0; $x + 65535 < $y; $x += 65535)
Expand All @@ -348,14 +376,14 @@ public function SendStderr($requestid, $data)

if ($x < $y || !$y) $this->WriteRecord(self::RECORD_TYPE_STDERR, $requestid, (string)substr($data, $x));

if (!$y) $this->requests[$requestid]->stderropen = false;

return array("success" => true);
}

// Client only.
public function IsDataOpen($requestid)
{
if ($this->fp === false) return false;
if (!$this->client) return false;
if (!isset($this->requests[$requestid])) return false;

return $this->requests[$requestid]->dataopen;
Expand All @@ -367,7 +395,7 @@ public function SendData($requestid, $data)
if ($this->fp === false) return array("success" => false, "error" => self::FCGITranslate("Connection not established."), "errorcode" => "no_connection");
if (!$this->client) return array("success" => false, "error" => self::FCGITranslate("The SendStdin() function is only available in client mode."), "errorcode" => "client_mode_only");
if (!isset($this->requests[$requestid])) return array("success" => false, "error" => self::FCGITranslate("The specified request ID does not exist."), "errorcode" => "invalid_request_id");
if (!$this->requests[$requestid]->dataopen) return array("success" => false, "error" => self::FCGITranslate("The specified request ID has already closed the data channel."), "errorcode" => "data_closed");
if (!$this->requests[$requestid]->dataopen) return array("success" => false, "error" => self::FCGITranslate("The specified request ID has already closed the data channel."), "errorcode" => "data_channel_closed");

$y = strlen($data);
for ($x = 0; $x + 65535 < $y; $x += 65535)
Expand Down Expand Up @@ -549,11 +577,14 @@ protected function ProcessReadData()
$request->role = $role;
$request->flags = $flags;
$request->abort = false;
$request->stdinopen = true;
$request->stdoutopen = true;
$request->stderropen = true;
$request->dataopen = ($role === self::ROLE_FILTER);
$request->params = "";
$request->stdin = "";
$request->stdincompleted = false;
$request->data = "";
$request->datacompleted = ($role !== self::ROLE_FILTER);
$request->ended = false;

$this->requests[$request->id] = $request;
$this->readyrequests[$request->id] = true;
Expand Down Expand Up @@ -584,8 +615,8 @@ protected function ProcessReadData()

$request->stdinopen = false;
$request->dataopen = false;
$request->stdoutcompleted = true;
$request->stderrcompleted = true;
$request->stdoutopen = false;
$request->stderropen = false;
$request->ended = true;
$request->appstatus = unpack("N", substr($record["content"], 0, 4))[1];
$request->protocolstatus = ord($record["content"]{4});
Expand Down Expand Up @@ -619,9 +650,9 @@ protected function ProcessReadData()
if (!isset($this->requests[$record["reqid"]])) continue;

$request = $this->requests[$record["reqid"]];
if ($request->stdincompleted) continue;
if (!$request->stdinopen) continue;

if ($record["content"] === "") $request->stdincompleted = true;
if ($record["content"] === "") $request->stdinopen = false;
else $request->stdin .= $record["content"];

$this->readyrequests[$record["reqid"]] = true;
Expand All @@ -636,9 +667,9 @@ protected function ProcessReadData()
if (!isset($this->requests[$record["reqid"]])) continue;

$request = $this->requests[$record["reqid"]];
if ($request->stdoutcompleted || $request->ended !== false) continue;
if (!$request->stdoutopen || $request->ended) continue;

if ($record["content"] === "") $request->stdoutcompleted = true;
if ($record["content"] === "") $request->stdoutopen = false;
else $request->stdout .= $record["content"];

$this->readyrequests[$record["reqid"]] = true;
Expand All @@ -653,9 +684,9 @@ protected function ProcessReadData()
if (!isset($this->requests[$record["reqid"]])) continue;

$request = $this->requests[$record["reqid"]];
if ($request->stderrcompleted || $request->ended !== false) continue;
if (!$request->stderropen || $request->ended) continue;

if ($record["content"] === "") $request->stderrcompleted = true;
if ($record["content"] === "") $request->stderropen = false;
else $request->stderr .= $record["content"];

$this->readyrequests[$record["reqid"]] = true;
Expand All @@ -670,9 +701,9 @@ protected function ProcessReadData()
if (!isset($this->requests[$record["reqid"]])) continue;

$request = $this->requests[$record["reqid"]];
if ($request->datacompleted) continue;
if (!$request->dataopen) continue;

if ($record["content"] === "") $request->datacompleted = true;
if ($record["content"] === "") $request->dataopen = false;
else $request->data .= $record["content"];

$this->readyrequests[$record["reqid"]] = true;
Expand Down

0 comments on commit c7ec494

Please sign in to comment.