From 5c2279a544735d451ad90aa20e7015afff81aad6 Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Tue, 27 Feb 2024 00:21:54 +0100 Subject: [PATCH] make frame fromBinary public, improve docs --- README.md | 5 ++--- src/Frame/Frame.php | 2 +- src/Frame/SettingsFrame.php | 7 +++++-- src/Header/HeaderPacker.php | 17 ++++++++++++++++- src/Http2Middleware.php | 18 +++++++++++++++++- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7b2730e..1c601a2 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,9 @@ The idea is tho end up with something like this. Expect a lot to change tho. // Tradtional request handler $http = function (Psr\Http\Message\ServerRequestInterface $request, ?callable $next=null) { - $promise = new React\Promise\Promise(); - React\Loop\Loop::laterTick(function () use ($request, $promise) { + $promise = new React\Promise\Promise(function ($resolve) use ($request) { // ... - $promise->resolve($response); + $resolve($response); }); return $promise; }; diff --git a/src/Frame/Frame.php b/src/Frame/Frame.php index 79292ef..e49e1a9 100644 --- a/src/Frame/Frame.php +++ b/src/Frame/Frame.php @@ -68,7 +68,7 @@ abstract class Frame abstract public function toBinary(): string; - abstract protected function fromBinary(string $binary): void; + abstract public function fromBinary(string $binary): void; public function encodeFrame(): string { diff --git a/src/Frame/SettingsFrame.php b/src/Frame/SettingsFrame.php index bb86a52..e53b50a 100644 --- a/src/Frame/SettingsFrame.php +++ b/src/Frame/SettingsFrame.php @@ -43,9 +43,12 @@ class SettingsFrame extends Frame return $packed; } - protected function fromBinary(string $data): void + public function fromBinary(string $data): void { - + for ($n = 0; $n < strlen($data) - 3; $n = $n + 3) { + $unpacked = unpack('vsetting/Vvalue', substr($data,$n,3)); + $this->set($unpacked['setting'], $unpacked['value']); + } } } diff --git a/src/Header/HeaderPacker.php b/src/Header/HeaderPacker.php index 792bd22..511623a 100644 --- a/src/Header/HeaderPacker.php +++ b/src/Header/HeaderPacker.php @@ -86,6 +86,12 @@ class HeaderPacker if (!self::$huffman) self::$huffman = new Codec(Dictionary::createRfc7541Dictionary()); } + /** + * Pack a HeaderBag into a binary string. + * + * @param HeaderBag $headers + * @return string + */ public function packHeaders(HeaderBag $headers): string { $packed = ''; @@ -102,12 +108,19 @@ class HeaderPacker $packed .= $value; } else { // Literal + // TODO pack literal } } return $packed; } + /** + * Unpack a binary string to a HeaderBag. + * + * @param string $raw + * @return HeaderBag + */ public function unpackHeaders(string $raw): HeaderBag { $headers = new HeaderBag(); @@ -167,7 +180,9 @@ class HeaderPacker { if ($index < self::STATIC_TABLE_SIZE) return self::$staticTable[$index]; - // TODO bounds check + if ($index - self::STATIC_TABLE_SIZE >= count($this->dynamicTable)) { + // TODO throw exception + } return $this->dynamicTable[$index - self::STATIC_TABLE_SIZE]; } diff --git a/src/Http2Middleware.php b/src/Http2Middleware.php index 1c048e0..d26b406 100644 --- a/src/Http2Middleware.php +++ b/src/Http2Middleware.php @@ -22,17 +22,33 @@ class Http2Middleware public function __invoke(ServerRequestInterface $request, ?callable $next=null) { + // expect upgrade h2 for secure connections, h2c for plaintext + + // TODO handle HTTP/2 upgrade from HTTP/1.1 + // TODO handle HTTP/2 with prior knowledge } + /** + * Parse the settings frame present in the HTTP/1.1 upgrade request. + * + * @param string $settings + * @return SettingsFrame + */ private function parseSettingsFromBase64String(string $settings): SettingsFrame { $decoded = base64_decode($settings); $frame = new SettingsFrame(); - $frame->parseFrame($decoded); + $frame->fromBinary($decoded); return $frame; } + /** + * Prepare a connection for the HTTP/2 session. + * + * @param ServerRequestInterface $request + * @return Http2Connection + */ private function setupConnection(ServerRequestInterface $request): Http2Connection { $stream = new ThroughStream();