Skip to content

Commit

Permalink
cumulative updates from package lisachenko/protocol-fcgi
Browse files Browse the repository at this point in the history
  • Loading branch information
deminy committed Feb 16, 2024
1 parent 58e5346 commit 497bb74
Show file tree
Hide file tree
Showing 28 changed files with 225 additions and 145 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changed:
* Refactor: Rename parameter in method `\Swoole\Database\PDOStatementProxy::setFetchMode()` for consistency.
* Refactor: Rename parameter in method `\Swoole\MultibyteStringObject::substr()` for consistency.
* Refactor: Enhance method `\Swoole\FastCGI\Message::withBody()` with explicit parameter type.
* Cumulative updates from package [lisachenko/protocol-fcgi].

## 5.1.2 (2024-01-24)

Expand Down Expand Up @@ -50,3 +51,5 @@ Fixed:
## 5.0.3 (2023-04-26)

Built-in PHP library included in [Swoole v5.0.3](https://github.com/swoole/swoole-src/releases/tag/v5.0.3).

[lisachenko/protocol-fcgi]: https://github.com/lisachenko/protocol-fcgi
36 changes: 20 additions & 16 deletions src/core/FastCGI/FrameParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class FrameParser
/**
* Mapping of constants to the classes
*
* @var array
* @phpstan-var array<int, class-string>
*/
protected static $classMapping = [
protected static array $classMapping = [
FastCGI::BEGIN_REQUEST => BeginRequest::class,
FastCGI::ABORT_REQUEST => AbortRequest::class,
FastCGI::END_REQUEST => EndRequest::class,
Expand All @@ -50,17 +50,19 @@ class FrameParser

/**
* Checks if the buffer contains a valid frame to parse
*
* @param string $buffer Binary buffer
*/
public static function hasFrame(string $buffer): bool
public static function hasFrame(string $binaryBuffer): bool
{
$bufferLength = strlen($buffer);
$bufferLength = strlen($binaryBuffer);
if ($bufferLength < FastCGI::HEADER_LEN) {
return false;
}

$fastInfo = unpack(FastCGI::HEADER_FORMAT, $buffer);
/** @phpstan-var false|array{version: int, type: int, requestId: int, contentLength: int, paddingLength: int} */
$fastInfo = unpack(FastCGI::HEADER_FORMAT, $binaryBuffer);
if ($fastInfo === false) {
throw new \RuntimeException('Can not unpack data from the binary buffer');
}
if ($bufferLength < FastCGI::HEADER_LEN + $fastInfo['contentLength'] + $fastInfo['paddingLength']) {
return false;
}
Expand All @@ -71,28 +73,30 @@ public static function hasFrame(string $buffer): bool
/**
* Parses a frame from the binary buffer
*
* @param string $buffer Binary buffer
*
* @return Record One of the corresponding FastCGI record
*/
public static function parseFrame(string &$buffer): Record
public static function parseFrame(string &$binaryBuffer): Record
{
$bufferLength = strlen($buffer);
$bufferLength = strlen($binaryBuffer);
if ($bufferLength < FastCGI::HEADER_LEN) {
throw new \RuntimeException('Not enough data in the buffer to parse');
}
$recordHeader = unpack(FastCGI::HEADER_FORMAT, $buffer);
$recordType = $recordHeader['type'];
/** @phpstan-var false|array{version: int, type: int, requestId: int, contentLength: int, paddingLength: int} */
$recordHeader = unpack(FastCGI::HEADER_FORMAT, $binaryBuffer);
if ($recordHeader === false) {
throw new \RuntimeException('Can not unpack data from the binary buffer');
}
$recordType = $recordHeader['type'];
if (!isset(self::$classMapping[$recordType])) {
throw new \DomainException("Invalid FastCGI record type {$recordType} received");
}

/** @var Record $className */
$className = self::$classMapping[$recordType];
$record = $className::unpack($buffer);
$record = $className::unpack($binaryBuffer);

$offset = FastCGI::HEADER_LEN + $record->getContentLength() + $record->getPaddingLength();
$buffer = substr($buffer, $offset);
$offset = FastCGI::HEADER_LEN + $record->getContentLength() + $record->getPaddingLength();
$binaryBuffer = substr($binaryBuffer, $offset);

return $record;
}
Expand Down
31 changes: 18 additions & 13 deletions src/core/FastCGI/Record.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,27 @@ final public function __toString(): string

/**
* Unpacks the message from the binary data buffer
*
* @param string $data Binary buffer with raw data
*/
final public static function unpack(string $data): static
final public static function unpack(string $binaryData): static
{
$self = new static(); // @phpstan-ignore new.static
/** @var static $self */
$self = (new \ReflectionClass(static::class))->newInstanceWithoutConstructor();

/** @phpstan-var false|array{version: int, type: int, requestId: int, contentLength: int, paddingLength: int, reserved: int} */
$packet = unpack(FastCGI::HEADER_FORMAT, $binaryData);
if ($packet === false) {
throw new \RuntimeException('Can not unpack data from the binary buffer');
}
[
$self->version,
$self->type,
$self->requestId,
$self->contentLength,
$self->paddingLength,
$self->reserved
] = array_values(unpack(FastCGI::HEADER_FORMAT, $data));
] = array_values($packet);

$payload = substr($data, FastCGI::HEADER_LEN);
$payload = substr($binaryData, FastCGI::HEADER_LEN);
self::unpackPayload($self, $payload);
if (static::class !== self::class && $self->contentLength > 0) {
static::unpackPayload($self, $payload);
Expand Down Expand Up @@ -190,18 +195,18 @@ final public function getPaddingLength(): int
* Method to unpack the payload for the record.
*
* NB: Default implementation will be always called
*
* @param static $self Instance of current frame
* @param string $data Binary data
*/
protected static function unpackPayload($self, string $data): void
protected static function unpackPayload(self $self, string $binaryData): void
{
/** @phpstan-var false|array{contentData: string, paddingData: string} */
$payload = unpack("a{$self->contentLength}contentData/a{$self->paddingLength}paddingData", $binaryData);
if ($payload === false) {
throw new \RuntimeException('Can not unpack data from the binary buffer');
}
[
$self->contentData,
$self->paddingData
] = array_values(
unpack("a{$self->contentLength}contentData/a{$self->paddingLength}paddingData", $data)
);
] = array_values($payload);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/core/FastCGI/Record/AbortRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
class AbortRequest extends Record
{
public function __construct(int $requestId = 0)
public function __construct(int $requestId)
{
$this->type = FastCGI::ABORT_REQUEST;
$this->setRequestId($requestId);
Expand Down
23 changes: 12 additions & 11 deletions src/core/FastCGI/Record/BeginRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@ class BeginRequest extends Record
* FCGI_RESPONDER
* FCGI_AUTHORIZER
* FCGI_FILTER
*
* @var int
*/
protected $role = FastCGI::UNKNOWN_ROLE;
protected int $role = FastCGI::UNKNOWN_ROLE;

/**
* The flags component contains a bit that controls connection shutdown.
Expand All @@ -37,17 +35,13 @@ class BeginRequest extends Record
* If zero, the application closes the connection after responding to this request.
* If not zero, the application does not close the connection after responding to this request;
* the Web server retains responsibility for the connection.
*
* @var int
*/
protected $flags;
protected int $flags;

/**
* Reserved data, 5 bytes maximum
*
* @var string
*/
protected $reserved1;
protected string $reserved1;

public function __construct(int $role = FastCGI::UNKNOWN_ROLE, int $flags = 0, string $reserved = '')
{
Expand Down Expand Up @@ -91,13 +85,20 @@ public function getFlags(): int
* {@inheritdoc}
* @param static $self
*/
protected static function unpackPayload($self, string $data): void
protected static function unpackPayload($self, string $binaryData): void
{
assert($self instanceof self);

/** @phpstan-var false|array{role: int, flags: int, reserved: string} */
$payload = unpack('nrole/Cflags/a5reserved', $binaryData);
if ($payload === false) {
throw new \RuntimeException('Can not unpack data from the binary buffer');
}
[
$self->role,
$self->flags,
$self->reserved1
] = array_values(unpack('nrole/Cflags/a5reserved', $data));
] = array_values($payload);
}

/** {@inheritdoc} */
Expand Down
2 changes: 1 addition & 1 deletion src/core/FastCGI/Record/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
class Data extends Record
{
public function __construct(string $contentData = '')
public function __construct(string $contentData)
{
$this->type = FastCGI::DATA;
$this->setContentData($contentData);
Expand Down
30 changes: 14 additions & 16 deletions src/core/FastCGI/Record/EndRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ class EndRequest extends Record
{
/**
* The appStatus component is an application-level status code. Each role documents its usage of appStatus.
*
* @var int
*/
protected $appStatus = 0;
protected int $appStatus = 0;

/**
* The protocolStatus component is a protocol-level status code.
Expand All @@ -39,23 +37,16 @@ class EndRequest extends Record
* This happens when the application runs out of some resource, e.g. database connections.
* FCGI_UNKNOWN_ROLE: rejecting a new request.
* This happens when the Web server has specified a role that is unknown to the application.
*
* @var int
*/
protected $protocolStatus = FastCGI::REQUEST_COMPLETE;
protected int $protocolStatus = FastCGI::REQUEST_COMPLETE;

/**
* Reserved data, 3 bytes maximum
*
* @var string
*/
protected $reserved1;
protected string $reserved1;

public function __construct(
int $protocolStatus = FastCGI::REQUEST_COMPLETE,
int $appStatus = 0,
string $reserved = ''
) {
public function __construct(int $protocolStatus = FastCGI::REQUEST_COMPLETE, int $appStatus = 0, string $reserved = '')
{
$this->type = FastCGI::END_REQUEST;
$this->protocolStatus = $protocolStatus;
$this->appStatus = $appStatus;
Expand Down Expand Up @@ -95,13 +86,20 @@ public function getProtocolStatus(): int
* {@inheritdoc}
* @param static $self
*/
protected static function unpackPayload($self, string $data): void
protected static function unpackPayload($self, string $binaryData): void
{
assert($self instanceof self);

/** @phpstan-var false|array{appStatus: int, protocolStatus: int, reserved: string} */
$payload = unpack('NappStatus/CprotocolStatus/a3reserved', $binaryData);
if ($payload === false) {
throw new \RuntimeException('Can not unpack data from the binary buffer');
}
[
$self->appStatus,
$self->protocolStatus,
$self->reserved1
] = array_values(unpack('NappStatus/CprotocolStatus/a3reserved', $data));
] = array_values($payload);
}

/** {@inheritdoc} */
Expand Down
4 changes: 3 additions & 1 deletion src/core/FastCGI/Record/GetValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ class GetValues extends Params
* Constructs a request
*
* @param array $keys List of keys to receive
*
* @phpstan-param list<string> $keys
*/
public function __construct(array $keys = [])
public function __construct(array $keys)
{
parent::__construct(array_fill_keys($keys, ''));
$this->type = FastCGI::GET_VALUES;
Expand Down
4 changes: 3 additions & 1 deletion src/core/FastCGI/Record/GetValuesResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ class GetValuesResult extends Params
{
/**
* Constructs a param request
*
* @phpstan-param array<string, string> $values
*/
public function __construct(array $values = [])
public function __construct(array $values)
{
parent::__construct($values);
$this->type = FastCGI::GET_VALUES_RESULT;
Expand Down
Loading

0 comments on commit 497bb74

Please sign in to comment.