Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Last active July 21, 2024 22:39
Show Gist options
  • Save masakielastic/924f750722ad06a25363735b48094fb2 to your computer and use it in GitHub Desktop.
Save masakielastic/924f750722ad06a25363735b48094fb2 to your computer and use it in GitHub Desktop.
HTTP/2 Frame Iterater
<?php
require 'H2FrameIter.php';
require 'h2testdata.php';
$chunk = h2_server_frame();
$iter = H2FrameIter($chunk);
$current = 0;
foreach ($iter as $index => $next) {
var_dump([
'index' => $inex,
'current' => $current,
'next' => $next,
'isEndStream' => isEndStream($chunk, $current)
]);
$current = $next;
}
<?php
function H2FrameIter(string $chunk): Generator {
$chunk_size = strlen($chunk);
$index = 0;
$next = 0;
while (true) {
if ($next > $chunk_size || $next + 3 > $chunk_size) {
break;
}
$size = hexdec(bin2hex(substr($chunk, $next, 3))) + 9;
$next += $size;
yield $index => $next;
++$index;
}
}
function isEndStream(string $chunk, int $current): bool {
$chunk_size = strlen($chunk);
if ($current + 4 > $chunk_size) {
return false;
}
$type = ord(substr($chunk, $current + 3, 1));
$flag = ord(substr($chunk, $current + 4, 1));
return $type === 0x00 && $flag === 0x01 ?: false;
}
function isDataFrame(string $chunk, int $current): bool {
$chunk_size = strlen($chunk);
if ($current + 4 > $chunk_size) {
return false;
}
$type = ord(substr($chunk, $current + 3, 1));
return $type === 0x00;
}
function getPayload(string $chunk, $current): string {
$chunk_size = strlen($chunk);
if ($current + 3 > $chunk_size) {
return "";
}
$length = hexdec(bin2hex(substr($chunk, $current, 3)));
if ($current + 9 + $length > $chunk_size) {
return "";
}
return substr($chunk, $current + 9, $length);
}
function h2_client_frame($name = null) {
$ret = [
'pri' => "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
'settings' => "\x00\x00\x0C".
"\x04".
"\x00".
"\x00\x00\x00\x00".
"\x00\x02\x00\x00\x00\x00".
"\x00\x03\x00\x00\x00\x64",
'ack' => "\x00\x00\x00".
"\x04".
"\x01".
"\x00\x00\x00\x00",
'headers' => "\x00\x00\x3a".
"\x01".
"\x05".
"\x00\x00\x00\x01".
"\x00".
"\x07:method". // 7 :method
"\x03\x47\x45\x54". // 3 GET
"\x00".
"\x05\x3a\x70\x61\x74\x68". // 5 :path
"\x01\x2f". // 1 /
"\x00".
"\x07\x3a\x73\x63\x68\x65\x6d\x65". // 7 :scheme
"\x04http". // 4 http
"\x00".
"\x0a\x3a\x61\x75\x74\x68\x6f\x72\x69\x74\x79". // 10 :authority
"\x09localhost" // 9 localhost
];
return $name === null ? implode($ret) : $ret[$name];
}
function h2_server_frame() {
$ret = [
'settings' => "\x00\x00\x06".
"\x04".
"\x00".
"\x00\x00\x00\x00".
"\x00\x03\x00\x00\x00\x64",
'ack' => "\x00\x00\x00".
"\x04".
"\x01".
"\x00\x00\x00\x00",
'headers' => "\x00\x00\x5c".
"\x01".
"\x04".
"\x00\x00\x00\x01".
"\x88\x76\x90\xaa\x69\xd2\x9a\xe4\x52\xa9\xa7".
"\x4a\x6b\x13\x01\x5d\xb1\x2e\x0f\x58\x89\xa4".
"\x7e\x56\x1c\xc5\x81\x97\x00\x0f\x61\x97\xdf".
"\x3d\xbf\x4a\x05\xe5\x32\xdb\x42\x82\x00\x9a".
"\x50\x22\xb8\xcb\xb7\x1b\x6d\x4c\x5a\x37\xff".
"\x0f\x0d\x01\x36\x6c\x96\xdc\x34\xfd\x28\x07".
"\x14\xcb\x6d\x0a\x08\x02\x69\x40\xbf\x70\x2f".
"\xdc\x6d\xb5\x31\x68\xdf\x5f\x87\x49\x7c\xa5".
"\x89\xd3\x4d\x1f",
'data' => "\x00\x00\x06".
"\x00".
"\x01".
"\x00\x00\x00\x01".
"\x48\x65\x6c\x6c\x6f\x0a"
];
return implode($ret);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment