diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 99eed18..0000000 --- a/.codecov.yml +++ /dev/null @@ -1,17 +0,0 @@ -# Documentation: https://github.com/codecov/support/wiki/codecov.yml - -coverage: - precision: 3 - round: down - range: 80...100 - - status: - # Learn more at https://codecov.io/docs#yaml_default_commit_status - project: off - patch: - default: - informational: true - changes: off - - -comment: false diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index decb0cd..0000000 --- a/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -root = true - -[*.{c,h,d,di,dd,json}] -end_of_line = lf -insert_final_newline = true -indent_style = tab -indent_size = 4 -trim_trailing_whitespace = true -charset = utf-8 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94f2657..12a3096 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,31 +9,90 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] - dc: [ dmd-latest, dmd-2.094.2, dmd-2.089.1, dmd-2.084.1, ldc-1.24.0, ldc-1.21.0, ldc-1.17.0 ] + os: + - ubuntu-latest + dc: + - dmd-latest + - dmd-2.097.1 + - dmd-2.096.1 + - dmd-2.093.1 + - dmd-2.091.1 + - ldc-latest + - ldc-1.27.1 + - ldc-1.26.0 + - ldc-1.23.0 + - ldc-1.21.0 + parts: + - 'builds,unittests,examples,tests' + extra_dflags: + - '' include: - # Default - - { parts: 'builds,unittests,examples,tests', extra_dflags: '' } # Custom part for coverage - - { dc: dmd-2.094.2, parts: 'unittests,tests', extra_dflags: "-cov -version=VibedSetCoverageMerge" } + - { os: ubuntu-latest, dc: dmd-latest, parts: 'unittests,tests', extra_dflags: "-cov -version=VibedSetCoverageMerge" } + # Custom part for vibe-core 1.x.x testing + - { os: ubuntu-latest, dc: dmd-latest, parts: 'builds,unittests,tests', extra_dflags: '' } runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Prepare compiler uses: dlang-community/setup-dlang@v1 with: compiler: ${{ matrix.dc }} + dub: 1.29.0 - name: '[POSIX] Run tests' env: - PARTS: builds,unittests,examples,tests + VIBED_DRIVER: vibe-core + PARTS: ${{ matrix.parts }} run: | - ./travis-ci.sh + ./run-ci.sh - name: '[DMD] Upload coverage to Codecov' if: matrix.dc == 'dmd-latest' uses: codecov/codecov-action@v1 + + + main_win: + name: Run Windows + strategy: + fail-fast: false + matrix: + os: + - windows-latest + dc: + - dmd-latest + - dmd-2.097.1 + - dmd-2.096.1 + - dmd-2.093.1 + - dmd-2.091.1 + - ldc-latest + - ldc-1.27.1 + - ldc-1.26.0 + - ldc-1.23.0 + - ldc-1.21.0 + parts: + - 'builds,unittests,examples,tests' + extra_dflags: + - '' + + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v3 + + - name: Prepare compiler + uses: dlang-community/setup-dlang@v1 + with: + compiler: ${{ matrix.dc }} + dub: 1.29.0 + + - name: '[POSIX] Run tests' + env: + PARTS: ${{ matrix.parts }} + run: | + ./run-ci.sh diff --git a/.gitignore b/.gitignore index 36b83de..adca066 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,48 @@ -/libevent.dll -/dub.selections.json -/http-test-library.exe +*.[oa] +*.so +*.lib +*.dll +.*.sw* +*.lst +*.map +*.pdb +*.suo +*.sln +*.visualdproj +*.exe_cv + +docs.json +/docs +__dummy.html + .dub -libvibe-http.a -vibe-http-test-library +dub.selections.json + +# Auto-generated +tls/openssl_version.d + +# Auto-downloaded 3rd-party (Meson) +lib/subprojects/allocator +lib/subprojects/diet/ +lib/subprojects/openssl/ + +# Mono-D files +*.userprefs + +# Unittest binaries +vibe-d +tests/*/tests +__test__*__ +vibe-d-test* +vibe-d-*-test* + +# Examples +examples/*/*-example +examples/app_skeleton/app-skeleton +examples/app_skeleton/__test__library__ +examples/bench-http-request/bench-http-request +examples/bench-http-server/bench-http-server +examples/bench-mongodb/bench-mongodb +examples/bench-urlrouter/bench-urlrouter +*.exe + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 557a87e..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,14 +0,0 @@ -Guidelines for Contributing -=========================== - -Welcome to the vibe.d HTTP repository and thank you for your interest in contributing to its development! - -When contributing pull requests, the following points should ideally apply: - - - Each pull request should contain only one isolated functional change - - The code adheres to the [style guide](http://vibed.org/style-guide) - - For the occasional more complex pull request each change should be separated into its own commit - - Try not to mix whitespace or style changes with functional changes in the same commit - - The pull request must pass the test suite (run `dub test` to test locally) - -Exceptions to these rules are accepted all the time, but please try to follow them as closely as possible, because otherwise it often considerably increases the total amount of work and communication overhead. diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 0cae710..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2012-2018 Sönke Ludwig - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/LICENSE_DE.txt b/LICENSE_DE.txt deleted file mode 100644 index 94193a5..0000000 --- a/LICENSE_DE.txt +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2012-2018 Sönke Ludwig - -Hiermit wird unentgeltlich, jeder Person, die eine Kopie der Software und der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, uneingeschränkt zu benutzen, inklusive und ohne Ausnahme, dem Recht, sie zu verwenden, kopieren, ändern, fusionieren, verlegen, verbreiten, unterlizenzieren und/oder zu verkaufen, und Personen, die diese Software erhalten, diese Rechte zu geben, unter den folgenden Bedingungen: - -Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen Kopien oder Teilkopien der Software beizulegen. - -DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE ZUR BENUTZUNG FÜR DEN VORGESEHENEN ODER EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRÄNKT. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FÜR JEGLICHEN SCHADEN ODER SONSTIGE ANSPRÜCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFÜLLUNG EINES VERTRAGES, EINES DELIKTES ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 515b349..0000000 --- a/README.md +++ /dev/null @@ -1,20 +0,0 @@ -[![vibe.d](http://vibed.org/images/logo-and-title.png)](http://vibed.org) - -vibe.d is a high-performance asynchronous I/O, concurrency and web application -toolkit written in D. This repository contains the upcoming HTTP module that -is going to replace the existing HTTP/1.1 implementation. - -[![Posix Build Status](https://travis-ci.org/vibe-d/vibe-http.svg?branch=master)](https://travis-ci.org/vibe-d/vibe-http) -[![Windows Build status](https://ci.appveyor.com/api/projects/status/9r1p1avpl75nb73e?svg=true)](https://ci.appveyor.com/project/s-ludwig/vibe-http/branch/master) - - -Experimental status -=================== - -This library is a partial rewrite of the original `vibe-d:http` package and should -be considered experimental. Do not use it in production, yet. - -- It may still receive breaking changes -- The code in general should not be considered ready for production -- It currently lacks some features, such as the HTTP client implementation -- The HTTP/2 server still needs extensive testing diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index f5bcb52..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,114 +0,0 @@ -platform: x64 -environment: - matrix: - - DC: dmd - DVersion: 2.094.2 - arch: x64 - - DC: dmd - DVersion: 2.094.2 - arch: x86 - - DC: dmd - DVersion: 2.089.1 - arch: x64 - - DC: dmd - DVersion: 2.084.1 - arch: x86_mscoff - - DC: ldc - DVersion: 1.24.0 - arch: x64 - - DC: ldc - DVersion: 1.17.0 - arch: x86 - -skip_tags: false - -install: - - ps: function SetUpDCompiler - { - if($env:DC -eq "dmd"){ - if($env:arch -eq "x86"){ - $env:DConf = "m32"; - } - elseif($env:arch -eq "x64"){ - $env:DConf = "m64"; - } - echo "downloading ..."; - $env:toolchain = "msvc"; - $version = $env:DVersion; - Invoke-WebRequest "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z" -OutFile "c:\dmd.7z"; - echo "finished."; - pushd c:\\; - 7z x dmd.7z > $null; - popd; - } - elseif($env:DC -eq "ldc"){ - echo "downloading ..."; - if($env:arch -eq "x86"){ - $env:DConf = "m32"; - } - elseif($env:arch -eq "x64"){ - $env:DConf = "m64"; - } - $env:toolchain = "msvc"; - $version = $env:DVersion; - if ([System.Version]$version -lt [System.Version]"1.7.0") { - Invoke-WebRequest "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-win64-msvc.zip" -OutFile "c:\ldc.zip"; - echo "finished."; - pushd c:\\; - 7z x ldc.zip > $null; - popd; - } - else { - Invoke-WebRequest "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-windows-multilib.7z" -OutFile "c:\ldc.7z"; - echo "finished."; - pushd c:\\; - 7z x ldc.7z > $null; - popd; - } - } - } - - ps: SetUpDCompiler - - powershell -Command [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest "https://github.com/dlang/dub/releases/download/v1.23.0/dub-v1.23.0-windows-i686.zip" -OutFile dub.zip - - 7z x dub.zip -odub > nul - - set PATH=%CD%\%binpath%;%CD%\dub;%PATH% - - dub --version - -before_build: - - ps: if($env:arch -eq "x86"){ - $env:compilersetupargs = "x86"; - $env:Darch = "x86"; - } - elseif($env:arch -eq "x86_mscoff"){ - $env:compilersetupargs = "x86"; - $env:Darch = "x86_mscoff"; - } - elseif($env:arch -eq "x64"){ - $env:compilersetupargs = "amd64"; - $env:Darch = "x86_64"; - } - - ps : if($env:DC -eq "dmd"){ - $env:PATH += ";C:\dmd2\windows\bin;"; - } - elseif($env:DC -eq "ldc"){ - $version = $env:DVersion; - if ([System.Version]$version -lt [System.Version]"1.7.0") { - $env:PATH += ";C:\ldc2-$($version)-win64-msvc\bin"; - } else { - $env:PATH += ";C:\ldc2-$($version)-windows-multilib\bin"; - } - $env:DC = "ldc2"; - } - - ps: $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall"; - - '"%compilersetup%" %compilersetupargs%' - -build_script: - - dub build -b release --arch=%Darch% --compiler=%DC% - - echo dummy build script - dont remove me - -test_script: - - echo %PLATFORM% - - echo %Darch% - - echo %DC% - - echo %PATH% - - '%DC% --version' - - dub test --arch=%Darch% --compiler=%DC% diff --git a/dub.sdl b/dub.sdl index 2fffcd0..7c510e8 100644 --- a/dub.sdl +++ b/dub.sdl @@ -1,17 +1,8 @@ name "vibe-http" description "HTTP server and client implementation and higher level HTTP functionality" -homepage "https://vibed.org/" - -license "MIT" -copyright "Copyright © 2012-2019 Sönke Ludwig" -authors "Sönke Ludwig" "Francesco Galla" "see GitHub for all" - -dependency "vibe-d:crypto" version=">0.8.4" -dependency "vibe-d:tls" version=">0.8.4" -dependency "vibe-d:inet" version="*" -dependency "vibe-d:stream" version="*" -dependency "vibe-d:textfilter" version="*" -dependency "diet-ng" version="~>1.1" -dependency "taggedalgebraic" version=">=0.10.9 <0.12.0-0" - +dependency "vibe-d:crypto" version="~>0.9.7" +dependency "vibe-d:inet" version="~>0.9.7" +dependency "vibe-d:tls" version="~>0.9.7" +dependency "vibe-d:textfilter" version="~>0.9.0" +dependency "diet-ng" version="~>1.2" targetType "library" diff --git a/examples/auth_basic/dub.sdl b/examples/auth_basic/dub.sdl new file mode 100644 index 0000000..d60b06c --- /dev/null +++ b/examples/auth_basic/dub.sdl @@ -0,0 +1,3 @@ +name "auth-basic-example" +description "Demonstrates basic authentication." +dependency "vibe-http" path="../../" diff --git a/examples/auth_basic/source/app.d b/examples/auth_basic/source/app.d new file mode 100644 index 0000000..e548e01 --- /dev/null +++ b/examples/auth_basic/source/app.d @@ -0,0 +1,33 @@ +module app; + +import vibe.core.core; +import vibe.http.auth.basic_auth; +import vibe.http.router; +import vibe.http.server; +import std.functional : toDelegate; + +bool checkPassword(string user, string password) +{ + return user == "admin" && password == "secret"; +} + +int main(string[] args) +{ + auto router = new URLRouter; + + // the following routes are accessible without authentication: + router.get("/", staticTemplate!"index.dt"); + + // now any request is matched and checked for authentication: + router.any("*", performBasicAuth("Site Realm", toDelegate(&checkPassword))); + + // the following routes can only be reached if authenticated: + router.get("/internal", staticTemplate!"internal.dt"); + + auto settings = new HTTPServerSettings; + settings.port = 8080; + settings.bindAddresses = ["::1", "127.0.0.1"]; + + auto listener = listenHTTP(settings, router); + return runApplication(&args); +} diff --git a/examples/auth_basic/views/index.dt b/examples/auth_basic/views/index.dt new file mode 100644 index 0000000..bc13fee --- /dev/null +++ b/examples/auth_basic/views/index.dt @@ -0,0 +1,10 @@ +doctype html +html + head + title Basic Authentication Example + body + p Click on the + a(href="/internal") link + | to access a protected page. + + diff --git a/examples/auth_basic/views/internal.dt b/examples/auth_basic/views/internal.dt new file mode 100644 index 0000000..76ec83a --- /dev/null +++ b/examples/auth_basic/views/internal.dt @@ -0,0 +1,8 @@ +doctype html +html + head + title Basic Authentication Example + body + p This page is protected. + + diff --git a/examples/auth_digest/dub.sdl b/examples/auth_digest/dub.sdl new file mode 100644 index 0000000..0737bdf --- /dev/null +++ b/examples/auth_digest/dub.sdl @@ -0,0 +1,3 @@ +name "auth-digest-example" +description "Demonstrates digest authentication." +dependency "vibe-http" path="../../" diff --git a/examples/auth_digest/source/app.d b/examples/auth_digest/source/app.d new file mode 100644 index 0000000..000453b --- /dev/null +++ b/examples/auth_digest/source/app.d @@ -0,0 +1,38 @@ +module app; + +import vibe.core.core; +import vibe.http.auth.digest_auth; +import vibe.http.router; +import vibe.http.server; +import std.functional : toDelegate; + +string digestPassword(string realm, string user) @safe +{ + if (realm == "Site Realm" && user == "admin") + return createDigestPassword(realm, user, "secret"); + return ""; +} + +int main(string[] args) +{ + auto authinfo = new DigestAuthInfo; + authinfo.realm = "Site Realm"; + + auto router = new URLRouter; + + // the following routes are accessible without authentication: + router.get("/", staticTemplate!"index.dt"); + + // now any request is matched and checked for authentication: + router.any("*", performDigestAuth(authinfo, toDelegate(&digestPassword))); + + // the following routes can only be reached if authenticated: + router.get("/internal", staticTemplate!"internal.dt"); + + auto settings = new HTTPServerSettings; + settings.port = 8080; + settings.bindAddresses = ["::1", "127.0.0.1"]; + + auto listener = listenHTTP(settings, router); + return runApplication(&args); +} diff --git a/examples/auth_digest/views/index.dt b/examples/auth_digest/views/index.dt new file mode 100644 index 0000000..acf269d --- /dev/null +++ b/examples/auth_digest/views/index.dt @@ -0,0 +1,10 @@ +doctype html +html + head + title Digest Authentication Example + body + p Click on the + a(href="/internal") link + | to access a protected page. + + diff --git a/examples/auth_digest/views/internal.dt b/examples/auth_digest/views/internal.dt new file mode 100644 index 0000000..052761e --- /dev/null +++ b/examples/auth_digest/views/internal.dt @@ -0,0 +1,8 @@ +doctype html +html + head + title Digest Authentication Example + body + p This page is protected. + + diff --git a/examples/bench-http-request/dub.sdl b/examples/bench-http-request/dub.sdl new file mode 100644 index 0000000..7233738 --- /dev/null +++ b/examples/bench-http-request/dub.sdl @@ -0,0 +1,3 @@ +name "bench-http-request" +dependency "vibe-http" path="../../" +versions "VibeManualMemoryManagement" diff --git a/examples/bench-http-request/source/app.d b/examples/bench-http-request/source/app.d new file mode 100644 index 0000000..32fdb82 --- /dev/null +++ b/examples/bench-http-request/source/app.d @@ -0,0 +1,105 @@ +import vibe.core.args; +import vibe.core.core; +import vibe.http.client; + +import core.atomic; + +import std.datetime.stopwatch; +import std.functional; +import std.stdio; + + +shared long nreq = 0; +shared long nerr = 0; +shared long nreqc = 1000; +shared long ndisconns = 0; +shared long nconn = 0; + +shared long g_concurrency = 100; +shared long g_requestDelay = 0; +shared long g_maxKeepAliveRequests = 1000; + +void request(bool disconnect) +nothrow { + atomicOp!"+="(nconn, 1); + try { + requestHTTP("http://127.0.0.1:8080/empty", + (scope req){ + req.headers.remove("Accept-Encoding"); + if (disconnect) { + atomicOp!"+="(ndisconns, 1); + req.headers["Connection"] = "close"; + } + }, + (scope res){ + if (g_requestDelay) + sleep(g_requestDelay.msecs()); + res.dropBody(); + } + ); + } catch (Exception) { atomicOp!"+="(nerr, 1); } + atomicOp!"-="(nconn, 1); + atomicOp!"+="(nreq, 1); +} + +void distTask() +nothrow { + static shared int s_threadCount = 0; + static shared int s_token = 0; + int id = atomicOp!"+="(s_threadCount, 1) - 1; + + while (true) { + while (atomicLoad(s_token) != id && g_concurrency > 0) {} + if (g_concurrency == 0) break; + runTask({ + long keep_alives = 0; + while (true) { + bool disconnect = ++keep_alives >= g_maxKeepAliveRequests; + request(disconnect); + if (disconnect) keep_alives = 0; + } + }); + atomicOp!"+="(g_concurrency, -1); + atomicStore(s_token, cast(int)((id + 1) % workerThreadCount)); + } +} + +void benchmark() +nothrow { + atomicOp!"+="(g_concurrency, -1); + if (g_concurrency > 0) { + runWorkerTaskDist(&distTask); + while (atomicLoad(nreq) == 0) { sleepUninterruptible(1.msecs); } + } + + StopWatch sw; + sw.start(); + ulong next_ts = 100; + + long keep_alives = 0; + while (true) { + auto tm = sw.peek().total!"msecs"; + + if (nreq >= nreqc && tm >= next_ts) { + try writefln("%s iterations: %s req/s, %s err/s (%s active conn, %s disconnects/s)", nreq, (nreq*1_000)/tm, (nerr*1_000)/tm, nconn, (ndisconns*1_000)/tm); + catch (Exception e) assert(false, e.msg); + nreqc.atomicOp!"+="(1000); + next_ts += 100; + } + bool disconnect = ++keep_alives >= g_maxKeepAliveRequests; + request(disconnect); + if (disconnect) keep_alives = 0; +// if (nreq >= 5000) exitEventLoop(true); + } +} + +void main() +{ + import vibe.core.args; + readOption("c", cast(long*) &g_concurrency, "The maximum number of concurrent requests"); + readOption("d", cast(long*) &g_requestDelay, "Artificial request delay in milliseconds"); + readOption("k", cast(long*) &g_maxKeepAliveRequests, "Maximum number of keep-alive requests for each connection"); + if (!finalizeCommandLineOptions()) return; + runTask(&benchmark); + runEventLoop(); +} diff --git a/examples/bench-http-server/dub.sdl b/examples/bench-http-server/dub.sdl new file mode 100644 index 0000000..3a78d55 --- /dev/null +++ b/examples/bench-http-server/dub.sdl @@ -0,0 +1,3 @@ +name "bench-http-server" +dependency "vibe-http" path="../../" +versions "VibeManualMemoryManagement" diff --git a/examples/bench-http-server/public/10 b/examples/bench-http-server/public/10 new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/examples/bench-http-server/public/10 @@ -0,0 +1 @@ +1234567890 \ No newline at end of file diff --git a/examples/bench-http-server/public/10k b/examples/bench-http-server/public/10k new file mode 100644 index 0000000..22d650d --- /dev/null +++ b/examples/bench-http-server/public/10k @@ -0,0 +1 @@ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 \ No newline at end of file diff --git a/examples/bench-http-server/public/1k b/examples/bench-http-server/public/1k new file mode 100644 index 0000000..33602dc --- /dev/null +++ b/examples/bench-http-server/public/1k @@ -0,0 +1 @@ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 \ No newline at end of file diff --git a/examples/bench-http-server/source/app.d b/examples/bench-http-server/source/app.d new file mode 100644 index 0000000..bf3c218 --- /dev/null +++ b/examples/bench-http-server/source/app.d @@ -0,0 +1,101 @@ +module app; + +import vibe.core.core; +import vibe.http.fileserver; +import vibe.http.router; +import vibe.http.server; +import vibe.core.stream : pipe, nullSink; + +import std.functional : toDelegate; + + +shared string data; + +void empty(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + res.writeBody(""); +} + +void static_10(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + res.writeBody(cast(string)data[0 .. 10]); +} + +void static_1k(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + res.writeBody(cast(string)data[0 .. 1000]); +} + +void static_10k(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + res.writeBody(cast(string)data[0 .. 10_000]); +} + +void static_100k(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + res.writeBody(cast(string)data[0 .. 100_000]); +} + +void quit(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + res.writeBody("Exiting event loop..."); + exitEventLoop(); +} + +void staticAnswer(TCPConnection conn) +@safe nothrow { + try { + conn.write("HTTP/1.0 200 OK\r\nContent-Length: 0\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n"); + conn.close(); + } catch (Exception e) { + // increment error counter + } +} + +pure char[] generateData() +{ + char[] data; + data.length = 100_000; + foreach (i; 0 .. data.length) { + data[i] = (i % 10) + '0'; + if (i % 100 == 99) data[i] = '\n'; + } + return data; +} + + +int main(string[] args) +{ + //setLogLevel(LogLevel.Trace); + data = generateData(); + + runWorkerTaskDist(() nothrow { + try { + auto settings = new HTTPServerSettings; + settings.port = 8080; + settings.bindAddresses = ["127.0.0.1"]; + settings.options = HTTPServerOption.reusePort; + //settings.accessLogToConsole = true; + + auto fsettings = new HTTPFileServerSettings; + fsettings.serverPathPrefix = "/file"; + + auto routes = new URLRouter; + routes.get("/", staticTemplate!"home.dt"); + routes.get("/empty", &empty); + routes.get("/static/10", &static_10); + routes.get("/static/1k", &static_1k); + routes.get("/static/10k", &static_10k); + routes.get("/static/100k", &static_100k); + routes.get("/quit", &quit); + routes.get("/file/*", serveStaticFiles("./public", fsettings)); + routes.rebuild(); + + auto httpListener = listenHTTP(settings, routes); + auto tcpListener = listenTCP(8081, toDelegate(&staticAnswer), + "127.0.0.1", TCPListenOptions.reusePort); + } catch (Exception e) assert(false, e.msg); + }); + + return runApplication(&args); +} diff --git a/examples/bench-http-server/views/home.dt b/examples/bench-http-server/views/home.dt new file mode 100644 index 0000000..894840e --- /dev/null +++ b/examples/bench-http-server/views/home.dt @@ -0,0 +1,25 @@ +doctype html +html + head + title Benchmark site + body + h1 Available tests: + ol + li + a(href="empty") Empty response + li + a(href="static/10") 10B static page + li + a(href="static/1k") 1kB static page + li + a(href="static/10k") 10kB static page + li + a(href="file/10") 10B file + li + a(href="file/1k") 1kB file + li + a(href="file/10k") 10kB file + li + a(href="http://127.0.0.1:8081/") static response + li + a(href="quit") Quit diff --git a/examples/bench-urlrouter/dub.sdl b/examples/bench-urlrouter/dub.sdl new file mode 100644 index 0000000..7e05a29 --- /dev/null +++ b/examples/bench-urlrouter/dub.sdl @@ -0,0 +1,4 @@ +name "bench-urlrouter" +description "Benchmark for the URLRouter class" +dependency "vibe-http" path="../../" +versions "VibeRouterTreeMatch" diff --git a/examples/bench-urlrouter/source/app.d b/examples/bench-urlrouter/source/app.d new file mode 100644 index 0000000..1de0db6 --- /dev/null +++ b/examples/bench-urlrouter/source/app.d @@ -0,0 +1,77 @@ +import vibe.core.log; +import vibe.http.router; +import vibe.http.server; +import vibe.inet.url; +import std.datetime.stopwatch; +import std.string : format; + + +void req(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + if (!res.headerWritten) + res.writeVoidBody(); +} + +Duration runTimed(scope void delegate() del) +{ + StopWatch sw; + sw.start(); + del(); + sw.stop(); + return sw.peek; +} + +void main() +{ + enum nroutes = 1_000; + enum nrequests = 1_000_000; + + auto router = new URLRouter; + + logInfo("Setting up routes..."); + auto duradd = runTimed({ + foreach (i; 0 .. nroutes) + router.get(format("/%s/:test1/%s/:test2", i/100, i), &req); + }); + + import std.random; + foreach (i; 0 .. nroutes) + router.get(format("/%s%s", uniform!uint(), uniform!uint()), &req); + + logInfo("Performing first request..."); + auto req = createTestHTTPServerRequest(URL("http://localhost/0/test/0/test"), HTTPMethod.GET); + auto res = createTestHTTPServerResponse(); + auto durfirst = runTimed({ + router.handleRequest(req, res); + }); + + logInfo("Performing first match requests..."); + auto durfirstmatch = runTimed({ + foreach (i; 0 .. nrequests) + router.handleRequest(req, res); + }); + + logInfo("Performing last match requests..."); + req = createTestHTTPServerRequest(URL(format("http://localhost/%s/test/%s/test", (nroutes-1)/100, nroutes-1)), HTTPMethod.GET); + auto durlastmatch = runTimed({ + foreach (i; 0 .. nrequests) + router.handleRequest(req, res); + }); + + logInfo("Performing non-match requests..."); + req = createTestHTTPServerRequest(URL("http://localhost/test/x/test"), HTTPMethod.GET); + auto durnonmatch = runTimed({ + foreach (i; 0 .. nrequests) + router.handleRequest(req, res); + }); + + version (VibeRouterTreeMatch) enum method = "tree match"; + else enum method = "linear probe"; + + logInfo("Results (%s):", method); + logInfo(" Add %s routes: %s", nroutes, duradd); + logInfo(" First request: %s", durfirst); + logInfo(" %s first match requests: %s", nrequests, durfirstmatch); + logInfo(" %s last match requests: %s", nrequests, durlastmatch); + logInfo(" %s non-match requests: %s", nrequests, durnonmatch); +} diff --git a/examples/dummy/dub.sdl b/examples/dummy/dub.sdl deleted file mode 100644 index eeafa87..0000000 --- a/examples/dummy/dub.sdl +++ /dev/null @@ -1 +0,0 @@ -name "dummy-example" diff --git a/examples/dummy/source/app.d b/examples/dummy/source/app.d deleted file mode 100644 index 255e5a0..0000000 --- a/examples/dummy/source/app.d +++ /dev/null @@ -1,6 +0,0 @@ -import std.stdio; - -void main() -{ - writeln("This is a dummy example"); -} diff --git a/examples/http2/dub.sdl b/examples/http2/dub.sdl deleted file mode 100644 index 73f5d59..0000000 --- a/examples/http2/dub.sdl +++ /dev/null @@ -1,7 +0,0 @@ -name "http2-example" - -dependency "vibe-http" path="../../../vibe-http" - -/*versions "VibeForceALPN"*/ -targetType "executable" -/*buildOptions "profileGC"*/ diff --git a/examples/http2/source/app.d b/examples/http2/source/app.d deleted file mode 100644 index ebb9f2d..0000000 --- a/examples/http2/source/app.d +++ /dev/null @@ -1,92 +0,0 @@ -/* ==== Vibe.d HTTP/2 Webserver Example ==== */ -/* Supports both HTTP and HTTPS transport */ -/* Transparent (WIP: exposing settings) */ -/* ========================================= */ - -import vibe.http.server; -import vibe.stream.tls; -import vibe.http.internal.http2.http2 : http2Callback; // ALPN negotiation -import vibe.core.core : runApplication; - -/* ==== declare two handlers (could use the same one) ==== */ -void handleReq(HTTPServerRequest req, HTTPServerResponse res) -@safe { - if (res.httpVersion == HTTPVersion.HTTP_2) - res.writeBody("Hello, you connected to "~req.path~"! This response is sent through HTTP/2\n"); - else - res.writeBody("Hello, World! You connected through HTTP/1, try using HTTP/2!\n"); -} - -void tlsHandleReq(HTTPServerRequest req, HTTPServerResponse res) -@safe { - if (req.httpVersion == HTTPVersion.HTTP_2) - res.writeBody("Hello, you connected to "~req.path~"! This response is sent through HTTP/2 with TLS\n"); - else - res.writeBody("Hello, World! You connected through HTTP/1 with TLS, try using HTTP/2!\n"); -} - -// sends a very big data frame -void bigHandleReq(size_t DIM)(HTTPServerRequest req, HTTPServerResponse res) -@trusted { - import vibe.utils.array : FixedAppender; - import std.range : iota; - - FixedAppender!(immutable(char)[], DIM) appender; - - if (req.path == "/") { - foreach(i; iota(1,DIM-4)) appender.put('1'); - appender.put(['O','k','!', '\n']); - res.writeBody(appender.data); - } -} - -void main() -{ - //import vibe.core.log; - //setLogLevel(LogLevel.trace); - -/* ==== cleartext HTTP/2 support (h2c) ==== */ - auto settings = new HTTPServerSettings; - settings.port = 8090; - settings.bindAddresses = ["127.0.0.1"]; - listenHTTP!handleReq(settings); - -/* ==== cleartext HTTP/2 support (h2c) with a heavy DATA frame ==== */ - auto bigSettings = new HTTPServerSettings; - settings.port = 8092; - settings.bindAddresses = ["127.0.0.1"]; - listenHTTP!(bigHandleReq!100000)(settings); - -/* ========== HTTPS (h2) support ========== */ - auto tlsSettings = new HTTPServerSettings; - tlsSettings.port = 8091; - tlsSettings.bindAddresses = ["127.0.0.1"]; - - /// setup TLS context by using cert and key in example rootdir - tlsSettings.tlsContext = createTLSContext(TLSContextKind.server); - tlsSettings.tlsContext.useCertificateChainFile("server.crt"); - tlsSettings.tlsContext.usePrivateKeyFile("server.key"); - - // set alpn callback to support HTTP/2 protocol negotiation - tlsSettings.tlsContext.alpnCallback(http2Callback); - listenHTTP!tlsHandleReq(tlsSettings); - -/* ========== HTTPS (h2) support with a heavy DATA frame ========== */ - auto bigTLSSettings = new HTTPServerSettings; - bigTLSSettings.port = 8093; - bigTLSSettings.bindAddresses = ["127.0.0.1"]; - - /// setup TLS context by using cert and key in example rootdir - bigTLSSettings.tlsContext = createTLSContext(TLSContextKind.server); - bigTLSSettings.tlsContext.useCertificateChainFile("server.crt"); - bigTLSSettings.tlsContext.usePrivateKeyFile("server.key"); - - // set alpn callback to support HTTP/2 protocol negotiation - bigTLSSettings.tlsContext.alpnCallback(http2Callback); - auto l = listenHTTP!(bigHandleReq!100000)(bigTLSSettings); - scope(exit) l.stopListening(); - -/* ========== Run both `listenHTTP` handlers ========== */ - // UNCOMMENT to run - runApplication(); -} diff --git a/examples/http_forward_proxy/dub.sdl b/examples/http_forward_proxy/dub.sdl index 6ce4a9e..85f8b44 100644 --- a/examples/http_forward_proxy/dub.sdl +++ b/examples/http_forward_proxy/dub.sdl @@ -1,3 +1,3 @@ -name "http-forward-proxy-example" +name "http-forward-proxy-example" description "Sets up a simple forward proxy." dependency "vibe-http" path="../../" diff --git a/examples/http_forward_proxy/source/app.d b/examples/http_forward_proxy/source/app.d index ea2005b..6fdba65 100644 --- a/examples/http_forward_proxy/source/app.d +++ b/examples/http_forward_proxy/source/app.d @@ -1,15 +1,15 @@ +module app; + import vibe.core.core; import vibe.http.proxy; import vibe.http.server; - -void main() +int main(string[] args) { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; listenHTTPForwardProxy(settings); - - runApplication(); + return runApplication(&args); } diff --git a/examples/http_info/dub.sdl b/examples/http_info/dub.sdl index ceb17ba..7e1c23a 100644 --- a/examples/http_info/dub.sdl +++ b/examples/http_info/dub.sdl @@ -1,3 +1,3 @@ -name "http-info-example" +name "http-info-example" description "Displays request information using a Diet template." dependency "vibe-http" path="../../" diff --git a/examples/http_info/source/app.d b/examples/http_info/source/app.d index 2225b79..9981353 100644 --- a/examples/http_info/source/app.d +++ b/examples/http_info/source/app.d @@ -1,14 +1,15 @@ +module app; + import vibe.core.core; import vibe.http.server; -void main() +int main (string[] args) { auto settings = new HTTPServerSettings; settings.sessionStore = new MemorySessionStore(); settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; - listenHTTP(settings, staticTemplate!("info.dt")); - - runApplication(); + auto listener = listenHTTP(settings, staticTemplate!("info.dt")); + return runApplication(&args); } diff --git a/examples/http_request/dub.sdl b/examples/http_request/dub.sdl index a929013..54617a9 100644 --- a/examples/http_request/dub.sdl +++ b/examples/http_request/dub.sdl @@ -1,4 +1,4 @@ -name "http-request-example" +name "http-request-example" description "Performs a custom HTTP request." authors "Sönke Ludwig" dependency "vibe-http" path="../../" diff --git a/examples/http_request_digest/dub.sdl b/examples/http_request_digest/dub.sdl index f0254bd..8dd92cb 100644 --- a/examples/http_request_digest/dub.sdl +++ b/examples/http_request_digest/dub.sdl @@ -1,4 +1,4 @@ -name "http-request-digest-example" +name "http-request-digest-example" description "Performs a custom HTTP request with digest authentication." authors "Sönke Ludwig" dependency "vibe-http" path="../../" diff --git a/examples/http_reverse_proxy/dub.sdl b/examples/http_reverse_proxy/dub.sdl index 8ad5bd1..a323114 100644 --- a/examples/http_reverse_proxy/dub.sdl +++ b/examples/http_reverse_proxy/dub.sdl @@ -1,3 +1,3 @@ -name "http-reverse-proxy-example" +name "http-reverse-proxy-example" description "Sets up a simple reverse proxy to a foreign server." dependency "vibe-http" path="../../" diff --git a/examples/http_reverse_proxy/source/app.d b/examples/http_reverse_proxy/source/app.d index 9ad9ea9..ca952b4 100644 --- a/examples/http_reverse_proxy/source/app.d +++ b/examples/http_reverse_proxy/source/app.d @@ -1,15 +1,15 @@ +module app; + import vibe.core.core; import vibe.http.proxy; import vibe.http.server; - -void main() +int main(string[] args) { auto settings = new HTTPServerSettings; settings.port = 8080; settings.bindAddresses = ["::1", "127.0.0.1"]; listenHTTPReverseProxy(settings, "vibed.org", 80); - - runApplication(); + return runApplication(&args); } diff --git a/examples/https_server_sni/dub.sdl b/examples/https_server_sni/dub.sdl index 56bee74..624dbc9 100644 --- a/examples/https_server_sni/dub.sdl +++ b/examples/https_server_sni/dub.sdl @@ -1,3 +1,3 @@ -name "https-sni-server-example" +name "https-sni-server-example" description "Uses SNI to serve multiple virtual hosts in a single HTTPS port." dependency "vibe-http" path="../../" diff --git a/examples/https_server_sni/source/app.d b/examples/https_server_sni/source/app.d index d5ebc33..0afafb7 100644 --- a/examples/https_server_sni/source/app.d +++ b/examples/https_server_sni/source/app.d @@ -1,10 +1,11 @@ +module app; + import vibe.core.core; import vibe.core.log; import vibe.http.server; import vibe.stream.tls; - -void main() +int main(string[] args) { { auto settings = new HTTPServerSettings; @@ -41,7 +42,7 @@ and should be presented with a different certificate each time, matching the host name entered. `); - runApplication(); + return runApplication(&args); } void handleRequestA(scope HTTPServerRequest req, scope HTTPServerResponse res) diff --git a/examples/uploader/dub.sdl b/examples/uploader/dub.sdl new file mode 100644 index 0000000..ba78330 --- /dev/null +++ b/examples/uploader/dub.sdl @@ -0,0 +1,3 @@ +name "uploader-example" +description "Simple form based file upload example." +dependency "vibe-http" path="../../" diff --git a/examples/uploader/source/app.d b/examples/uploader/source/app.d new file mode 100644 index 0000000..c4483ae --- /dev/null +++ b/examples/uploader/source/app.d @@ -0,0 +1,38 @@ +module app; + +import vibe.core.core; +import vibe.core.file; +import vibe.core.log; +import vibe.core.path; +import vibe.http.router; +import vibe.http.server; + +import std.exception; + +void uploadFile(scope HTTPServerRequest req, scope HTTPServerResponse res) +{ + auto pf = "file" in req.files; + enforce(pf !is null, "No file uploaded!"); + try moveFile(pf.tempPath, NativePath(".") ~ pf.filename); + catch (Exception e) { + logWarn("Failed to move file to destination folder: %s", e.msg); + logInfo("Performing copy+delete instead."); + copyFile(pf.tempPath, NativePath(".") ~ pf.filename); + } + + res.writeBody("File uploaded!", "text/plain"); +} + +int main(string[] args) +{ + auto router = new URLRouter; + router.get("/", staticTemplate!"upload_form.dt"); + router.post("/upload", &uploadFile); + + auto settings = new HTTPServerSettings; + settings.port = 8080; + settings.bindAddresses = ["::1", "127.0.0.1"]; + + auto listener = listenHTTP(settings, router); + return runApplication(&args); +} diff --git a/examples/uploader/views/upload_form.dt b/examples/uploader/views/upload_form.dt new file mode 100644 index 0000000..6ee0677 --- /dev/null +++ b/examples/uploader/views/upload_form.dt @@ -0,0 +1,11 @@ +doctype 5 +html(lang="en") + head + title Uploader + body + h1 Uploader + form(method="POST", action="/upload", enctype="multipart/form-data") + p File: + input(type="file", name="file", size="50", maxlength="100000") + input(type="submit", value="Upload!") + \ No newline at end of file diff --git a/examples/websocket/dub.sdl b/examples/websocket/dub.sdl new file mode 100644 index 0000000..050a2c0 --- /dev/null +++ b/examples/websocket/dub.sdl @@ -0,0 +1,3 @@ +name "websocket-example" +description "Example for using the WebSocket feature" +dependency "vibe-http" path="../../" diff --git a/examples/websocket/public/index.html b/examples/websocket/public/index.html new file mode 100644 index 0000000..172792b --- /dev/null +++ b/examples/websocket/public/index.html @@ -0,0 +1,17 @@ + + +
+The following box should show a running counter, updated by the server:
+ + + + diff --git a/examples/websocket/public/scripts/websocket.js b/examples/websocket/public/scripts/websocket.js new file mode 100644 index 0000000..3981d81 --- /dev/null +++ b/examples/websocket/public/scripts/websocket.js @@ -0,0 +1,35 @@ +var socket + +function connect() +{ + setText("connecting..."); + socket = new WebSocket(getBaseURL() + "/ws"); + socket.onopen = function() { + setText("connected. waiting for timer..."); + } + socket.onmessage = function(message) { + setText(message.data); + } + socket.onclose = function() { + setText("connection closed."); + } + socket.onerror = function() { + setText("Error!"); + } +} + +function closeConnection() +{ + socket.close(); + setText("closed."); +} + +function setText(text) +{ + document.getElementById("timer").innerHTML = text; +} + +function getBaseURL() +{ + return "ws://" + window.location.host; +} diff --git a/examples/websocket/source/app.d b/examples/websocket/source/app.d new file mode 100644 index 0000000..14465e5 --- /dev/null +++ b/examples/websocket/source/app.d @@ -0,0 +1,41 @@ +module app; + +import vibe.core.core; +import vibe.core.log; +import vibe.http.fileserver : serveStaticFiles; +import vibe.http.router : URLRouter; +import vibe.http.server; +import vibe.http.websockets : WebSocket, handleWebSockets; + +import core.time; +import std.conv : to; + + +int main(string[] args) +{ + auto router = new URLRouter; + router.get("/", staticRedirect("/index.html")); + router.get("/ws", handleWebSockets(&handleWebSocketConnection)); + router.get("*", serveStaticFiles("public/")); + + auto settings = new HTTPServerSettings; + settings.port = 8080; + settings.bindAddresses = ["::1", "127.0.0.1"]; + + auto listener = listenHTTP(settings, router); + return runApplication(&args); +} + +void handleWebSocketConnection(scope WebSocket socket) +{ + int counter = 0; + logInfo("Got new web socket connection."); + while (true) { + sleep(1.seconds); + if (!socket.connected) break; + counter++; + logInfo("Sending '%s'.", counter); + socket.send(counter.to!string); + } + logInfo("Client disconnected."); +} diff --git a/run-ci.sh b/run-ci.sh new file mode 100755 index 0000000..d475551 --- /dev/null +++ b/run-ci.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -e -x -o pipefail + +DUB_ARGS="--build-mode=${DUB_BUILD_MODE:-separate} ${DUB_ARGS:-}" +# default to run all parts +: ${PARTS:=lint,builds,unittests,examples,tests} + +# force selecting vibe-core 2.x.x +if [[ $PARTS =~ (^|,)vibe-core-1(,|$) ]]; then + RECIPES=`find | grep dub.sdl` + sed -i "s/\"vibe-core\" version=\">=1\.0\.0 <3\.0\.0-0\"/\"vibe-core\" version=\">=1.0.0 <2.0.0-0\"/g" $RECIPES +fi + +if [[ $PARTS =~ (^|,)lint(,|$) ]]; then + ./scripts/test_version.sh + # Check for trailing whitespace" + grep -nrI --include=*.d '\s$' && (echo "Trailing whitespace found"; exit 1) +fi + +if [[ $PARTS =~ (^|,)builds(,|$) ]]; then + # test for successful release build + dub build --combined -b release --compiler=$DC + dub clean --all-packages + + # test for successful 32-bit build + if [ "$DC" == "dmd" ]; then + dub build --combined --arch=x86 + dub clean --all-packages + fi +fi + +if [[ $PARTS =~ (^|,)unittests(,|$) ]]; then + dub test --compiler=$DC $DUB_ARGS + dub clean --all-packages +fi + +if [[ $PARTS =~ (^|,)examples(,|$) ]]; then + for ex in $(\ls -1 examples/); do + echo "[INFO] Building example $ex" + (cd examples/$ex && dub build --compiler=$DC $DUB_ARGS && dub clean) + done +fi + +if [[ $PARTS =~ (^|,)tests(,|$) ]]; then + for ex in `\ls -1 tests/`; do + if ! [[ $PARTS =~ (^|,)redis(,|$) ]] && [ $ex == "redis" ]; then + continue + fi + if [ -r tests/$ex/run.sh ]; then + echo "[INFO] Running test $ex" + (cd tests/$ex && ./run.sh) + elif [ -r tests/$ex/dub.json ] || [ -r tests/$ex/dub.sdl ]; then + if [ $ex == "vibe.http.client.2080" ]; then + echo "[WARNING] Skipping test $ex due to TravisCI incompatibility". + else + echo "[INFO] Running test $ex" + (cd tests/$ex && dub --compiler=$DC $DUB_ARGS && dub clean) + fi + fi + done +fi diff --git a/source/vibe/http/auth/digest_auth.d b/source/vibe/http/auth/digest_auth.d index 60f0189..15bdf67 100644 --- a/source/vibe/http/auth/digest_auth.d +++ b/source/vibe/http/auth/digest_auth.d @@ -29,16 +29,16 @@ class DigestAuthInfo @safe: string realm; - ubyte[32] secret; - ulong timeout; + ubyte[16] secret; + Duration timeout; this() { secureRNG.read(secret[]); - timeout = 300; + timeout = 300.seconds; } - string createNonce(in HTTPServerRequest req) + string createNonce(scope const HTTPServerRequest req) { auto now = Clock.currTime(UTC()).stdTime(); auto time = () @trusted { return *cast(ubyte[now.sizeof]*)&now; } (); @@ -49,14 +49,14 @@ class DigestAuthInfo return Base64.encode(time ~ data); } - NonceState checkNonce(in string nonce, in HTTPServerRequest req) + NonceState checkNonce(string nonce, scope const HTTPServerRequest req) { auto now = Clock.currTime(UTC()).stdTime(); ubyte[] decoded = Base64.decode(nonce); if (decoded.length != now.sizeof + secret.length) return NonceState.Invalid; auto timebytes = decoded[0 .. now.sizeof]; auto time = () @trusted { return (cast(typeof(now)[])timebytes)[0]; } (); - if (timeout + time > now) return NonceState.Expired; + if (timeout.total!"hnsecs" + time < now) return NonceState.Expired; MD5 md5; md5.put(timebytes); md5.put(secret); @@ -66,6 +66,14 @@ class DigestAuthInfo } } +unittest +{ + auto authInfo = new DigestAuthInfo; + auto req = createTestHTTPServerRequest(URL("http://localhost/")); + auto nonce = authInfo.createNonce(req); + assert(authInfo.checkNonce(nonce, req) == NonceState.Valid); +} + private bool checkDigest(scope HTTPServerRequest req, DigestAuthInfo info, scope DigestHashCallback pwhash, out bool stale, out string username) { stale = false; diff --git a/source/vibe/http/client.d b/source/vibe/http/client.d index 9485c3d..5a0062c 100644 --- a/source/vibe/http/client.d +++ b/source/vibe/http/client.d @@ -77,11 +77,7 @@ HTTPClientResponse requestHTTP(string url, scope void delegate(scope HTTPClientR /// ditto HTTPClientResponse requestHTTP(URL url, scope void delegate(scope HTTPClientRequest req) requester = null, const(HTTPClientSettings) settings = defaultSettings) { - import std.algorithm.searching : canFind; - - bool use_tls = isTLSRequired(url, settings); - - auto cli = connectHTTP(url.getFilteredHost, url.port, use_tls, settings); + auto cli = connectHTTP(url, settings); auto res = cli.request( (scope req){ httpRequesterDg(req, url, settings, requester); }, ); @@ -100,9 +96,7 @@ void requestHTTP(string url, scope void delegate(scope HTTPClientRequest req) re /// ditto void requestHTTP(URL url, scope void delegate(scope HTTPClientRequest req) requester, scope void delegate(scope HTTPClientResponse req) responder, const(HTTPClientSettings) settings = defaultSettings) { - bool use_tls = isTLSRequired(url, settings); - - auto cli = connectHTTP(url.getFilteredHost, url.port, use_tls, settings); + auto cli = connectHTTP(url, settings); cli.request( (scope req){ httpRequesterDg(req, url, settings, requester); }, responder @@ -197,7 +191,7 @@ auto connectHTTP(string host, ushort port = 0, bool use_tls = false, const(HTTPC auto sttngs = settings ? settings : defaultSettings; if (port == 0) port = use_tls ? 443 : 80; - auto ckey = ConnInfo(host, port, use_tls, sttngs.proxyURL.host, sttngs.proxyURL.port, sttngs.networkInterface); + auto ckey = ConnInfo(host, sttngs.tlsPeerName, port, use_tls, sttngs.proxyURL.host, sttngs.proxyURL.port, sttngs.networkInterface); ConnectionPool!HTTPClient pool; s_connections.opApply((ref c) @safe { @@ -207,7 +201,7 @@ auto connectHTTP(string host, ushort port = 0, bool use_tls = false, const(HTTPC }); if (!pool) { - logDebug("Create HTTP client pool %s:%s %s proxy %s:%d", host, port, use_tls, sttngs.proxyURL.host, sttngs.proxyURL.port); + logDebug("Create HTTP client pool %s(%s):%s %s proxy %s:%d", host, sttngs.tlsPeerName, port, use_tls, sttngs.proxyURL.host, sttngs.proxyURL.port); pool = new ConnectionPool!HTTPClient({ auto ret = new HTTPClient; ret.connect(host, port, use_tls, sttngs); @@ -220,6 +214,13 @@ auto connectHTTP(string host, ushort port = 0, bool use_tls = false, const(HTTPC return pool.lockConnection(); } +/// Ditto +auto connectHTTP(URL url, const(HTTPClientSettings) settings = null) +{ + const use_tls = isTLSRequired(url, settings); + return connectHTTP(url.getFilteredHost, url.port, use_tls, settings); +} + static ~this() { foreach (ci; s_connections) { @@ -229,7 +230,7 @@ static ~this() } } -private struct ConnInfo { string host; ushort port; bool useTLS; string proxyIP; ushort proxyPort; NetworkAddress bind_addr; } +private struct ConnInfo { string host; string tlsPeerName; ushort port; bool useTLS; string proxyIP; ushort proxyPort; NetworkAddress bind_addr; } private static vibe.utils.array.FixedRingBuffer!(Tuple!(ConnInfo, ConnectionPool!HTTPClient), 16) s_connections; @@ -244,13 +245,7 @@ class HTTPClientSettings { URL proxyURL; Duration defaultKeepAliveTimeout = 10.seconds; - /** Timeout for establishing a connection to the server - - Note that this setting is only supported when using the vibe-core - module. If using one of the legacy drivers, any value other than - `Duration.max` will emit a runtime warning and connects without a - specific timeout. - */ + /// Timeout for establishing a connection to the server Duration connectTimeout = Duration.max; /// Timeout during read operations on the underyling transport @@ -268,6 +263,13 @@ class HTTPClientSettings { */ void delegate(TLSContext ctx) @safe nothrow tlsContextSetup; + /** + TLS Peer name override. + + Allows to customize the tls peer name sent to server during the TLS connection setup (SNI) + */ + string tlsPeerName; + @property HTTPClientSettings dup() const @safe { auto ret = new HTTPClientSettings; @@ -277,6 +279,7 @@ class HTTPClientSettings { ret.networkInterface = this.networkInterface; ret.dnsAddressFamily = this.dnsAddressFamily; ret.tlsContextSetup = this.tlsContextSetup; + ret.tlsPeerName = this.tlsPeerName; return ret; } } @@ -294,8 +297,8 @@ unittest { }, (scope res){ logInfo("Headers:"); - foreach(h; res.headers.byKeyValue) { - logInfo("%s: %s", h.key, h.value); + foreach (key, ref value; res.headers.byKeyValue) { + logInfo("%s: %s", key, value); } logInfo("Response: %s", res.bodyReader.readAllUTF8()); }, settings); @@ -377,6 +380,7 @@ final class HTTPClient { private { Rebindable!(const(HTTPClientSettings)) m_settings; string m_server; + string m_tlsPeerName; ushort m_port; bool m_useTLS; TCPConnection m_conn; @@ -409,9 +413,11 @@ final class HTTPClient { static void setTLSSetupCallback(void function(TLSContext) @safe func) @trusted { ms_tlsSetup = func; } /** - Connects to a specific server. + Sets up this HTTPClient to connect to a specific server. This method may only be called if any previous connection has been closed. + + The actual connection is deferred until a request is initiated (using `HTTPClient.request`). */ void connect(string server, ushort port = 80, bool use_tls = false, const(HTTPClientSettings) settings = defaultSettings) { @@ -423,6 +429,7 @@ final class HTTPClient { m_keepAliveTimeout = settings.defaultKeepAliveTimeout; m_keepAliveLimit = Clock.currTime(UTC()) + m_keepAliveTimeout; m_server = server; + m_tlsPeerName = settings.tlsPeerName.length ? settings.tlsPeerName : server; m_port = port; m_useTLS = use_tls; if (use_tls) { @@ -502,13 +509,15 @@ final class HTTPClient { m_responding = true; static if (is(T == HTTPClientResponse)) - res = new HTTPClientResponse(this, has_body, close_conn, request_allocator, connected_time); + res = new HTTPClientResponse(this, close_conn); else - res = scoped!HTTPClientResponse(this, has_body, close_conn, request_allocator, connected_time); + res = scoped!HTTPClientResponse(this, close_conn); + + res.initialize(has_body, request_allocator, connected_time); if (res.headers.get("Proxy-Authenticate", null) !is null){ res.dropBody(); - throw new HTTPStatusException(HTTPStatus.ProxyAuthenticationRequired, "Proxy Authentication Failed."); + throw new HTTPStatusException(HTTPStatus.proxyAuthenticationRequired, "Proxy Authentication Failed."); } } @@ -549,7 +558,8 @@ final class HTTPClient { bool has_body = doRequestWithRetry(requester, false, close_conn, connected_time); m_responding = true; - auto res = scoped!HTTPClientResponse(this, has_body, close_conn, request_allocator, connected_time); + auto res = scoped!HTTPClientResponse(this, close_conn); + res.initialize(has_body, request_allocator, connected_time); // proxy implementation if (res.headers.get("Proxy-Authenticate", null) !is null) { @@ -568,7 +578,8 @@ final class HTTPClient { // just an informational status -> read and handle next response if (m_responding) res.dropBody(); if (m_conn) { - res = scoped!HTTPClientResponse(this, has_body, close_conn, request_allocator, connected_time); + res = scoped!HTTPClientResponse(this, close_conn); + res.initialize(has_body, request_allocator, connected_time); continue; } } @@ -596,7 +607,8 @@ final class HTTPClient { } bool has_body = doRequestWithRetry(requester, false, close_conn, connected_time); m_responding = true; - auto res = new HTTPClientResponse(this, has_body, close_conn, () @trusted { return vibeThreadAllocator(); } (), connected_time); + auto res = new HTTPClientResponse(this, close_conn); + res.initialize(has_body, () @trusted { return vibeThreadAllocator(); } (), connected_time); // proxy implementation if (res.headers.get("Proxy-Authenticate", null) !is null) { @@ -608,7 +620,7 @@ final class HTTPClient { private bool doRequestWithRetry(scope void delegate(HTTPClientRequest req) requester, bool confirmed_proxy_auth /* basic only */, out bool close_conn, out SysTime connected_time) { - if (m_conn && m_conn.connected && connected_time > m_keepAliveLimit){ + if (m_conn && m_conn.connected && Clock.currTime(UTC()) > m_keepAliveLimit){ logDebug("Disconnected to avoid timeout"); disconnect(); } @@ -719,7 +731,7 @@ final class HTTPClient { m_stream = m_conn; if (m_useTLS) { - try m_tlsStream = createTLSStream(m_conn, m_tls, TLSStreamState.connecting, m_server, m_conn.remoteAddress); + try m_tlsStream = createTLSStream(m_conn, m_tls, TLSStreamState.connecting, m_tlsPeerName, m_conn.remoteAddress); catch (Exception e) { m_conn.close(); m_conn = TCPConnection.init; @@ -768,13 +780,7 @@ final class HTTPClient { private auto connectTCPWithTimeout(NetworkAddress addr, NetworkAddress bind_address, Duration timeout) { - version (Have_vibe_core) { - return connectTCP(addr, bind_address, timeout); - } else { - if (timeout != Duration.max) - logWarn("HTTP client connect timeout is set, but not supported by the legacy vibe-d:core module."); - return connectTCP(addr, bind_address); - } + return connectTCP(addr, bind_address, timeout); } /** @@ -852,7 +858,7 @@ final class HTTPClientRequest : HTTPRequest { { import vibe.stream.wrapper : streamOutputRange; - headers["Content-Type"] = "application/json"; + headers["Content-Type"] = "application/json; charset=UTF-8"; // set an explicit content-length field if chunked encoding is not allowed if (!allow_chunked) { @@ -1016,16 +1022,19 @@ final class HTTPClientResponse : HTTPResponse { } /// private - this(HTTPClient client, bool has_body, bool close_conn, IAllocator alloc, SysTime connected_time = Clock.currTime(UTC())) - { + this(HTTPClient client, bool close_conn) + nothrow { m_client = client; m_closeConn = close_conn; + } + private void initialize(bool has_body, IAllocator alloc, SysTime connected_time = Clock.currTime(UTC())) + { scope(failure) finalize(true); // read and parse status line ("HTTP/#.# #[ $]\r\n") logTrace("HTTP client reading status line"); - string stln = () @trusted { return cast(string)client.m_stream.readLine(HTTPClient.maxHeaderLineLength, "\r\n", alloc); } (); + string stln = () @trusted { return cast(string)m_client.m_stream.readLine(HTTPClient.maxHeaderLineLength, "\r\n", alloc); } (); logTrace("stln: %s", stln); this.httpVersion = parseHTTPVersion(stln); @@ -1039,7 +1048,7 @@ final class HTTPClientResponse : HTTPResponse { } // read headers until an empty line is hit - parseRFC5322Header(client.m_stream, this.headers, HTTPClient.maxHeaderLineLength, alloc, false); + parseRFC5322Header(m_client.m_stream, this.headers, HTTPClient.maxHeaderLineLength, alloc, false); logTrace("---------------------"); logTrace("HTTP client response:"); @@ -1258,6 +1267,7 @@ final class HTTPClientResponse : HTTPResponse { auto cli = m_client; m_client = null; cli.m_responding = false; + destroy(m_endCallback); destroy(m_zlibInputStream); destroy(m_chunkedInputStream); destroy(m_limitedInputStream); @@ -1282,7 +1292,7 @@ package auto getFilteredHost(URL url) // This object is a placeholder and should to never be modified. package @property const(HTTPClientSettings) defaultSettings() -@trusted { +@trusted nothrow { __gshared HTTPClientSettings ret = new HTTPClientSettings; return ret; } diff --git a/source/vibe/http/common.d b/source/vibe/http/common.d index 540819a..e9d368e 100644 --- a/source/vibe/http/common.d +++ b/source/vibe/http/common.d @@ -1,7 +1,7 @@ /** Common classes for HTTP clients and servers. - Copyright: © 2012-2015 RejectedSoftware e.K. + Copyright: © 2012-2015 Sönke Ludwig License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig, Jan Krüger */ @@ -15,10 +15,10 @@ import vibe.inet.message; import vibe.stream.operations; import vibe.textfilter.urlencode : urlEncode, urlDecode; import vibe.utils.array; +import vibe.utils.dictionarylist; +import vibe.internal.allocator; import vibe.internal.freelistref; import vibe.internal.interfaceproxy : InterfaceProxy, interfaceProxy; -import vibe.internal.allocator; -import vibe.utils.dictionarylist; import vibe.utils.string; import std.algorithm; @@ -30,12 +30,12 @@ import std.format; import std.range : isOutputRange; import std.string; import std.typecons; +import std.uni: asLowerCase, sicmp; enum HTTPVersion { HTTP_1_0, - HTTP_1_1, - HTTP_2 + HTTP_1_1 } @@ -213,6 +213,8 @@ class HTTPRequest { { } + scope: + public override string toString() { return httpMethodString(method) ~ " " ~ requestURL ~ " " ~ getHTTPVersionString(httpVersion); @@ -261,10 +263,10 @@ class HTTPRequest { auto ph = "connection" in headers; switch(httpVersion) { case HTTPVersion.HTTP_1_0: - if (ph && toLower(*ph) == "keep-alive") return true; + if (ph && asLowerCase(*ph).equal("keep-alive")) return true; return false; case HTTPVersion.HTTP_1_1: - if (ph && toLower(*ph) != "keep-alive") return false; + if (ph && !(asLowerCase(*ph).equal("keep-alive"))) return false; return true; default: return false; @@ -286,7 +288,7 @@ class HTTPResponse { HTTPVersion httpVersion = HTTPVersion.HTTP_1_1; /// The status code of the response, 200 by default - int statusCode = HTTPStatus.OK; + int statusCode = HTTPStatus.ok; /** The status phrase of the response @@ -301,6 +303,8 @@ class HTTPResponse { @property ref DictionaryList!Cookie cookies() { return m_cookies; } } + scope: + public override string toString() { auto app = appender!string(); @@ -322,7 +326,7 @@ class HTTPResponse { Throwing this exception from within a request handler will produce a matching error page. */ class HTTPStatusException : Exception { - @safe: + pure nothrow @safe @nogc: private { int m_status; @@ -330,7 +334,7 @@ class HTTPStatusException : Exception { this(int status, string message = null, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { - super(message != "" ? message : httpStatusText(status), file, line, next); + super(message.length ? message : httpStatusText(status), file, line, next); m_status = status; } @@ -349,26 +353,27 @@ final class MultiPart { string[string] form; } +/** + * Returns: + * The version string corresponding to the `ver`, + * suitable for usage in the start line of the request. + */ string getHTTPVersionString(HTTPVersion ver) -@safe nothrow { +nothrow pure @nogc @safe { final switch(ver){ case HTTPVersion.HTTP_1_0: return "HTTP/1.0"; case HTTPVersion.HTTP_1_1: return "HTTP/1.1"; - case HTTPVersion.HTTP_2: return "HTTP/2"; } } HTTPVersion parseHTTPVersion(ref string str) @safe { - enforceBadRequest(str.startsWith("HTTP/")); - str = str[5 .. $]; - int majorVersion = parse!int(str); - enforceBadRequest(str.startsWith(".")); - str = str[1 .. $]; + enforceBadRequest(str.startsWith("HTTP/1.")); + str = str[7 .. $]; int minorVersion = parse!int(str); - enforceBadRequest( majorVersion == 1 && (minorVersion == 0 || minorVersion == 1) ); + enforceBadRequest( minorVersion == 0 || minorVersion == 1 ); return minorVersion == 0 ? HTTPVersion.HTTP_1_0 : HTTPVersion.HTTP_1_1; } @@ -385,12 +390,6 @@ final class ChunkedInputStream : InputStream ulong m_bytesInCurrentChunk = 0; } - deprecated("Use createChunkedInputStream() instead.") - this(InputStream stream) - { - this(interfaceProxy!InputStream(stream), true); - } - /// private this(InterfaceProxy!InputStream stream, bool dummy) { @@ -489,17 +488,11 @@ final class ChunkedOutputStream : OutputStream { ChunkExtensionCallback m_chunkExtensionCallback = null; } - deprecated("Use createChunkedOutputStream() instead.") - this(OutputStream stream, IAllocator alloc = vibeThreadAllocator()) - { - this(interfaceProxy!OutputStream(stream), alloc, true); - } - /// private this(InterfaceProxy!OutputStream stream, IAllocator alloc, bool dummy) { m_out = stream; - m_buffer = AllocAppender!(ubyte[])(alloc); + m_buffer = AllocAppender!(ubyte[])(alloc); } /** Maximum buffer size used to buffer individual chunks. @@ -548,7 +541,15 @@ final class ChunkedOutputStream : OutputStream { } } - size_t write(in ubyte[] bytes_, IOMode mode) + static if (is(typeof(.OutputStream.outputStreamVersion)) && .OutputStream.outputStreamVersion > 1) { + override size_t write(scope const(ubyte)[] bytes_, IOMode mode) { return doWrite(bytes_, mode); } + } else { + override size_t write(in ubyte[] bytes_, IOMode mode) { return doWrite(bytes_, mode); } + } + + alias write = OutputStream.write; + + private size_t doWrite(scope const(ubyte)[] bytes_, IOMode mode) { assert(!m_finalized); const(ubyte)[] bytes = bytes_; @@ -568,8 +569,6 @@ final class ChunkedOutputStream : OutputStream { return nbytes; } - alias write = OutputStream.write; - void flush() { assert(!m_finalized); @@ -612,18 +611,17 @@ final class ChunkedOutputStream : OutputStream { } /// Creates a new `ChunkedInputStream` instance. -ChunkedOutputStream createChunkedOutputStream(OS)(OS destination_stream, IAllocator allocator = vibeThreadAllocator()) if (isOutputStream!OS) +ChunkedOutputStream createChunkedOutputStream(OS)(OS destination_stream, IAllocator allocator = theAllocator()) if (isOutputStream!OS) { return new ChunkedOutputStream(interfaceProxy!OutputStream(destination_stream), allocator, true); } /// Creates a new `ChunkedOutputStream` instance. -FreeListRef!ChunkedOutputStream createChunkedOutputStreamFL(OS)(OS destination_stream, IAllocator allocator = vibeThreadAllocator()) if (isOutputStream!OS) +FreeListRef!ChunkedOutputStream createChunkedOutputStreamFL(OS)(OS destination_stream, IAllocator allocator = theAllocator()) if (isOutputStream!OS) { return FreeListRef!ChunkedOutputStream(interfaceProxy!OutputStream(destination_stream), allocator, true); } - /// Parses the cookie from a header field, returning the name of the cookie. /// Implements an algorithm equivalent to https://tools.ietf.org/html/rfc6265#section-5.2 /// Returns: the cookie name as return value, populates the dst argument or allocates on the GC for the tuple overload. @@ -632,8 +630,6 @@ string parseHTTPCookie(string header_string, scope Cookie dst) in { assert(dst !is null); } do { - import std.uni : sicmp; - if (!header_string.length) return typeof(return).init; @@ -714,6 +710,7 @@ final class Cookie { long m_maxAge; bool m_secure; bool m_httpOnly; + SameSite m_sameSite; } enum Encoding { @@ -722,6 +719,12 @@ final class Cookie { none = raw } + enum SameSite { + default_, + lax, + strict, + } + /// Cookie payload @property void value(string value) { m_value = urlEncode(value); } /// ditto @@ -772,6 +775,12 @@ final class Cookie { /// ditto @property bool httpOnly() const { return m_httpOnly; } + /** Prevent cross-site request forgery. + */ + @property void sameSite(Cookie.SameSite value) { m_sameSite = value; } + /// ditto + @property Cookie.SameSite sameSite() const { return m_sameSite; } + /** Sets the "expires" and "max-age" attributes to limit the life time of the cookie. */ @@ -820,6 +829,12 @@ final class Cookie { if (this.maxAge) dst.formattedWrite("; Max-Age=%s", this.maxAge); if (this.secure) dst.put("; Secure"); if (this.httpOnly) dst.put("; HttpOnly"); + with(Cookie.SameSite) + final switch(this.sameSite) { + case default_: break; + case lax: dst.put("; SameSite=Lax"); break; + case strict: dst.put("; SameSite=Strict"); break; + } } private static void validateValue(string value) @@ -849,6 +864,43 @@ unittest { assertThrown(c.value); assertThrown(c.setValue("foo;bar", Cookie.Encoding.raw)); + + auto tup = parseHTTPCookie("foo=bar; HttpOnly; Secure; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Max-Age=60000; Domain=foo.com; Path=/users"); + assert(tup[0] == "foo"); + assert(tup[1].value == "bar"); + assert(tup[1].httpOnly == true); + assert(tup[1].secure == true); + assert(tup[1].expires == "Wed, 09 Jun 2021 10:18:14 GMT"); + assert(tup[1].maxAge == 60000L); + assert(tup[1].domain == "foo.com"); + assert(tup[1].path == "/users"); + + tup = parseHTTPCookie("SESSIONID=0123456789ABCDEF0123456789ABCDEF; Path=/site; HttpOnly"); + assert(tup[0] == "SESSIONID"); + assert(tup[1].value == "0123456789ABCDEF0123456789ABCDEF"); + assert(tup[1].httpOnly == true); + assert(tup[1].secure == false); + assert(tup[1].expires == ""); + assert(tup[1].maxAge == 0); + assert(tup[1].domain == ""); + assert(tup[1].path == "/site"); + + tup = parseHTTPCookie("invalid"); + assert(!tup[0].length); + + tup = parseHTTPCookie("valid="); + assert(tup[0] == "valid"); + assert(tup[1].value == ""); + + tup = parseHTTPCookie("valid=;Path=/bar;Path=foo;Expires=14 ; Something ; Domain=..example.org"); + assert(tup[0] == "valid"); + assert(tup[1].value == ""); + assert(tup[1].httpOnly == false); + assert(tup[1].secure == false); + assert(tup[1].expires == ""); + assert(tup[1].maxAge == 0); + assert(tup[1].domain == ".example.org"); // spec says you must strip only the first leading dot + assert(tup[1].path == ""); } diff --git a/source/vibe/http/dist.d b/source/vibe/http/dist.d new file mode 100644 index 0000000..c45f11a --- /dev/null +++ b/source/vibe/http/dist.d @@ -0,0 +1,52 @@ +/** + Interface for the VibeDist load balancer + + Copyright: © 2012-2013 Sönke Ludwig + License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. + Authors: Sönke Ludwig, Jan Krüger +*/ +module vibe.http.dist; + +import vibe.core.log; +import vibe.data.json; +import vibe.inet.url; +import vibe.http.client; +import vibe.http.server; + +import std.conv; +import std.exception; +import std.process; + + +/** + Listens for HTTP connections on the specified load balancer using the given HTTP server settings. + + This function is usable as direct replacement of listenHTTP +*/ +HTTPListener listenHTTPDist(HTTPServerSettings settings, HTTPServerRequestDelegate handler, string balancer_address, ushort balancer_port = 11000) +@safe { + Json regmsg = Json.emptyObject; + regmsg["host_name"] = settings.hostName; + regmsg["port"] = settings.port; + regmsg["ssl_settings"] = ""; + regmsg["pid"] = thisProcessID; + //regmsg.sslContext = settings.sslContext; // TODO: send key/cert contents + + HTTPServerSettings local_settings = settings.dup; + local_settings.bindAddresses = ["127.0.0.1"]; + local_settings.port = 0; + local_settings.disableDistHost = true; + auto ret = listenHTTP(local_settings, handler); + + requestHTTP(URL("http://"~balancer_address~":"~to!string(balancer_port)~"/register"), (scope req){ + logInfo("Listening for VibeDist connections on port %d", req.localAddress.port); + regmsg["local_address"] = "127.0.0.1"; + regmsg["local_port"] = req.localAddress.port; + req.method = HTTPMethod.POST; + req.writeJsonBody(regmsg); + }, (scope res){ + enforce(res.statusCode == HTTPStatus.ok, "Failed to register with load balancer."); + }); + + return ret; +} diff --git a/source/vibe/http/fileserver.d b/source/vibe/http/fileserver.d index e76a28c..8f5b82b 100644 --- a/source/vibe/http/fileserver.d +++ b/source/vibe/http/fileserver.d @@ -55,7 +55,7 @@ HTTPServerRequestDelegateS serveStaticFiles(NativePath local_path, HTTPFileServe @safe { string srv_path; if (auto pp = "pathMatch" in req.params) srv_path = *pp; - else if (req.path.length > 0) srv_path = req.path; + else if (req.requestPath != InetPath.init) srv_path = (cast(PosixPath)req.requestPath).toString(); else srv_path = req.requestURL; if (!srv_path.startsWith(settings.serverPathPrefix)) { @@ -282,14 +282,14 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse // return if the file does not exist if (!existsFile(pathstr)){ if (settings.options & HTTPFileServerOption.failIfNotFound) - throw new HTTPStatusException(HTTPStatus.NotFound); + throw new HTTPStatusException(HTTPStatus.notFound); return; } FileInfo dirent; try dirent = getFileInfo(pathstr); catch(Exception){ - throw new HTTPStatusException(HTTPStatus.InternalServerError, "Failed to get information for the file due to a file system error."); + throw new HTTPStatusException(HTTPStatus.internalServerError, "Failed to get information for the file due to a file system error."); } if (dirent.isDirectory) { @@ -297,7 +297,7 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse return sendFileImpl(req, res, path ~ "index.html", settings); logDebugV("Hit directory when serving files, ignoring: %s", pathstr); if (settings.options & HTTPFileServerOption.failIfNotFound) - throw new HTTPStatusException(HTTPStatus.NotFound); + throw new HTTPStatusException(HTTPStatus.notFound); return; } @@ -320,7 +320,7 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse range = parseRangeHeader(*prange, dirent.size, res); // potential integer overflow with rangeEnd - rangeStart == size_t.max is intended. This only happens with empty files, the + 1 will then put it back to 0 - res.headers["Content-Length"] = to!string(range.min - range.max); + res.headers["Content-Length"] = to!string(range.max - range.min); res.headers["Content-Range"] = "bytes %s-%s/%s".format(range.min, range.max - 1, dirent.size); res.statusCode = HTTPStatus.partialContent; } else res.headers["Content-Length"] = dirent.size.to!string; @@ -341,7 +341,7 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse try dirent = getFileInfo(encodedFilepath); catch(Exception){ - throw new HTTPStatusException(HTTPStatus.InternalServerError, "Failed to get information for the file due to a file system error."); + throw new HTTPStatusException(HTTPStatus.internalServerError, "Failed to get information for the file due to a file system error."); } // encoded file must be younger than original else warn diff --git a/source/vibe/http/form.d b/source/vibe/http/form.d index 2a46b91..7a772af 100644 --- a/source/vibe/http/form.d +++ b/source/vibe/http/form.d @@ -5,7 +5,6 @@ License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Sönke Ludwig, Jan Krüger */ -deprecated("Use vibe.inet.webform instead") module vibe.http.form; public import vibe.inet.webform; diff --git a/source/vibe/http/headers.d b/source/vibe/http/headers.d deleted file mode 100644 index 1501cfa..0000000 --- a/source/vibe/http/headers.d +++ /dev/null @@ -1,13 +0,0 @@ -module vibe.http.headers; - -import taggedalgebraic; -import std.datetime.systime : SysTime; -import std.typecons : Tuple; - -struct HTTPHeaderValueTypes { - Tuple!(const(char)[], const(char)[]) generic; - SysTime date; - long contentLength; -} - -alias HTTPHeaderValue = TaggedAlgebraic!HTTPHeaderValueTypes; diff --git a/source/vibe/http/internal/http1.d b/source/vibe/http/internal/http1.d deleted file mode 100644 index ff10472..0000000 --- a/source/vibe/http/internal/http1.d +++ /dev/null @@ -1,514 +0,0 @@ -module vibe.http.internal.http1; - -import vibe.http.internal.http2.http2; -import vibe.http.internal.http2.settings; -import vibe.core.stream; -import vibe.core.core : runTask; -import vibe.core.net; -import vibe.http.server; -import vibe.core.stream; -import vibe.core.core : runTask; -import vibe.core.net; -import vibe.http.server; -import vibe.internal.allocator; -import vibe.internal.freelistref; -import vibe.internal.interfaceproxy : InterfaceProxy; -import vibe.core.file; -import vibe.core.log; -import vibe.inet.url; -import vibe.inet.webform; -import vibe.data.json; -import vibe.stream.wrapper : ConnectionProxyStream, createConnectionProxyStream, createConnectionProxyStreamFL; -import vibe.utils.array; -import vibe.utils.string; -import vibe.stream.counting; -import vibe.stream.operations; -import vibe.stream.zlib; -import vibe.textfilter.urlencode : urlEncode, urlDecode; -import vibe.stream.tls; - -import std.datetime; -import std.typecons; -import std.conv; -import std.array; -import std.algorithm; -import std.format; -import std.parallelism; -import std.exception; -import std.string; -import std.encoding : sanitize; -import std.traits : isInstanceOf, ReturnType; - -private alias TLSStreamType = ReturnType!(createTLSStreamFL!(InterfaceProxy!Stream)); - -void handleHTTP1Connection(ConnectionStream)(ConnectionStream connection, HTTPServerContext context) -@safe if (isConnectionStream!ConnectionStream) -{ - connection.tcpNoDelay = true; - - //logInfo("Connection"); - version(HaveNoTLS) {} else { - TLSStreamType tls_stream; - } - - // If this is a HTTPS server, initiate TLS - if (context.tlsContext) { - version (HaveNoTLS) assert(false, "No TLS support compiled in."); - else { - - logDebug("Accept TLS connection: %s", context.tlsContext.kind); - - //TODO: determine if there's a better alternative to InterfaceProxy - InterfaceProxy!Stream http_stream; - http_stream = connection; - - // TODO: reverse DNS lookup for peer_name of the incoming connection for TLS client certificate verification purposes - tls_stream = createTLSStreamFL(http_stream, context.tlsContext, TLSStreamState.accepting, null, connection.remoteAddress); - - Nullable!string proto = tls_stream.alpn; - if(!proto.isNull && proto == "h2") { - HTTP2Settings settings; - auto h2context = new HTTP2ServerContext(context, settings); - handleHTTP2Connection(tls_stream, connection, h2context); - return; - } - http_stream = tls_stream; - } - } - handleHTTP1RequestChain(connection, context); -} - -private void handleHTTP1RequestChain(ConnectionStream)(ConnectionStream connection, HTTPContext context) -@safe -{ - //logInfo("HTTP/1 Request Chain Handler"); - - // copies connection/context instead of creating a heap closure - static struct CB { - ConnectionStream connection; - HTTPContext context; - - void opCall(bool st) - { - if (!st) connection.close; - else runTask(&handleHTTP1RequestChain, connection, context); - } - } - - while(true) { - CB cb = {connection, context}; - auto st = connection.waitForDataAsync(cb); - - final switch(st) { - case WaitForDataAsyncStatus.waiting: return; - case WaitForDataAsyncStatus.noMoreData: connection.close; return; - case WaitForDataAsyncStatus.dataAvailable: handleHTTP1Request(connection, context); break; - } - } -} - -private void handleHTTP1Request(ConnectionStream)(ConnectionStream connection, HTTPContext context) -@safe -{ - //logInfo("HTTP/1 Request Handler"); - - HTTPServerSettings settings; - InterfaceProxy!Stream http_stream; - http_stream = connection; - bool keep_alive; - () @trusted { - import vibe.internal.utilallocator: RegionListAllocator; - version (VibeManualMemoryManagement) - scope request_allocator = new RegionListAllocator!(shared(Mallocator), false)(1024, Mallocator.instance); - else - scope request_allocator = new RegionListAllocator!(shared(GCAllocator), true)(1024, GCAllocator.instance); - - originalHandleRequest(http_stream, connection, context, settings, keep_alive, request_allocator); - - if (!keep_alive) { connection.close; return; } - } (); - - if(!connection.waitForData()) { - connection.close; - logWarn("Reached end of stream while reading."); - } -} - - -/* Previous vibe.http handleRequest - * Gets called by handleHTTP1Request - */ -private bool originalHandleRequest(InterfaceProxy!Stream http_stream, TCPConnection tcp_connection, HTTPServerContext listen_info, HTTPServerSettings settings, ref bool keep_alive, scope IAllocator request_allocator) -@safe { - - //logInfo ("Old request handler"); - import std.algorithm.searching : canFind; - - SysTime reqtime = Clock.currTime(UTC()); - - // some instances that live only while the request is running - //FreeListRef!HTTPServerRequest req = FreeListRef!HTTPServerRequest(reqtime, listen_info.bindPort); - auto req = HTTPServerRequest(reqtime, listen_info.bindPort); - - FreeListRef!TimeoutHTTPInputStream timeout_http_input_stream; - FreeListRef!LimitedHTTPInputStream limited_http_input_stream; - FreeListRef!ChunkedInputStream chunked_input_stream; - - // store the IP address - req.clientAddress = tcp_connection.remoteAddress; - - if (!listen_info.hasVirtualHosts) { - logWarn("Didn't find a HTTP listening context for incoming connection. Dropping."); - keep_alive = false; - return false; - } - - // Default to the first virtual host for this listener - HTTPServerContext.VirtualHost context = listen_info.virtualHosts[0]; - HTTPServerRequestDelegate request_task = context.requestHandler; - settings = context.settings; - - // temporarily set to the default settings, the virtual host specific settings will be set further down - req.m_settings = settings; - - // Create the response object - InterfaceProxy!ConnectionStream cproxy = tcp_connection; - auto res = HTTPServerResponse(http_stream, cproxy, settings, request_allocator/*.Scoped_payload*/); - auto istls = listen_info.tlsContext !is null; - req.tls = istls; - res.tls = istls; - - if (req.tls) { - version (HaveNoTLS) assert(false); - else { - static if (is(InterfaceProxy!ConnectionStream == ConnectionStream)) - req.clientCertificate = (cast(TLSStream)http_stream).peerCertificate; - else if (is(typeof(http_stream) : TLSStream)) - req.clientCertificate = http_stream.extract!TLSStreamType.peerCertificate; - else - // TODO fix: no client certificate - assert(false); - } - } - - // Error page handler - void errorOut(int code, string msg, string debug_msg, Throwable ex) - @safe { - assert(!res.headerWritten); - - // stack traces sometimes contain random bytes - make sure they are replaced - debug_msg = sanitizeUTF8(cast(const(ubyte)[])debug_msg); - - res.setStatusCode(code); - if (settings.errorPageHandler) { - //[>scope<] auto err = new HTTPServerErrorInfo; - HTTPServerErrorInfo err; - err.code = code; - err.message = msg; - err.debugMessage = debug_msg; - err.exception = ex; - settings.handleErrorPage(req, res, err); - } else { - if (debug_msg.length) - res.writeBody(format("%s - %s\n\n%s\n\nInternal error information:\n%s", code, httpStatusText(code), msg, debug_msg)); - else res.writeBody(format("%s - %s\n\n%s", code, httpStatusText(code), msg)); - } - assert(res.headerWritten); - } - - bool parsed = false; - /*bool*/ keep_alive = false; - - // parse the request - try { - logTrace("reading request.."); - - // limit the total request time - InterfaceProxy!InputStream reqReader = http_stream; - if (settings.maxRequestTime > dur!"seconds"(0) && settings.maxRequestTime != Duration.max) { - timeout_http_input_stream = FreeListRef!TimeoutHTTPInputStream(reqReader, settings.maxRequestTime, reqtime); - reqReader = timeout_http_input_stream; - } - - // basic request parsing - uint h2 = parseRequestHeader(req, reqReader, request_allocator, settings.maxRequestHeaderSize); - if(h2) { - // start http/2 with prior knowledge - uint len = 22 - h2; - ubyte[] dummy; dummy.length = len; - - http_stream.read(dummy); // finish reading connection preface - auto h2settings = HTTP2Settings(); - auto h2context = new HTTP2ServerContext(listen_info, h2settings); - handleHTTP2Connection(tcp_connection, tcp_connection, h2context, true); - return true; - } - - logTrace("Got request header."); - - // find the matching virtual host - string reqhost; - ushort reqport = 0; - { - string s = req.host; - enforceHTTP(s.length > 0 || req.httpVersion <= HTTPVersion.HTTP_1_0, HTTPStatus.badRequest, "Missing Host header."); - if (s.startsWith('[')) { // IPv6 address - auto idx = s.indexOf(']'); - enforce(idx > 0, "Missing closing ']' for IPv6 address."); - reqhost = s[1 .. idx]; - s = s[idx+1 .. $]; - } else if (s.length) { // host name or IPv4 address - auto idx = s.indexOf(':'); - if (idx < 0) idx = s.length; - enforceHTTP(idx > 0, HTTPStatus.badRequest, "Missing Host header."); - reqhost = s[0 .. idx]; - s = s[idx .. $]; - } - if (s.startsWith(':')) reqport = s[1 .. $].to!ushort; - } - - foreach (ctx; listen_info.virtualHosts) - if (icmp2(ctx.settings.hostName, reqhost) == 0 && - (!reqport || reqport == ctx.settings.port)) - { - context = ctx; - settings = ctx.settings; - request_task = ctx.requestHandler; - break; - } - req.m_settings = settings; - res.m_settings = settings; - - // setup compressed output - if (settings.useCompressionIfPossible) { - if (auto pae = "Accept-Encoding" in req.headers) { - if (canFind(*pae, "gzip")) { - res.headers["Content-Encoding"] = "gzip"; - } else if (canFind(*pae, "deflate")) { - res.headers["Content-Encoding"] = "deflate"; - } - } - } - - // limit request size - if (auto pcl = "Content-Length" in req.headers) { - string v = *pcl; - auto contentLength = parse!ulong(v); // DMDBUG: to! thinks there is a H in the string - enforceBadRequest(v.length == 0, "Invalid content-length"); - enforceBadRequest(settings.maxRequestSize <= 0 || contentLength <= settings.maxRequestSize, "Request size too big"); - limited_http_input_stream = FreeListRef!LimitedHTTPInputStream(reqReader, contentLength); - } else if (auto pt = "Transfer-Encoding" in req.headers) { - enforceBadRequest(icmp(*pt, "chunked") == 0); - chunked_input_stream = createChunkedInputStreamFL(reqReader); - InterfaceProxy!InputStream ciproxy = chunked_input_stream; - limited_http_input_stream = FreeListRef!LimitedHTTPInputStream(ciproxy, settings.maxRequestSize, true); - } else { - limited_http_input_stream = FreeListRef!LimitedHTTPInputStream(reqReader, 0); - } - req.bodyReader = limited_http_input_stream; - - // handle Expect header - if (auto pv = "Expect" in req.headers) { - if (icmp2(*pv, "100-continue") == 0) { - logTrace("sending 100 continue"); - http_stream.write("HTTP/1.1 100 Continue\r\n\r\n"); - } - } - - // eagerly parse the URL as its lightweight and defacto @nogc - auto url = URL.parse(req.requestURI); - req.queryString = url.queryString; - req.username = url.username; - req.password = url.password; - req.requestPath = url.path; - - // lookup the session - if (settings.sessionStore) { - // use the first cookie that contains a valid session ID in case - // of multiple matching session cookies - foreach (val; req.cookies.getAll(settings.sessionIdCookie)) { - req.session = settings.sessionStore.open(val); - res.m_session = req.session; - if (req.session) break; - } - } - - // write default headers - if (req.method == HTTPMethod.HEAD) res.m_isHeadResponse = true; - if (settings.serverString.length) - res.headers["Server"] = settings.serverString; - res.headers["Date"] = formatRFC822DateAlloc(request_allocator, reqtime); - if (req.persistent) res.headers["Keep-Alive"] = formatAlloc(request_allocator, "timeout=%d", settings.keepAliveTimeout.total!"seconds"()); - - // finished parsing the request - parsed = true; - logTrace("persist: %s", req.persistent); - keep_alive = req.persistent; - - // handle the request - logTrace("handle request (body %d)", req.bodyReader.leastSize); - - /** - * UPGRADE TO HTTP/2 for cleartext HTTP/1 - * this requires that the "Upgrade" header is set - * with value "h2c" (for cleartext) - * "h2" is ignored since it is used for TLS protocol switching (ALPN) - */ - if(req.headers.get("Upgrade") == "h2c" ) { - import vibe.stream.memory; - import vibe.http.internal.http2.exchange; - - // write the original response to a buffer - string createResBuffer(ref MemoryOutputStream buf, ref size_t hlen) @trusted - { - res.bodyWriterH2(buf, true); - auto statusLine = (cast(string)buf.data).split("\r\n")[0]; - hlen = buf.data.length; - - // write body to buffer - request_task(req, res); - - // no matching path in handler - if(buf.data.length == hlen && req.method != HTTPMethod.HEAD) { - return "HTTP/2 404 Not Found\r\n"; - } - - //// matching path, data needs to be saved - //if(req.method != HTTPMethod.HEAD) { - //ctx.resBody = request_allocator.make!(ubyte)(buf.data[hlen..$]); - //} - - return statusLine; - } - - auto psettings = "HTTP2-Settings" in req.headers; - enforceHTTP(psettings !is null, HTTPStatus.badRequest, "Upgrade request must - include HTTP2-Settings"); - auto h2settings = *psettings; - - logInfo("Switching to HTTP/2"); - logTrace("handle request (body %d)", req.bodyReader.leastSize); - - // initialize the request handler - auto h2context = new HTTP2ServerContext(listen_info); - - MemoryOutputStream buf = createMemoryOutputStream(request_allocator); - size_t hlen; - auto st = createResBuffer(buf, hlen); - auto switchRes = HTTPServerResponse(http_stream, cproxy, settings, request_allocator); - - return startHTTP2Connection(tcp_connection, h2settings, h2context, switchRes, - res.headers, st, request_allocator, buf.data[hlen..$]); - } - - res.httpVersion = req.httpVersion; - request_task(req, res); - - - // if no one has written anything, return 404 - if (!res.headerWritten) { - string dbg_msg; - logDiagnostic("No response written for %s", req.requestURI); - if (settings.options & HTTPServerOption.errorStackTraces) - dbg_msg = format("No routes match path '%s'", req.requestURI); - errorOut(HTTPStatus.notFound, httpStatusText(HTTPStatus.notFound), dbg_msg, null); - } - } catch (HTTPStatusException err) { - if (!res.headerWritten) errorOut(err.status, err.msg, err.debugMessage, err); - else logDiagnostic("HTTPSterrorOutatusException while writing the response: %s", err.msg); - debug logDebug("Exception while handling request %s %s: %s", req.method, req.requestURI, () @trusted { return err.toString().sanitize; } ()); - if (!parsed || res.headerWritten || justifiesConnectionClose(err.status)) - keep_alive = false; - } catch (UncaughtException e) { - auto status = parsed ? HTTPStatus.internalServerError : HTTPStatus.badRequest; - string dbg_msg; - if (settings.options & HTTPServerOption.errorStackTraces) dbg_msg = () @trusted { return e.toString().sanitize; } (); - if (!res.headerWritten && tcp_connection.connected) errorOut(status, httpStatusText(status), dbg_msg, e); - else logDiagnostic("Error while writing the response: %s", e.msg); - debug logDebug("Exception while handling request %s %s: %s", req.method, req.requestURI, () @trusted { return e.toString().sanitize(); } ()); - if (!parsed || res.headerWritten || !cast(Exception)e) keep_alive = false; - } - - if (tcp_connection.connected) { - if (req.bodyReader && !req.bodyReader.empty) { - req.bodyReader.pipe(nullSink); - logTrace("dropped body"); - } - } - - // finalize (e.g. for chunked encoding) - res.finalize(); - - foreach (k, v ; req._files.byKeyValue) { - if (existsFile(v.tempPath)) { - removeFile(v.tempPath); - logDebug("Deleted upload tempfile %s", v.tempPath.toString()); - } - } - - if (!req.noLog) { - // log the request to access log - foreach (log; context.loggers) - log.log(req, res); - } - - //logTrace("return %s (used pool memory: %s/%s)", keep_alive, request_allocator.allocatedSize, request_allocator.totalSize); - logTrace("return %s", keep_alive); - return keep_alive != false; -} - -final class LimitedHTTPInputStream : LimitedInputStream { -@safe: - - this(InterfaceProxy!InputStream stream, ulong byte_limit, bool silent_limit = false) { - super(stream, byte_limit, silent_limit, true); - } - override void onSizeLimitReached() { - throw new HTTPStatusException(HTTPStatus.requestEntityTooLarge); - } -} - -final class TimeoutHTTPInputStream : InputStream { -@safe: - - private { - long m_timeref; - long m_timeleft; - InterfaceProxy!InputStream m_in; - } - - this(InterfaceProxy!InputStream stream, Duration timeleft, SysTime reftime) - { - enforce(timeleft > 0.seconds, "Timeout required"); - m_in = stream; - m_timeleft = timeleft.total!"hnsecs"(); - m_timeref = reftime.stdTime(); - } - - @property bool empty() { enforce(m_in, "InputStream missing"); return m_in.empty(); } - @property ulong leastSize() { enforce(m_in, "InputStream missing"); return m_in.leastSize(); } - @property bool dataAvailableForRead() { enforce(m_in, "InputStream missing"); return m_in.dataAvailableForRead; } - const(ubyte)[] peek() { return m_in.peek(); } - - size_t read(scope ubyte[] dst, IOMode mode) - { - enforce(m_in, "InputStream missing"); - size_t nread = 0; - checkTimeout(); - // FIXME: this should use ConnectionStream.waitForData to enforce the timeout during the - // read operation - return m_in.read(dst, mode); - } - - alias read = InputStream.read; - - private void checkTimeout() - @safe { - auto curr = Clock.currStdTime(); - auto diff = curr - m_timeref; - if (diff > m_timeleft) throw new HTTPStatusException(HTTPStatus.RequestTimeout); - m_timeleft -= diff; - m_timeref = curr; - } -} - diff --git a/source/vibe/http/internal/http2/error.d b/source/vibe/http/internal/http2/error.d deleted file mode 100644 index 4e00321..0000000 --- a/source/vibe/http/internal/http2/error.d +++ /dev/null @@ -1,84 +0,0 @@ -module vibe.http.internal.http2.error; - -import vibe.http.internal.http2.hpack.exception; -import vibe.http.internal.http2.frame; - -import vibe.core.log; -import vibe.core.net; -import vibe.core.core; -import vibe.core.stream; -import vibe.stream.tls; -import vibe.internal.array; -import vibe.internal.allocator; -import vibe.internal.freelistref; -import vibe.internal.interfaceproxy; - -import std.range; -import std.base64; -import std.traits; -import std.bitmanip; // read from ubyte (decoding) -import std.typecons; -import std.conv : to; -import std.exception; -import std.algorithm : canFind; // alpn callback -import std.algorithm.iteration; - -enum HTTP2Error { - NO_ERROR = 0x0, - PROTOCOL_ERROR = 0x1, - INTERNAL_ERROR = 0x2, - FLOW_CONTROL_ERROR = 0x3, - SETTINGS_TIMEOUT = 0x4, - STREAM_CLOSED = 0x5, - FRAME_SIZE_ERROR = 0x6, - REFUSED_STREAM = 0x7, - CANCEL = 0x8, - COMPRESSION_ERROR = 0x9, - CONNECT_ERROR = 0xa, - ENHANCE_YOUR_CALM = 0xb, - INADEQUATE_SECURITY = 0xc, - HTTP_1_1_REQUIRED = 0xd -} - -enum GOAWAYFrameLength = 17; - -/// creates a GOAWAY frame as defined in RFC 7540, section 6.8 -void buildGOAWAYFrame(R)(ref R buf, const uint streamId, HTTP2Error error) -@safe @nogc -{ - assert(buf.length == GOAWAYFrameLength, "Unable to create GOAWAY frame"); - - // last stream processed by the server (client-initiated) - uint sid = (streamId > 1) ? streamId - 2 : 0; - - buf.createHTTP2FrameHeader(8, HTTP2FrameType.GOAWAY, 0x0, 0x0); - buf.putBytes!4(sid & 127); // last stream ID - buf.putBytes!4(error); -} -/// ditto -auto buildGOAWAYFrame(uint sid, HTTP2Error code) @safe -{ - BatchBuffer!(ubyte, GOAWAYFrameLength) gbuf; - - gbuf.putN(GOAWAYFrameLength); - gbuf.buildGOAWAYFrame(sid, code); - - return gbuf.peekDst; -} - - -/// exceptions -T enforceHTTP2(T)(T condition, string message = null, HTTP2Error h2e = HTTP2Error.NO_ERROR, string file = __FILE__, typeof(__LINE__) line = __LINE__) @trusted -{ - return enforce(condition, new HTTP2Exception(message, h2e, file, line)); -} - -class HTTP2Exception : Exception -{ - HTTP2Error code; - - this(string msg, HTTP2Error h2e = HTTP2Error.NO_ERROR, string file = __FILE__, size_t line = __LINE__) { - code = h2e; - super(msg, file, line); - } -} diff --git a/source/vibe/http/internal/http2/exchange.d b/source/vibe/http/internal/http2/exchange.d deleted file mode 100644 index 8364b13..0000000 --- a/source/vibe/http/internal/http2/exchange.d +++ /dev/null @@ -1,585 +0,0 @@ -module vibe.http.internal.http2.exchange; - -import vibe.http.internal.http2.multiplexing; -import vibe.http.internal.http2.settings; -import vibe.http.internal.http2.http2 : HTTP2ConnectionStream, HTTP2StreamState; -import vibe.http.internal.http2.hpack.hpack; -import vibe.http.internal.http2.hpack.tables; -import vibe.http.internal.http2.frame; - -import vibe.http.common; -import vibe.http.status; -import vibe.http.server; -import vibe.core.log; -import vibe.core.stream; -import vibe.core.core; -import vibe.internal.interfaceproxy; -import vibe.stream.tls; -import vibe.internal.allocator; -import vibe.internal.array; -import vibe.internal.utilallocator: RegionListAllocator; -import vibe.stream.wrapper : ConnectionProxyStream, createConnectionProxyStream, createConnectionProxyStreamFL; -import vibe.utils.string; -import vibe.stream.memory; -import vibe.inet.url; -import vibe.inet.message; - -import std.range; -import std.string; -import std.conv; -import std.traits; -import std.typecons; -import std.datetime; -import std.exception; -import std.format; -import std.algorithm.iteration; -import std.algorithm.mutation; -import std.algorithm.searching; -import std.algorithm.comparison; - -/** - * HTTP/2 message exchange module as documented in: - * RFC 7540 (HTTP/2) section 8 -*/ - -enum StartLine { REQUEST, RESPONSE }; - -private alias H2F = HTTP2HeaderTableField; - -alias DataOutputStream = MemoryOutputStream; - -/// accepts a HTTP/1.1 header list, converts it to an HTTP/2 header frame and encodes it -ubyte[] buildHeaderFrame(alias type)(string statusLine, InetHeaderMap headers, - HTTP2ServerContext context, ref IndexingTable table, scope IAllocator alloc, bool - isTLS = true) @safe -{ - // frame header + frame payload - FixedAppender!(ubyte[], 9) hbuf; - auto pbuf = AllocAppender!(ubyte[])(alloc); - auto res = AllocAppender!(ubyte[])(alloc); - - // split the start line of each req / res into pseudo-headers - convertStartMessage(statusLine, pbuf, table, type, isTLS); - - // "Host" header does not exist in HTTP/2, use ":authority" pseudo-header - if("Host" in headers) { - headers[":authority"] = headers["Host"]; - headers.remove("Host"); - } - - foreach(k,v; headers.byKeyValue) { - H2F(k.toLower,v).encodeHPACK(pbuf, table); - } - - // TODO padding - if(context.next_sid == 0) context.next_sid = 1; - - hbuf.createHTTP2FrameHeader(cast(uint)pbuf.data.length, HTTP2FrameType.HEADERS, 0x0, context.next_sid); - - res.put(hbuf.data); - res.put(pbuf.data); - return res.data; -} - -/// DITTO for first request in case of h2c -ubyte[] buildHeaderFrame(alias type)(string statusLine, InetHeaderMap headers, - HTTP2ServerContext context, scope IAllocator alloc) @trusted -{ - return buildHeaderFrame!type(statusLine, headers, context, context.table, alloc); -} - -/// generates an HTTP/2 pseudo-header representation to encode a HTTP/1.1 start message line -private void convertStartMessage(T)(string src, ref T dst, ref IndexingTable table, StartLine type, bool isTLS = true) @safe -{ - void toPseudo(string buf) @safe - { - // exclude protocol version (not needed in HTTP/2) - if(buf != "HTTP/1.1" && buf != "HTTP/2") - { - if(type == StartLine.REQUEST) { // request - // request-line = method SP request-target SP HTTP-version CRLF - try { - auto method = httpMethodFromString(buf); // might throw - H2F(":method", method).encodeHPACK(dst, table); - } catch(Exception e) { - H2F(":scheme", (isTLS ? "https" : "http")).encodeHPACK(dst, table); - H2F(":path", buf).encodeHPACK(dst, table); - } - } else if(type == StartLine.RESPONSE) { // response (status-line) - // status-line = HTTP-version SP status-code SP reason-phrase CRLF - static foreach(st; __traits(allMembers, HTTPStatus)) { - if(buf.isNumeric && __traits(getMember, HTTPStatus, st) == buf.to!int) { - mixin("H2F(\":status\",HTTPStatus."~st~").encodeHPACK(dst, table); return;"); - } - } - } - } - } - - // consider each chunk of the start message line - src.strip("\r\n").splitter(' ').each!(s => toPseudo(s)); -} - -unittest { - import std.experimental.allocator; - import std.experimental.allocator.mallocator; - HTTP2Settings settings; - HTTPServerContext ctx; - auto context = new HTTP2ServerContext(ctx, settings); - auto table = IndexingTable(settings.headerTableSize); - scope alloc = new RegionListAllocator!(shared(Mallocator), false)(1024, Mallocator.instance); - - string statusline = "GET / HTTP/2\r\n\r\n"; - InetHeaderMap hmap; - hmap["Host"] = "www.example.com"; - ubyte[] expected = [0x82, 0x86, 0x84, 0x41, 0x8c, 0xf1 , 0xe3, 0xc2 , 0xe5, 0xf2 , 0x3a, 0x6b , 0xa0, 0xab , 0x90, 0xf4 , 0xff]; - // [9..$] excludes the HTTP/2 Frame header - auto res = buildHeaderFrame!(StartLine.REQUEST)(statusline, hmap, context, table, alloc, - false)[9..$]; - assert(res == expected); - - statusline = "HTTP/2 200 OK"; - InetHeaderMap hmap1; - expected = [0x88]; - res = buildHeaderFrame!(StartLine.RESPONSE)(statusline, hmap1, context, table, alloc, - false)[9..$]; - - assert(res == expected); -} - -/* ======================================================= */ -/* HTTP/2 REQUEST HANDLING */ -/* ======================================================= */ - -/** Similar to originalHandleRequest, adapted to HTTP/2 - * The request is converted to HTTPServerRequest through parseHTTP2RequestHeader - * once the HTTPServerResponse is built, HEADERS frame and (optionally) DATA Frames are sent -*/ -bool handleHTTP2Request(UStream)(ref HTTP2ConnectionStream!UStream stream, - TCPConnection tcp_connection, HTTP2ServerContext h2context, - HTTP2HeaderTableField[] headers, ref IndexingTable table, scope IAllocator alloc) @safe -{ - SysTime reqtime = Clock.currTime(UTC()); - HTTPServerContext listen_info = h2context.h1context; - - // initialize request - auto req = HTTPServerRequest(reqtime, listen_info.bindPort); - - // store the IP address - req.clientAddress = tcp_connection.remoteAddress; - - if (!listen_info.hasVirtualHosts) { - logWarn("Didn't find a HTTP listening context for incoming connection. Dropping."); - return false; - } - - // Default to the first virtual host for this listener - HTTPServerContext.VirtualHost context = listen_info.virtualHosts[0]; - HTTPServerRequestDelegate request_task = context.requestHandler; - HTTPServerSettings settings = context.settings; - - // temporarily set to the default settings - req.m_settings = settings; - - // Create the response object - InterfaceProxy!ConnectionStream cproxy = tcp_connection; - InterfaceProxy!Stream cstream = stream.connection; // TCPConnection / TLSStream - auto res = HTTPServerResponse(cstream, cproxy, settings, alloc); - - // check for TLS encryption - bool istls; - static if(is(UStream : TLSStream)) { - istls = true; - } else { - istls = false; - } - req.tls = istls; - res.tls = istls; - - if (req.tls) { - version (HaveNoTLS) assert(false); - else { - static if (is(InterfaceProxy!Stream == Stream)) - req.clientCertificate = (cast(TLSStream)stream.connection).peerCertificate; - else static if (is(typeof(stream.connection) : TLSStream)) - req.clientCertificate = stream.connection.peerCertificate; - else - assert(false); - } - } - - bool parsed = false; - - // parse request: - // both status line + headers (already unpacked in `headers`) - // defined in vibe.http.server because of protected struct HTTPServerRequest - parseHTTP2RequestHeader(headers, req); - if(req.host.empty) { - req.host = tcp_connection.localAddress.toString; - } - - if(req.tls) req.requestURI = "https://" ~ req.host ~ req.path; - else req.requestURI = "http://" ~ req.host ~ req.path; - - string reqhost; - ushort reqport = 0; - { - string s = req.host; - enforceHTTP(s.length > 0 || req.httpVersion <= HTTPVersion.HTTP_1_0, HTTPStatus.badRequest, "Missing Host header."); - if (s.startsWith('[')) { // IPv6 address - auto idx = s.indexOf(']'); - enforce(idx > 0, "Missing closing ']' for IPv6 address."); - reqhost = s[1 .. idx]; - s = s[idx+1 .. $]; - } else if (s.length) { // host name or IPv4 address - auto idx = s.indexOf(':'); - if (idx < 0) idx = s.length; - enforceHTTP(idx > 0, HTTPStatus.badRequest, "Missing Host header."); - reqhost = s[0 .. idx]; - s = s[idx .. $]; - } - if (s.startsWith(':')) reqport = s[1 .. $].to!ushort; - } - foreach (ctx; listen_info.virtualHosts) { - if (icmp2(ctx.settings.hostName, reqhost) == 0 && - (!reqport || reqport == ctx.settings.port)) - { - context = ctx; - settings = ctx.settings; - request_task = ctx.requestHandler; - break; - } - } - req.m_settings = settings; - res.m_settings = settings; - - // setup compressed output - if (settings.useCompressionIfPossible) { - if (auto pae = "Accept-Encoding" in req.headers) { - if (canFind(*pae, "gzip")) { - res.headers["Content-Encoding"] = "gzip"; - } else if (canFind(*pae, "deflate")) { - res.headers["Content-Encoding"] = "deflate"; - } - } - } - - // handle Expect header - if (auto pv = "Expect" in req.headers) { - if (icmp2(*pv, "100-continue") == 0) { - logTrace("sending 100 continue"); - InetHeaderMap hmap; - auto cres = buildHeaderFrame!(StartLine.RESPONSE)( - "HTTP/1.1 100 Continue\r\n\r\n", hmap, h2context, table, alloc, istls); - } - assert(false); // TODO determine if actually used with HTTP/2 (PUSH_PROMISE?) - } - - // eagerly parse the URL as its lightweight and defacto @nogc - auto url = URL.parse(req.requestURI); - req.queryString = url.queryString; - req.username = url.username; - req.password = url.password; - req.requestPath = url.path; - - // lookup the session - if (settings.sessionStore) { - // use the first cookie that contains a valid session ID in case - // of multiple matching session cookies - foreach (val; req.cookies.getAll(settings.sessionIdCookie)) { - req.session = settings.sessionStore.open(val); - res.m_session = req.session; - if (req.session) break; - } - } - - // write default headers - if (req.method == HTTPMethod.HEAD) res.m_isHeadResponse = true; - if (settings.serverString.length) - res.headers["Server"] = settings.serverString; - res.headers["Date"] = formatRFC822DateAlloc(alloc, reqtime); - if (req.persistent) res.headers["Keep-Alive"] = formatAlloc(alloc, "timeout=%d", settings.keepAliveTimeout.total!"seconds"()); - - // finished parsing the request - parsed = true; - logTrace("persist: %s", req.persistent); - //keep_alive = req.persistent; - logDebug("Received %s request on stream ID %d", req.method, stream.streamId); - - // utility to format the status line - auto statusLine = AllocAppender!string(alloc); - - void writeLine(T...)(string fmt, T args) - @safe { - formattedWrite(() @trusted { return &statusLine; } (), fmt, args); - statusLine.put("\r\n"); - logTrace(fmt, args); - } - - // header frame to be sent - ubyte[] headerFrame; - - // handle payload (DATA frame) - auto dataWriter = createDataOutputStream(alloc); - res.bodyWriterH2 = dataWriter; - h2context.next_sid = stream.streamId; - - // run task (writes body) - request_task(req, res); - - if(req.method != HTTPMethod.HEAD && dataWriter.data.length > 0) { // HEADERS + DATA - - // write the status line - writeLine("%s %d %s", - getHTTPVersionString(res.httpVersion), - res.statusCode, - res.statusPhrase.length ? res.statusPhrase : httpStatusText(res.statusCode)); - - // build the HEADERS frame - () @trusted { - headerFrame = buildHeaderFrame!(StartLine.RESPONSE)(statusLine.data, res.headers, - h2context, table, alloc, istls); - } (); - - // send HEADERS frame - if(headerFrame.length < h2context.settings.maxFrameSize) { - headerFrame[4] += 0x4; // set END_HEADERS flag (sending complete header) - cstream.write(headerFrame); - - } else { - // TODO CONTINUATION frames - assert(false); - } - - logDebug("Sent HEADERS frame on streamID " ~ stream.streamId.to!string); - - auto tlen = dataWriter.data.length; - - // multiple DATA Frames might be required - void sendDataTask() - @safe { - logDebug("[DATA] Starting dispatch task"); - - scope(exit) { - if(stream.state == HTTP2StreamState.HALF_CLOSED_REMOTE) { - stream.state = HTTP2StreamState.CLOSED; - } else { - stream.state = HTTP2StreamState.HALF_CLOSED_LOCAL; - } - } - - try { - - auto abort = false; - uint done = 0; - - // window length - uint wlen = sendWindowLength(h2context.multiplexer, - stream.streamId, h2context.settings.maxFrameSize, tlen); - - // until the whole payload is sent - while(done <= tlen) { - auto dataFrame = AllocAppender!(ubyte[])(alloc); - - dataFrame.createHTTP2FrameHeader( - wlen, - HTTP2FrameType.DATA, - (done+wlen >= tlen) ? 0x1 : 0x0, // END_STREAM 0x1 - stream.streamId - ); - - // send is over - if(done == tlen) { - logDebug("[DATA] Completed DATA frame dispatch"); - // remove task from waiting state - doneCondition(h2context.multiplexer, stream.streamId); - closeStream(h2context.multiplexer, stream.streamId); - break; - } - - // wait to resume and retry - if(wlen == 0) { - logDebug("[DATA] Dispatch task waiting for WINDOW_UPDATE"); - - // after 60 seconds waiting, terminate dispatch - () @trusted { - auto timer = setTimer(600.seconds, { - logDebug("[DATA] timer expired, aborting dispatch"); - notifyCondition(h2context.multiplexer); - abort = true; - }); - - // wait until a new WINDOW_UPDATE is received (or timer expires) - waitCondition(h2context.multiplexer, stream.streamId); - - // task resumed: cancel timer - if(!abort) timer.stop; - else return; - } (); - - logDebug("[DATA] Dispatch task resumed"); - - } else { - // write - - dataFrame.put(dataWriter.data[done..done+wlen]); - cstream.write(dataFrame.data); - - done += wlen; - - logDebug("[DATA] Sent frame chunk (%d/%d bytes) on streamID %d", - done, tlen, stream.streamId); - - updateWindow(h2context.multiplexer, stream.streamId, wlen); - - // return control to the event loop - yield(); - } - - // compute new window length - wlen = sendWindowLength(h2context.multiplexer, - stream.streamId, h2context.settings.maxFrameSize, tlen - done); - } - - } catch (Exception e) { - logDebug("[DATA] "~e.msg); - return; - } - } - - // spawn the asynchronous data sender - sendDataTask(); - - } else if(dataWriter.data.length > 0) { // HEAD response, HEADERS frame, no DATA - - // write the status line - writeLine("%s %d %s", - getHTTPVersionString(res.httpVersion), - res.statusCode, - res.statusPhrase.length ? res.statusPhrase : httpStatusText(res.statusCode)); - - // build the HEADERS frame - () @trusted { - headerFrame = buildHeaderFrame!(StartLine.RESPONSE)(statusLine.data, res.headers, - h2context, table, alloc, istls); - } (); - - // send HEADERS frame - if(headerFrame.length < h2context.settings.maxFrameSize) { - headerFrame[4] += 0x5; // set END_HEADERS, END_STREAM flag - cstream.write(headerFrame); - } else { - // TODO CONTINUATION frames - assert(false); - } - - logDebug("Sent HEADERS frame on streamID " ~ stream.streamId.to!string); - - logDebug("[Data] No DATA frame to send"); - - if(stream.state == HTTP2StreamState.HALF_CLOSED_REMOTE) { - stream.state = HTTP2StreamState.CLOSED; - } else { - stream.state = HTTP2StreamState.HALF_CLOSED_LOCAL; - } - closeStream(h2context.multiplexer, stream.streamId); - - } else { // 404: no DATA for the given path - - writeLine("%s %d %s", - "HTTP/2", - 404, - "Not Found"); - - // build the HEADERS frame - () @trusted { - headerFrame = buildHeaderFrame!(StartLine.RESPONSE)(statusLine.data, res.headers, - h2context, table, alloc, istls); - } (); - - if(headerFrame.length < h2context.settings.maxFrameSize) { - headerFrame[4] += 0x5; // set END_HEADERS, END_STREAM flag - cstream.write(headerFrame); - } - - logDebug("No response: sent 404 HEADERS frame"); - - } - - return true; -} - - -uint sendWindowLength(Mux)(ref Mux multiplexer, const uint sid, const uint maxfsize, const ulong len) @safe -{ - return min(connectionWindow(multiplexer), streamConnectionWindow(multiplexer, sid), maxfsize, len); -} - -void updateWindow(Mux)(ref Mux multiplexer, const uint sid, const ulong sent) @safe -{ - auto cw = connectionWindow(multiplexer) - sent; - auto scw = streamConnectionWindow(multiplexer, sid) - sent; - - updateConnectionWindow(multiplexer, cw); - updateStreamConnectionWindow(multiplexer, sid, cw); -} - -private DataOutputStream createDataOutputStream(IAllocator alloc = vibeThreadAllocator()) -@safe nothrow { - return createMemoryOutputStream(alloc); -} - -private HeaderOutputStream createHeaderOutputStream(IAllocator alloc = vibeThreadAllocator()) -@safe nothrow { - return new HeaderOutputStream(alloc); -} - -private final class HeaderOutputStream : OutputStream { -@safe: - - private { - AllocAppender!(string) m_destination; - } - - this(IAllocator alloc) - nothrow { - m_destination = AllocAppender!(string)(alloc); - } - - /// An array with all data written to the stream so far. - @property string data() @trusted nothrow { return m_destination.data(); } - - /// Resets the stream to its initial state containing no data. - void reset(AppenderResetMode mode = AppenderResetMode.keepData) - @system { - m_destination.reset(mode); - } - - /// Reserves space for data - useful for optimization. - void reserve(size_t nbytes) - { - m_destination.reserve(nbytes); - } - - size_t write(in string bytes, IOMode) - { - () @trusted { m_destination.put(bytes); } (); - return bytes.length; - } - /// DITTO - size_t write(const(ubyte[]) bytes, IOMode) - { - () @trusted { m_destination.put(cast(string)bytes); } (); - return bytes.length; - } - - alias write = OutputStream.write; - - void flush() - nothrow { - } - - void finalize() - nothrow { - } -} diff --git a/source/vibe/http/internal/http2/frame.d b/source/vibe/http/internal/http2/frame.d deleted file mode 100644 index b153f85..0000000 --- a/source/vibe/http/internal/http2/frame.d +++ /dev/null @@ -1,471 +0,0 @@ -module vibe.http.internal.http2.frame; - -import vibe.http.internal.http2.settings; -import vibe.http.internal.http2.error; - -import vibe.internal.array; - -import std.typecons; -import std.traits; -import std.range; -import std.array; -import std.exception; -import std.algorithm.iteration; -import std.algorithm.mutation; - - -/** This module implements HTTP/2 Frames, as defined in RFC 7540 under: - * - * Section 4: Frame overview, Frame header composition (octets) and their meaning - * https://tools.ietf.org/html/rfc7540#section-4 - * - * Section 6: Frame definition according to Frame Type - * https://tools.ietf.org/html/rfc7540#section-6 -*/ - -enum uint HTTP2HeaderLength = 9; - -enum HTTP2FrameType { - DATA = 0x0, - HEADERS = 0x1, - PRIORITY = 0x2, - RST_STREAM = 0x3, - SETTINGS = 0x4, - PUSH_PROMISE = 0x5, - PING = 0x6, - GOAWAY = 0x7, - WINDOW_UPDATE = 0x8, - CONTINUATION = 0x9 -} - -/*** FRAME PARSING ***/ - -/// updated by `unpackHTTP2Frame` -struct HTTP2FrameStreamDependency { - bool exclusive = false; - bool isPushPromise = false; - uint streamId = 0; - ubyte weight = 0; - - @property bool isSet() @safe @nogc { return streamId != 0; } - - void fill(R)(ref R src) @safe @nogc - if(is(ElementType!R : ubyte)) - { - uint first = src.takeExactly(4).fromBytes(4); - exclusive = first & (cast(ulong)1 << 32); - streamId = first & ((cast(ulong)1 << 32) - 1); - src.popFrontN(4); - - if(!isPushPromise) { - weight = src.front; - src.popFront(); - } - } -} - -/** unpacks a frame putting the payload in `payloadDst` and returning the header - * implements the checks required for each frame type (Section 6 of HTTP/2 RFC) - * - * Invoked by a possible HTTP/2 request handler, the payload is meant to be handled by - * the caller. - * - * Note: @nogc-compatible as long as payloadDst.put is @nogc (AllocAppender.put isn't) - */ -HTTP2FrameHeader unpackHTTP2Frame(R,T)(ref R payloadDst, T src, ref bool endStream, ref bool endHeaders, ref bool ack, ref HTTP2FrameStreamDependency sdep) @safe -{ - auto header = unpackHTTP2FrameHeader(src); - unpackHTTP2Frame(payloadDst, src, header, endStream, endHeaders, ack, sdep); - return header; -} - -/// DITTO -void unpackHTTP2Frame(R,T)(ref R payloadDst, T src, HTTP2FrameHeader header, ref bool endStream, ref bool endHeaders, ref bool ack, ref HTTP2FrameStreamDependency sdep) @safe -{ - size_t len = header.payloadLength; - - switch(header.type) { - case HTTP2FrameType.DATA: - if(header.flags & 0x8) { // padding is set, first bit is pad length - len -= cast(size_t)src.front + 1; - src.popFront(); - enforceHTTP2(src.length >= len, "Invalid pad length", HTTP2Error.PROTOCOL_ERROR); - } - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - src.popFrontN(header.payloadLength - len - 1); // remove padding - if(header.flags & 0x1) endStream = true; - break; - - case HTTP2FrameType.HEADERS: - if(header.flags & 0x8) { // padding is set, first bit is pad length - len -= cast(size_t)src.front + 1; - src.popFront(); - enforceHTTP2(src.length >= len, "Invalid pad length", HTTP2Error.PROTOCOL_ERROR); - } - if(header.flags & 0x20) { // priority is set, fill `sdep` - sdep.fill(src); - len -= 5; - } - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - src.popFrontN(header.payloadLength - len - 1); // remove padding - if(header.flags & 0x1) endStream = true; - if(header.flags & 0x4) endHeaders = true; - break; - - case HTTP2FrameType.PRIORITY: - enforceHTTP2(len == 5, "Invalid PRIORITY Frame", HTTP2Error.PROTOCOL_ERROR); - sdep.fill(src); - break; - - case HTTP2FrameType.RST_STREAM: - enforceHTTP2(len == 4, "Invalid RST_STREAM Frame", HTTP2Error.PROTOCOL_ERROR); - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - break; - - case HTTP2FrameType.SETTINGS: - enforceHTTP2(len % 6 == 0, "Invalid SETTINGS Frame (FRAME_SIZE error)", HTTP2Error.PROTOCOL_ERROR); - enforceHTTP2(header.streamId == 0, "Invalid streamId for SETTINGS Frame", HTTP2Error.PROTOCOL_ERROR); - if(header.flags & 0x1) { // this is an ACK frame - enforceHTTP2(len == 0, "Invalid SETTINGS ACK Frame (FRAME_SIZE error)", HTTP2Error.PROTOCOL_ERROR); - ack = true; - break; - } - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - break; - - case HTTP2FrameType.PUSH_PROMISE: - if(header.flags & 0x8) { // padding is set, first bit is pad length - len -= cast(size_t)src.front + 1; - src.popFront(); - enforceHTTP2(src.length >= len, "Invalid pad length", HTTP2Error.PROTOCOL_ERROR); - } - sdep.isPushPromise = true; - sdep.fill(src); - len -= 4; - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - src.popFrontN(header.payloadLength - len - 1); // remove padding - if(header.flags & 0x4) endHeaders = true; - break; - - case HTTP2FrameType.PING: - enforceHTTP2(len == 8, "Invalid PING Frame (FRAME_SIZE error)", - HTTP2Error.PROTOCOL_ERROR); - enforceHTTP2(header.streamId == 0, "Invalid streamId for PING Frame", - HTTP2Error.PROTOCOL_ERROR); - if(header.flags & 0x1) { - ack = true; - } - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - break; - - case HTTP2FrameType.GOAWAY: // GOAWAY is used to close connection (in handler) - enforceHTTP2(len >= 8, "Invalid GOAWAY Frame (FRAME_SIZE error)", - HTTP2Error.PROTOCOL_ERROR); - enforceHTTP2(header.streamId == 0, "Invalid streamId for GOAWAY Frame", - HTTP2Error.PROTOCOL_ERROR); - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - break; - - case HTTP2FrameType.WINDOW_UPDATE: - enforceHTTP2(len == 4, "Invalid WINDOW_UPDATE Frame (FRAME_SIZE error)", - HTTP2Error.PROTOCOL_ERROR); - foreach(i,b; src.takeExactly(len).enumerate) { - if(i == 0) b &= 0x7F; // reserved bit - payloadDst.put(b); - src.popFront(); - } - break; - - case HTTP2FrameType.CONTINUATION: - enforceHTTP2(header.streamId != 0, "Invalid streamId for CONTINUATION frame", - HTTP2Error.PROTOCOL_ERROR); - foreach(b; src.takeExactly(len)) { - payloadDst.put(b); - src.popFront(); - } - if(header.flags & 0x4) endHeaders = true; - break; - - default: - enforceHTTP2(false, "Invalid frame header unpacked.", HTTP2Error.PROTOCOL_ERROR); - break; - } -} - -unittest { - import vibe.internal.array : FixedAppender; - - FixedAppender!(ubyte[], 4) payloadDst; - bool endStream = false; - bool endHeaders = false; - bool ack = false; - HTTP2FrameStreamDependency sdep; - - - // DATA Frame - ubyte[] data = [0, 0, 4, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == [1, 1, 1, 1]); - - // HEADERS Frame - payloadDst.clear; - data = [0, 0, 4, 1, 0, 0, 0, 0, 2, 2, 2, 2, 2]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == [2, 2, 2, 2]); - - // PRIORITY Frame - payloadDst.clear; - data = [0, 0, 5, 2, 0, 0, 0, 0, 3, 0, 0, 0, 2, 5]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == []); - assert(sdep.weight == 5 && sdep.streamId == 2); - - // RST_STREAM Frame - payloadDst.clear; - data = [0, 0, 4, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == [4, 4, 4, 4]); - - // SETTINGS Frame - FixedAppender!(ubyte[], 6) settingsDst; - data = [0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2]; - settingsDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(settingsDst.data == [0, 1, 2, 2, 2, 2]); - - // PUSH_PROMISE Frame - payloadDst.clear; - data = [0, 0, 8, 5, 0, 0, 0, 0, 5, 0, 0, 0, 2, 4, 4, 4, 4]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == [4, 4, 4, 4]); - assert(sdep.weight == 5 && sdep.streamId == 2); - - // PING Frame - FixedAppender!(ubyte[], 8) pingDst; - data = [0, 0, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4]; - pingDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(pingDst.data == [0, 0, 0, 2, 4, 4, 4, 4]); - - // GOAWAY Frame - pingDst.clear; - data = [0, 0, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4]; - pingDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(pingDst.data == [0, 0, 0, 2, 0, 0, 0, 4]); - - // WINDOW_UPDATE - payloadDst.clear; - data = [0, 0, 4, 8, 0, 0, 0, 0, 6, 1, 1, 1, 1]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == [1, 1, 1, 1]); - - // CONTINUATION - payloadDst.clear; - data = [0, 0, 4, 9, 0, 0, 0, 0, 6, 2, 2, 2, 2]; - payloadDst.unpackHTTP2Frame(data, endStream, endHeaders, ack, sdep); - assert(payloadDst.data == [2, 2, 2, 2]); -} - -/*** FRAME BUILDING ***/ - -/// concatenates a Frame header with a Frame payload -void buildHTTP2Frame(R,H,T)(ref R dst, ref H header, ref T payload) @safe @nogc - if(is(ElementType!R : ubyte) && is(ElementType!T : ubyte)) -{ - // put header - static if(is(H == HTTP2FrameHeader)) { - assert(header.payloadLength == payload.length, "Invalid payload length"); - dst.serializeHTTP2FrameHeader(header); - - } else static if(is(ElementType!H : ubyte)) { - auto len = header.takeExactly(3).fromBytes(3); - assert(len == payload.length, "Invalid payload length"); - foreach(b; header) dst.put(b); - } - - // put payload - foreach(b; payload) dst.put(b); -} - -/// DITTO -/// @nogc-compatible if dst.put is @nogc -void buildHTTP2Frame(R,T)(ref R dst, T payload) @safe -{ - payload.copy(dst); -} - -unittest { - auto header = HTTP2FrameHeader(4, cast(HTTP2FrameType)1, 0, 5); - ubyte[4] payload = [0, 1, 2, 3]; - ubyte[] bheader = [0, 0, 4, 1, 0, 0, 0, 0, 5]; - ubyte[13] expected = [0, 0, 4, 1, 0, 0, 0, 0, 5, 0, 1, 2, 3]; - - BatchBuffer!(ubyte, 13) dst, ddst; - dst.putN(13); - ddst.putN(13); - dst.buildHTTP2Frame(header, payload); - ddst.buildHTTP2Frame(bheader, payload); - - assert(dst.peekDst == expected); - assert(ddst.peekDst == expected); -} - -/*** FRAME HEADER ***/ -/// header packing -/// @nogc-compatible if dst.put is @nogc -void createHTTP2FrameHeader(R)(ref R dst, const uint len, const HTTP2FrameType type, const ubyte flags, const uint sid) @safe -{ - dst.serialize(HTTP2FrameHeader(len, type, flags, sid)); -} - -/// serializing -void serializeHTTP2FrameHeader(R)(ref R dst, HTTP2FrameHeader header) @safe @nogc -{ - dst.serialize(header); -} - -/// unpacking -HTTP2FrameHeader unpackHTTP2FrameHeader(R)(scope ref R src) @safe @nogc -{ - scope header = HTTP2FrameHeader(src); - return header; -} - -/** Implement an HTTP/2 Frame header - * The header is a 9-bit ubyte[9] string - */ -struct HTTP2FrameHeader -{ - private { - //ubyte[3] m_length; // 24-bit frame payload length - FixedAppender!(ubyte[], 3) m_length; - HTTP2FrameType m_type; // frame type (stored as ubyte for serialization) - ubyte m_flags; // frame flags - //ubyte[4] m_streamId; // stream id, uint (stored as ubyte for serialization) - FixedAppender!(ubyte[], 4) m_streamId; - } - - this(const uint len, const HTTP2FrameType tp, const ubyte flg, const uint sid) @safe @nogc - { - assert(sid < (cast(ulong)1 << 32), "Invalid stream id"); - - m_length.putBytes!3(len); - m_type = tp; - m_flags = flg; - m_streamId.putBytes!4(sid & ((cast(ulong)1 << 32) - 1)); // reserved bit is 0 - } - - this(T)(ref T src) @safe @nogc - if(is(ElementType!T : ubyte)) - { - m_length.put(src.take(3)); - src.popFrontN(3); - - m_type = cast(HTTP2FrameType)src.front; src.popFront; - m_flags = src.front; src.popFront; - - m_streamId.put(src.take(1).front & 127); src.popFront; // ignore reserved bit - m_streamId.put(src.take(3)); - src.popFrontN(3); - } - - @property HTTP2FrameType type() @safe @nogc { return m_type; } - - @property uint payloadLength() @safe @nogc { return m_length.data.fromBytes(3); } - - @property ubyte flags() @safe @nogc { return m_flags; } - - @property uint streamId() @safe @nogc { return m_streamId.data.fromBytes(4); } -} - -/// convert 32-bit unsigned integer to N bytes (MSB first) -void putBytes(uint N, R)(ref R dst, const(ulong) src) @safe @nogc -{ - assert(src >= 0 && src < (cast(ulong)1 << N*8), "Invalid frame payload length"); - static if(hasLength!R) assert(dst.length >= N); - - ubyte[N] buf; - foreach(i,ref b; buf) b = cast(ubyte)(src >> 8*(N-1-i)) & 0xff; - - static if(isArray!R) { - dst.put(buf); - } else { - foreach(b; buf) dst.put(b); - } -} - -/// convert a N-bytes representation MSB->LSB to uint -uint fromBytes(R)(R src, uint n) @safe @nogc -{ - uint res = 0; - static if(isArray!R) { - foreach(i,b; src) res = res + (b << 8*(n-1-i)); - } else { - foreach(i,b; src.enumerate.retro) res = res + (b << 8*i); - } - return res; -} - -/// fill a buffer with fields from `header` -/// @nogc-compatible if dst.put is @nogc -private void serialize(R)(ref R dst, HTTP2FrameHeader header) @safe - if(isOutputRange!(R, ubyte)) -{ - static foreach(f; __traits(allMembers, HTTP2FrameHeader)) { - static if(f != "__ctor" && f != "type" - && f != "payloadLength" && f != "flags" && f != "streamId") { - static if(f == "m_length" || f == "m_streamId") { - mixin("dst.put(header."~f~".data);"); - } else static if(f == "m_type") { - mixin("dst.put(cast(ubyte)header."~f~");"); - } else { - mixin("dst.put(header."~f~");"); - } - } - } -} - -unittest { - import vibe.internal.array : FixedAppender; - - auto header = HTTP2FrameHeader(2, cast(HTTP2FrameType)1, 0, 5); - ubyte[] expected = [0, 0, 2, 1, 0, 0, 0, 0, 5]; - FixedAppender!(ubyte[], 9) dst; - // serialize to a ubyte[9] array - serialize(dst,header); - assert(dst.data == expected); - - // test utility functions - FixedAppender!(ubyte[], 9) ddst; - ddst.createHTTP2FrameHeader(2, cast(HTTP2FrameType)1, 0, 5); - assert(dst.data == ddst.data); - - FixedAppender!(ubyte[], 9) dddst; - dddst.serializeHTTP2FrameHeader(header); - assert(dst.data == dddst.data); - - // test unpacking - assert(header == unpackHTTP2FrameHeader(expected)); - - assert(header.payloadLength == 2); -} - diff --git a/source/vibe/http/internal/http2/hpack/decoder.d b/source/vibe/http/internal/http2/hpack/decoder.d deleted file mode 100644 index c083b3e..0000000 --- a/source/vibe/http/internal/http2/hpack/decoder.d +++ /dev/null @@ -1,142 +0,0 @@ -module vibe.http.internal.http2.hpack.decoder; - -import vibe.http.internal.http2.hpack.huffman; -import vibe.http.internal.http2.hpack.tables; -import vibe.http.internal.http2.hpack.util; -import vibe.http.internal.http2.hpack.exception; - -import vibe.internal.array : AllocAppender; -import vibe.core.log; - -import std.range; // Decoder -import std.string; -import std.experimental.allocator; -import std.experimental.allocator.mallocator; -import std.exception; - -/** Module to implement an header decoder consistent with HPACK specifications (RFC 7541) - * The detailed description of the decoding process, examples and binary format details can - * be found at: - * Section 3: https://tools.ietf.org/html/rfc7541#section-3 - * Section 6: https://tools.ietf.org/html/rfc7541#section-6 - * Appendix C: https://tools.ietf.org/html/rfc7541#appendix-C -*/ -alias HTTP2SettingValue = uint; - -void decode(I, R, T)(ref I src, ref R dst, ref IndexingTable table, ref T alloc, ulong maxTableSize=4096) @trusted -{ - ubyte bbuf = src[0]; - src = src[1..$]; - - if(bbuf & 128) { - auto res = decodeInteger(src, bbuf, 7); - dst.put(table[res]); - } else { - HTTP2HeaderTableField hres; - bool update = false; - auto adst = AllocAppender!string(alloc); - - if (bbuf & 64) { // inserted in dynamic table - size_t idx = decodeInteger(src, bbuf, 6); - if(idx > 0) { // name == table[index].name, value == literal - hres.name = table[idx].name; - } else { // name == literal, value == literal - decodeLiteral(src, adst); - hres.name.setReset(adst); - } - decodeLiteral(src, adst); - hres.value.setReset(adst); - hres.index = true; - hres.neverIndex = false; - - } else if(bbuf & 32) { - update = true; - auto nsize = decodeInteger(src, bbuf, 3); - enforce(nsize <= maxTableSize, "Invalid table size update"); - - table.updateSize(cast(HTTP2SettingValue)nsize); - logDebug("Updated dynamic table size to: %d octets", nsize); - - } else if(bbuf & 16) { // NEVER inserted in dynamic table - size_t idx = decodeInteger(src, bbuf, 4); - if(idx > 0) { // name == table[index].name, value == literal - hres.name = table[idx].name; - } else { // name == literal, value == literal - decodeLiteral(src, adst); - hres.name.setReset(adst); - } - decodeLiteral(src, adst); - hres.value.setReset(adst); - hres.index = false; - hres.neverIndex = true; - - } else { // this occourrence is not inserted in dynamic table - size_t idx = decodeInteger(src, bbuf, 4); - if(idx > 0) { // name == table[index].name, value == literal - hres.name = table[idx].name; - } else { // name == literal, value == literal - decodeLiteral(src, adst); - hres.name.setReset(adst); - } - decodeLiteral(src, adst); - hres.value.setReset(adst); - hres.index = hres.neverIndex = false; - - } - assert(!(hres.index && hres.neverIndex), "Invalid header indexing information"); - - if(!update) dst.put(hres); - } -} - -private void setReset(I,R)(ref I dst, ref R buf) - if(is(R == AllocAppender!string) || is(R == AllocAppender!(immutable(ubyte)[]))) -{ - dst = buf.data; - buf.reset; -} - -private size_t decodeInteger(I)(ref I src, ubyte bbuf, uint nbits) @safe @nogc -{ - auto res = bbuf.toInteger(8-nbits); - - if (res < (1 << nbits) - 1) { - return res; - } else { - uint m = 0; - do { - // take another octet - bbuf = src[0]; - src = src[1..$]; - // concatenate it to the result - res = res + bbuf.toInteger(1)*(1 << m); - m += 7; - } while((bbuf & 128) == 128); - return res; - } -} - -private void decodeLiteral(I,R)(ref I src, ref R dst) @safe -{ - enforceHPACK(!src.empty, "Invalid literal header block"); - - ubyte bbuf = src[0]; - src = src[1..$]; - - bool huffman = (bbuf & 128) ? true : false; - - assert(!src.empty, "Cannot decode from empty range block"); - - // take a buffer of remaining octets - auto vlen = decodeInteger(src, bbuf, 7); // value length - enforceHPACK(vlen <= src.length, "Invalid literal decoded"); - - auto buf = src[0..vlen]; - src = src[vlen..$]; - - if(huffman) { // huffman encoded - decodeHuffman(buf, dst); - } else { // raw encoded - dst.put(cast(string)buf); - } -} diff --git a/source/vibe/http/internal/http2/hpack/encoder.d b/source/vibe/http/internal/http2/hpack/encoder.d deleted file mode 100644 index 3f15bd6..0000000 --- a/source/vibe/http/internal/http2/hpack/encoder.d +++ /dev/null @@ -1,126 +0,0 @@ -module vibe.http.internal.http2.hpack.encoder; - -import vibe.http.internal.http2.hpack.tables; -import vibe.http.internal.http2.hpack.huffman; -import vibe.http.internal.http2.hpack.util; - -import std.range; -import std.typecons; -import std.conv; -import std.array; - -void encode(R)(HTTP2HeaderTableField header, ref R dst, ref IndexingTable table, bool huffman = true) -@safe -{ - // try to encode as integer - bool indexed = encodeInteger(header, dst, table, huffman); - // if fail, encode as literal - if(!indexed) encodeLiteral(header, dst, huffman); -} - -/// encode a pure integer (present in table) or integer name + literal value -private bool encodeInteger(R)(const HTTP2HeaderTableField header, ref R dst, ref IndexingTable table, bool huffman = true) -@trusted -{ - // check table for indexed headers - size_t idx = 1; - bool found = false; - size_t partialFound = false; - - while(idx < table.size) { - // encode both name / value as index - auto h = table[idx]; - if(h.name == header.name && h.value == header.value) { - found = true; - partialFound = false; - break; - // encode name as index, value as literal - } else if(h.name == header.name && h.value != header.value) { - found = false; - partialFound = idx; - } - idx++; - } - - if(found) { - if(idx < 127) { // can be fit in one octet - dst.put(cast(ubyte)(idx ^ 128)); - } else { // must be split in multiple octets - dst.put(cast(ubyte)255); - idx -= 127; - while (idx > 127) { - dst.put(cast(ubyte)((idx % 128) ^ 128)); - idx = idx / 128; - } - dst.put(cast(ubyte)(idx & 127)); - } - return true; - - } else if(partialFound) { - // encode name as index ( always smaller than 64 ) - if(header.index) dst.put(cast(ubyte)((partialFound + 64) & 127)); - else if (header.neverIndex) dst.put(cast(ubyte)((partialFound + 16) & 31)); - else dst.put(cast(ubyte)(partialFound & 15)); - // encode value as literal - encodeLiteralField(to!string(header.value), dst, huffman); - - return true; - } - - return false; -} - -/// encode a literal field depending on its indexing requirements -private void encodeLiteral(R)(const HTTP2HeaderTableField header, ref R dst, bool huffman = true) -@safe -{ - if(header.index) dst.put(cast(ubyte)(64)); - else if(header.neverIndex) dst.put(cast(ubyte)(16)); - else dst.put(cast(ubyte)(0)); - - encodeLiteralField(to!string(header.name), dst, huffman); - encodeLiteralField(to!string(header.value), dst, huffman); -} - -/// encode a field (name / value) using huffman or raw encoding -private void encodeLiteralField(R)(string src, ref R dst, bool huffman = true) @safe -{ - if(huffman) { - encodeHuffman(src, dst); - } else { - auto blen = (src.length) & 127; - dst.put(cast(ubyte)blen); - dst.put(cast(ubyte[])(to!string(src).dup)); - } -} - -unittest { - // encode integer - import vibe.internal.array : BatchBuffer; - import vibe.http.common; - auto table = IndexingTable(4096); - - BatchBuffer!(ubyte, 1) bres; - bres.putN(1); - ubyte[1] expected = [0x82]; - auto hint = HTTP2HeaderTableField(":method", HTTPMethod.GET); - - assert(encodeInteger(hint, bres, table)); - assert(bres.peekDst == expected); -} - -unittest { - // encode literal - // custom-key: custom-header - import vibe.internal.array : BatchBuffer; - ubyte[26] lexpected = [0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, - 0x65, 0x79, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72]; - - BatchBuffer!(ubyte, 26) lres; - lres.putN(26); - auto hlit = HTTP2HeaderTableField("custom-key", "custom-header"); - - encodeLiteral(hlit, lres, false); - assert(lres.peekDst == lexpected); -} diff --git a/source/vibe/http/internal/http2/hpack/exception.d b/source/vibe/http/internal/http2/hpack/exception.d deleted file mode 100644 index 5df59ba..0000000 --- a/source/vibe/http/internal/http2/hpack/exception.d +++ /dev/null @@ -1,30 +0,0 @@ -module vibe.http.internal.http2.hpack.exception; - -import std.exception; - -T enforceHPACK(T)(T condition, string message = null, string file = __FILE__, - typeof(__LINE__) line = __LINE__) @safe -{ - return enforce(condition, new HPACKException(message, file, line)); -} - -class HPACKException : Exception -{ - this(string msg, string file = __FILE__, size_t line = __LINE__) @safe { - super(msg, file, line); - } -} - -class HPACKDecoderException : HPACKException -{ - this(string msg, string file = __FILE__, size_t line = __LINE__) { - super(msg, file, line); - } -} - -class HPACKEncoderException : HPACKException -{ - this(string msg, string file = __FILE__, size_t line = __LINE__) { - super(msg, file, line); - } -} diff --git a/source/vibe/http/internal/http2/hpack/hpack.d b/source/vibe/http/internal/http2/hpack/hpack.d deleted file mode 100644 index 31981ec..0000000 --- a/source/vibe/http/internal/http2/hpack/hpack.d +++ /dev/null @@ -1,267 +0,0 @@ -//module vibe.http.internal.hpack.hpack; -module vibe.http.internal.http2.hpack.hpack; - -import vibe.http.internal.http2.hpack.encoder; -import vibe.http.internal.http2.hpack.decoder; -import vibe.http.internal.http2.hpack.tables; - - -import std.range; -import std.typecons; -import std.array; // appender -import std.algorithm.iteration; - - -/// interface for the HPACK encoder -void encodeHPACK(I,R)(I src, ref R dst, ref IndexingTable table, bool huffman = true) @safe - if(is(I == HTTP2HeaderTableField) || is(ElementType!I : HTTP2HeaderTableField)) -{ - static if(is(I == HTTP2HeaderTableField)) { - src.encode(dst, table, huffman); - } else if(is(ElementType!I : HTTP2HeaderTableField)){ - src.each!(h => h.encode(dst, table, huffman)); - } -} - -void decodeHPACK(I,R,T)(I src, ref R dst, ref IndexingTable table, ref T alloc, uint maxTableSize = 4096) @safe - if(isInputRange!I && (is(ElementType!I : immutable(ubyte)) || is(ElementType!I : immutable(char)))) -{ - while(!src.empty) src.decode(dst, table, alloc, maxTableSize); -} - -/// ENCODER -unittest { - //// Following examples can be found in Appendix C of the HPACK RFC - import vibe.http.status; - import vibe.http.common; - import vibe.internal.utilallocator: RegionListAllocator; - import std.experimental.allocator; - import std.experimental.allocator.gc_allocator; - - auto table = IndexingTable(4096); - scope alloc = new RegionListAllocator!(shared(GCAllocator), false)(1024, GCAllocator.instance); - - /** 1. Literal header field w. indexing (raw) - * custom-key: custom-header - */ - HTTP2HeaderTableField h1 = HTTP2HeaderTableField("custom-key", "custom-header"); - auto e1 = appender!(ubyte[]); - auto dec1 = appender!(HTTP2HeaderTableField[]); - - h1.encodeHPACK(e1, table, false); - decodeHPACK(cast(immutable(ubyte)[])e1.data, dec1, table, alloc); - assert(dec1.data.front == h1); - - /** 1bis. Literal header field w. indexing (huffman encoded) - * :authority: www.example.com - */ - table.insert(HTTP2HeaderTableField(":authority", "www.example.com")); - HTTP2HeaderTableField h1b = HTTP2HeaderTableField(":authority", "www.example.com"); - h1b.neverIndex = false; - h1b.index = true; - auto e1b = appender!(ubyte[]); - auto dec1b = appender!(HTTP2HeaderTableField[]); - - h1b.encodeHPACK(e1b, table, true); - decodeHPACK(cast(immutable(ubyte)[])e1b.data, dec1b, table, alloc); - assert(dec1b.data.front == h1b); - - /** 2. Literal header field without indexing (raw) - * :path: /sample/path - */ - auto h2 = HTTP2HeaderTableField(":path", "/sample/path"); - h2.neverIndex = false; - h2.index = false; - // initialize with huffman=false (can be modified by e2.huffman) - auto e2 = appender!(ubyte[]); - auto dec2 = appender!(HTTP2HeaderTableField[]); - - h2.encodeHPACK(e2, table, false); - decodeHPACK(cast(immutable(ubyte)[])e2.data, dec2, table, alloc); - assert(dec2.data.front == h2); - - /** 3. Literal header field never indexed (raw) - * password: secret - */ - HTTP2HeaderTableField h3 = HTTP2HeaderTableField("password", "secret"); - h3.neverIndex = true; - h3.index = false; - auto e3 = appender!(ubyte[]); - auto dec3 = appender!(HTTP2HeaderTableField[]); - - h3.encodeHPACK(e3, table, false); - decodeHPACK(cast(immutable(ubyte)[])e3.data, dec3, table, alloc); - assert(dec3.data.front == h3); - - /** 4. Indexed header field (integer) - * :method: GET - */ - HTTP2HeaderTableField h4 = HTTP2HeaderTableField(":method", HTTPMethod.GET); - auto e4 = appender!(ubyte[]); - auto dec4 = appender!(HTTP2HeaderTableField[]); - - h4.encodeHPACK(e4, table); - decodeHPACK(cast(immutable(ubyte)[])e4.data, dec4, table, alloc); - assert(dec4.data.front == h4); - - /** 5. Full request without huffman encoding - * :method: GET - * :scheme: http - * :path: / - * :authority: www.example.com - * cache-control: no-cache - */ - HTTP2HeaderTableField[] block = [ - HTTP2HeaderTableField(":method", HTTPMethod.GET), - HTTP2HeaderTableField(":scheme", "http"), - HTTP2HeaderTableField(":path", "/"), - HTTP2HeaderTableField(":authority", "www.example.com"), - HTTP2HeaderTableField("cache-control", "no-cache") - ]; - - ubyte[14] expected = [0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65]; - auto bres = appender!(ubyte[]); - block.encodeHPACK(bres, table, false); - assert(bres.data == expected); - - /** 5. Full request with huffman encoding - * :method: GET - * :scheme: http - * :path: / - * :authority: www.example.com - * cache-control: no-cache - */ - ubyte[12] eexpected = [0x82, 0x86, 0x84, 0xbe, 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf]; - auto bbres = appender!(ubyte[]); - block.encodeHPACK(bbres, table, true); - assert(bbres.data == eexpected); -} - -/// DECODER -unittest { - //// Following examples can be found in Appendix C of the HPACK RFC - - import vibe.internal.utilallocator: RegionListAllocator; - import std.experimental.allocator; - import std.experimental.allocator.gc_allocator; - - auto table = IndexingTable(4096); - scope alloc = new RegionListAllocator!(shared(GCAllocator), false)(1024, GCAllocator.instance); - - /** 1. Literal header field w. indexing (raw) - * custom-key: custom-header - */ - immutable(ubyte)[] block = [0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, - 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72]; - - //auto decoder = HeaderDecoder!(ubyte[])(block, table); - auto dec1 = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(dec1, table, alloc); - assert(dec1.data.front.name == "custom-key" && dec1.data.front.value == "custom-header"); - // check entries to be inserted in the indexing table (dynamic) - assert(dec1.data.front.index); - - /** 1bis. Literal header field w. indexing (huffman encoded) - * :authority: www.example.com - */ - block = [0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff]; - auto dec1b = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(dec1b, table, alloc); - assert(dec1b.data.front.name == ":authority" && dec1b.data.front.value == "www.example.com"); - assert(dec1b.data.front.index); - - /** 2. Literal header field without indexing (raw) - * :path: /sample/path - */ - block = [0x04, 0x0c, 0x2f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68]; - auto dec2 = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(dec2, table, alloc); - assert(dec2.data.front.name == ":path" && dec2.data.front.value == "/sample/path"); - - - /** 3. Literal header field never indexed (raw) - * password: secret - */ - block = [0x10, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x06, 0x73, 0x65, - 0x63, 0x72, 0x65, 0x74]; - auto dec3 = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(dec3, table, alloc); - assert(dec3.data.front.name == "password" && dec3.data.front.value == "secret"); - assert(dec3.data.front.neverIndex); - - - /** 4. Indexed header field (integer) - * :method: GET - */ - import vibe.http.common; - block = [0x82]; - auto dec4 = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(dec4, table, alloc); - assert(dec4.data.front.name == ":method" && dec4.data.front.value == HTTPMethod.GET); - - /** 5. Full request without huffman encoding - * :method: GET - * :scheme: http - * :path: / - * :authority: www.example.com - * cache-control: no-cache - */ - block = [0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65]; - table.insert(HTTP2HeaderTableField(":authority", "www.example.com")); - auto decR1 = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(decR1, table, alloc); - HTTP2HeaderTableField[] expected = [ - HTTP2HeaderTableField(":method", HTTPMethod.GET), - HTTP2HeaderTableField(":scheme", "http"), - HTTP2HeaderTableField(":path", "/"), - HTTP2HeaderTableField(":authority", "www.example.com"), - HTTP2HeaderTableField("cache-control", "no-cache")]; - - foreach(i,h; decR1.data.enumerate(0)) { - assert(h == expected[i]); - } - - /** 5. Full request with huffman encoding - * :method: GET - * :scheme: http - * :path: / - * :authority: www.example.com - * cache-control: no-cache - */ - block = [0x82, 0x86, 0x84, 0xbe, 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c,0xbf]; - auto decR2 = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(decR2, table, alloc); - - foreach(i,h; decR2.data.enumerate(0)) { - assert(h == expected[i]); - } - - /** Cookie header - * cookie: filter=downloading - */ - auto ckexp = HTTP2HeaderTableField("cookie", "filter=downloading"); - block = [96, 141, 148, 212, 36, 182, 65, 33, 252, 85, 65, 199, 33, 170, 155]; - auto ckdec = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(ckdec, table, alloc); - assert(ckdec.data.front == ckexp); -} - - -/// Mallocator -unittest { - import vibe.internal.utilallocator: RegionListAllocator; - import std.experimental.allocator; - import std.experimental.allocator.mallocator; - import std.experimental.allocator.gc_allocator; - auto table = IndexingTable(4096); - /** 1bis. Literal header field w. indexing (huffman encoded) - * :authority: www.example.com - */ - immutable(ubyte)[] block = [0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff]; - scope alloc = new RegionListAllocator!(shared(Mallocator), false)(1024, Mallocator.instance); - - auto dec1b = appender!(HTTP2HeaderTableField[]); - block.decodeHPACK(dec1b, table, alloc); - assert(dec1b.data.front.name == ":authority" && dec1b.data.front.value == "www.example.com"); - assert(dec1b.data.front.index); -} diff --git a/source/vibe/http/internal/http2/hpack/huffman.d b/source/vibe/http/internal/http2/hpack/huffman.d deleted file mode 100644 index 30b21aa..0000000 --- a/source/vibe/http/internal/http2/hpack/huffman.d +++ /dev/null @@ -1,2807 +0,0 @@ -module vibe.http.internal.http2.hpack.huffman; - -import vibe.http.internal.http2.hpack.exception; - -import std.range; - -/** Huffman encoding for HPACK header compression - * The huffman table specifications can be found at: - * Appendix B of RFC 7541: https://tools.ietf.org/html/rfc7541#appendix-B -*/ -void encodeHuffman(I, O)(I source, ref O dst) @safe -{ - ulong bits; - int bitsLeft = 40; - size_t len = 0; - - // compute length - foreach(c; source) { - auto e = HuffEncodeCodes[c]; - len += e.length; - } - - dst.put(cast(ubyte)((len/8 ^ 128) + 1)); - - foreach(c; source) { - auto e = HuffEncodeCodes[c]; - bits |= (cast(ulong)e.code) << (bitsLeft - e.length); - bitsLeft -= e.length; - while(bitsLeft <= 32) { - dst.put(cast(ubyte)(bits >> 32)); - bits <<= 8; - bitsLeft += 8; - } - } - - if(bitsLeft != 40) { - bits |= ((cast(ulong)1) << bitsLeft) - 1; - dst.put(cast(ubyte)(bits >> 32)); - } -} - -@nogc unittest { - import vibe.internal.array : BatchBuffer; - - string src = "www.example.com"; - BatchBuffer!(ubyte, 13) bres; - bres.putN(13); - ubyte[13] expected = [0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff]; - encodeHuffman(src, bres); - assert(bres.peekDst == expected); -} - -/** Huffman decoding for HPACK header compression - * The huffman table specifications can be found at: - * Appendix B of RFC 7541: https://tools.ietf.org/html/rfc7541#appendix-B -*/ -void decodeHuffman(I, O)(I source, ref O dst) @safe -{ - auto block = cast(immutable(ubyte)[])source; - - char state = 0; - char eos = true; // termination flag - - while(!block.empty) { - char ch = block[0]; - block.popFront(); - decodeSymbol(dst, state, ch >> 4, eos); - decodeSymbol(dst, state, ch & 0xf, eos); - } - - enforceHPACK(eos, "Invalid encoded source"); -} - -private void decodeSymbol(O)(ref O decoded, ref char state, int pos, ref char eos) -@safe -{ - enforceHPACK(state < 256 && pos < 16, "Invalid entry reference"); - auto entry = HuffDecodeCodes[state][pos]; - enforceHPACK(entry.next != state, "Invalid symbol"); - - if (entry.emit) { // if the symbol is terminal - auto sym = cast(immutable(char))entry.symbol; - decoded.put(sym); - } - - state = entry.next; - eos = entry.ending; -} - -unittest { - import std.array; - immutable ubyte[] test = [0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff]; - - auto dst = appender!string; - decodeHuffman(test, dst); - assert(dst.data == "www.example.com"); - - immutable char[] ctest = [0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff]; - auto dst2 = appender!string; - decodeHuffman(ctest, dst2); - assert(dst2.data == "www.example.com"); -} - -unittest { // could be @nogc (exceptions aren't) - import vibe.internal.array : BatchBuffer; - - immutable ubyte[12] src = [0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff]; - BatchBuffer!(char, 15) bres; - bres.putN(15); - decodeHuffman(src, bres); - assert(bres.peekDst == "www.example.com"); -} - -private struct HuffCode { - char next; - char emit; - char symbol; - char ending; -} - -private struct HuffEncCode { - uint code; - size_t length; -} - -private static immutable HuffEncCode[256] HuffEncodeCodes = [ - {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, - {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, - {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28}, - {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28}, - {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28}, - {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28}, - {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28}, - {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28}, - {0x00000014, 6}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12}, - {0x00001ff9, 13}, {0x00000015, 6}, {0x000000f8, 8}, {0x000007fa, 11}, - {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f9, 8}, {0x000007fb, 11}, - {0x000000fa, 8}, {0x00000016, 6}, {0x00000017, 6}, {0x00000018, 6}, - {0x00000000, 5}, {0x00000001, 5}, {0x00000002, 5}, {0x00000019, 6}, - {0x0000001a, 6}, {0x0000001b, 6}, {0x0000001c, 6}, {0x0000001d, 6}, - {0x0000001e, 6}, {0x0000001f, 6}, {0x0000005c, 7}, {0x000000fb, 8}, - {0x00007ffc, 15}, {0x00000020, 6}, {0x00000ffb, 12}, {0x000003fc, 10}, - {0x00001ffa, 13}, {0x00000021, 6}, {0x0000005d, 7}, {0x0000005e, 7}, - {0x0000005f, 7}, {0x00000060, 7}, {0x00000061, 7}, {0x00000062, 7}, - {0x00000063, 7}, {0x00000064, 7}, {0x00000065, 7}, {0x00000066, 7}, - {0x00000067, 7}, {0x00000068, 7}, {0x00000069, 7}, {0x0000006a, 7}, - {0x0000006b, 7}, {0x0000006c, 7}, {0x0000006d, 7}, {0x0000006e, 7}, - {0x0000006f, 7}, {0x00000070, 7}, {0x00000071, 7}, {0x00000072, 7}, - {0x000000fc, 8}, {0x00000073, 7}, {0x000000fd, 8}, {0x00001ffb, 13}, - {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x00000022, 6}, - {0x00007ffd, 15}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, - {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, - {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, - {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, - {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, - {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, - {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00007ffe, 15}, - {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28}, - {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20}, - {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23}, - {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23}, - {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23}, - {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23}, - {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23}, - {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23}, - {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24}, - {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22}, - {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21}, - {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24}, - {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23}, - {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21}, - {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23}, - {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22}, - {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23}, - {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19}, - {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25}, - {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27}, - {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25}, - {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27}, - {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24}, - {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26}, - {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27}, - {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21}, - {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23}, - {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25}, - {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23}, - {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26}, - {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27}, - {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27}, - {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26} -]; - -private static immutable HuffCode[16][256] HuffDecodeCodes = [ - /* 0 */ - [ -// next emit sym ending next emit sym ending - {0x04, 0x00, 0x00, 0x00}, {0x05, 0x00, 0x00, 0x00}, - {0x07, 0x00, 0x00, 0x00}, {0x08, 0x00, 0x00, 0x00}, - {0x0b, 0x00, 0x00, 0x00}, {0x0c, 0x00, 0x00, 0x00}, - {0x10, 0x00, 0x00, 0x00}, {0x13, 0x00, 0x00, 0x00}, - {0x19, 0x00, 0x00, 0x00}, {0x1c, 0x00, 0x00, 0x00}, - {0x20, 0x00, 0x00, 0x00}, {0x23, 0x00, 0x00, 0x00}, - {0x2a, 0x00, 0x00, 0x00}, {0x31, 0x00, 0x00, 0x00}, - {0x39, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0x30, 0x01}, {0x00, 0x01, 0x31, 0x01}, - {0x00, 0x01, 0x32, 0x01}, {0x00, 0x01, 0x61, 0x01}, - {0x00, 0x01, 0x63, 0x01}, {0x00, 0x01, 0x65, 0x01}, - {0x00, 0x01, 0x69, 0x01}, {0x00, 0x01, 0x6f, 0x01}, - {0x00, 0x01, 0x73, 0x01}, {0x00, 0x01, 0x74, 0x01}, - {0x0d, 0x00, 0x00, 0x00}, {0x0e, 0x00, 0x00, 0x00}, - {0x11, 0x00, 0x00, 0x00}, {0x12, 0x00, 0x00, 0x00}, - {0x14, 0x00, 0x00, 0x00}, {0x15, 0x00, 0x00, 0x00} - ], - [ - {0x01, 0x01, 0x30, 0x00}, {0x16, 0x01, 0x30, 0x01}, - {0x01, 0x01, 0x31, 0x00}, {0x16, 0x01, 0x31, 0x01}, - {0x01, 0x01, 0x32, 0x00}, {0x16, 0x01, 0x32, 0x01}, - {0x01, 0x01, 0x61, 0x00}, {0x16, 0x01, 0x61, 0x01}, - {0x01, 0x01, 0x63, 0x00}, {0x16, 0x01, 0x63, 0x01}, - {0x01, 0x01, 0x65, 0x00}, {0x16, 0x01, 0x65, 0x01}, - {0x01, 0x01, 0x69, 0x00}, {0x16, 0x01, 0x69, 0x01}, - {0x01, 0x01, 0x6f, 0x00}, {0x16, 0x01, 0x6f, 0x01} - ], - [ - {0x02, 0x01, 0x30, 0x00}, {0x09, 0x01, 0x30, 0x00}, - {0x17, 0x01, 0x30, 0x00}, {0x28, 0x01, 0x30, 0x01}, - {0x02, 0x01, 0x31, 0x00}, {0x09, 0x01, 0x31, 0x00}, - {0x17, 0x01, 0x31, 0x00}, {0x28, 0x01, 0x31, 0x01}, - {0x02, 0x01, 0x32, 0x00}, {0x09, 0x01, 0x32, 0x00}, - {0x17, 0x01, 0x32, 0x00}, {0x28, 0x01, 0x32, 0x01}, - {0x02, 0x01, 0x61, 0x00}, {0x09, 0x01, 0x61, 0x00}, - {0x17, 0x01, 0x61, 0x00}, {0x28, 0x01, 0x61, 0x01} - ], - [ - {0x03, 0x01, 0x30, 0x00}, {0x06, 0x01, 0x30, 0x00}, - {0x0a, 0x01, 0x30, 0x00}, {0x0f, 0x01, 0x30, 0x00}, - {0x18, 0x01, 0x30, 0x00}, {0x1f, 0x01, 0x30, 0x00}, - {0x29, 0x01, 0x30, 0x00}, {0x38, 0x01, 0x30, 0x01}, - {0x03, 0x01, 0x31, 0x00}, {0x06, 0x01, 0x31, 0x00}, - {0x0a, 0x01, 0x31, 0x00}, {0x0f, 0x01, 0x31, 0x00}, - {0x18, 0x01, 0x31, 0x00}, {0x1f, 0x01, 0x31, 0x00}, - {0x29, 0x01, 0x31, 0x00}, {0x38, 0x01, 0x31, 0x01} - ], - /* 5 */ - [ - {0x03, 0x01, 0x32, 0x00}, {0x06, 0x01, 0x32, 0x00}, - {0x0a, 0x01, 0x32, 0x00}, {0x0f, 0x01, 0x32, 0x00}, - {0x18, 0x01, 0x32, 0x00}, {0x1f, 0x01, 0x32, 0x00}, - {0x29, 0x01, 0x32, 0x00}, {0x38, 0x01, 0x32, 0x01}, - {0x03, 0x01, 0x61, 0x00}, {0x06, 0x01, 0x61, 0x00}, - {0x0a, 0x01, 0x61, 0x00}, {0x0f, 0x01, 0x61, 0x00}, - {0x18, 0x01, 0x61, 0x00}, {0x1f, 0x01, 0x61, 0x00}, - {0x29, 0x01, 0x61, 0x00}, {0x38, 0x01, 0x61, 0x01} - ], - [ - {0x02, 0x01, 0x63, 0x00}, {0x09, 0x01, 0x63, 0x00}, - {0x17, 0x01, 0x63, 0x00}, {0x28, 0x01, 0x63, 0x01}, - {0x02, 0x01, 0x65, 0x00}, {0x09, 0x01, 0x65, 0x00}, - {0x17, 0x01, 0x65, 0x00}, {0x28, 0x01, 0x65, 0x01}, - {0x02, 0x01, 0x69, 0x00}, {0x09, 0x01, 0x69, 0x00}, - {0x17, 0x01, 0x69, 0x00}, {0x28, 0x01, 0x69, 0x01}, - {0x02, 0x01, 0x6f, 0x00}, {0x09, 0x01, 0x6f, 0x00}, - {0x17, 0x01, 0x6f, 0x00}, {0x28, 0x01, 0x6f, 0x01} - ], - [ - {0x03, 0x01, 0x63, 0x00}, {0x06, 0x01, 0x63, 0x00}, - {0x0a, 0x01, 0x63, 0x00}, {0x0f, 0x01, 0x63, 0x00}, - {0x18, 0x01, 0x63, 0x00}, {0x1f, 0x01, 0x63, 0x00}, - {0x29, 0x01, 0x63, 0x00}, {0x38, 0x01, 0x63, 0x01}, - {0x03, 0x01, 0x65, 0x00}, {0x06, 0x01, 0x65, 0x00}, - {0x0a, 0x01, 0x65, 0x00}, {0x0f, 0x01, 0x65, 0x00}, - {0x18, 0x01, 0x65, 0x00}, {0x1f, 0x01, 0x65, 0x00}, - {0x29, 0x01, 0x65, 0x00}, {0x38, 0x01, 0x65, 0x01} - ], - [ - {0x03, 0x01, 0x69, 0x00}, {0x06, 0x01, 0x69, 0x00}, - {0x0a, 0x01, 0x69, 0x00}, {0x0f, 0x01, 0x69, 0x00}, - {0x18, 0x01, 0x69, 0x00}, {0x1f, 0x01, 0x69, 0x00}, - {0x29, 0x01, 0x69, 0x00}, {0x38, 0x01, 0x69, 0x01}, - {0x03, 0x01, 0x6f, 0x00}, {0x06, 0x01, 0x6f, 0x00}, - {0x0a, 0x01, 0x6f, 0x00}, {0x0f, 0x01, 0x6f, 0x00}, - {0x18, 0x01, 0x6f, 0x00}, {0x1f, 0x01, 0x6f, 0x00}, - {0x29, 0x01, 0x6f, 0x00}, {0x38, 0x01, 0x6f, 0x01} - ], - [ - {0x01, 0x01, 0x73, 0x00}, {0x16, 0x01, 0x73, 0x01}, - {0x01, 0x01, 0x74, 0x00}, {0x16, 0x01, 0x74, 0x01}, - {0x00, 0x01, 0x20, 0x01}, {0x00, 0x01, 0x25, 0x01}, - {0x00, 0x01, 0x2d, 0x01}, {0x00, 0x01, 0x2e, 0x01}, - {0x00, 0x01, 0x2f, 0x01}, {0x00, 0x01, 0x33, 0x01}, - {0x00, 0x01, 0x34, 0x01}, {0x00, 0x01, 0x35, 0x01}, - {0x00, 0x01, 0x36, 0x01}, {0x00, 0x01, 0x37, 0x01}, - {0x00, 0x01, 0x38, 0x01}, {0x00, 0x01, 0x39, 0x01} - ], - /* 10 */ - [ - {0x02, 0x01, 0x73, 0x00}, {0x09, 0x01, 0x73, 0x00}, - {0x17, 0x01, 0x73, 0x00}, {0x28, 0x01, 0x73, 0x01}, - {0x02, 0x01, 0x74, 0x00}, {0x09, 0x01, 0x74, 0x00}, - {0x17, 0x01, 0x74, 0x00}, {0x28, 0x01, 0x74, 0x01}, - {0x01, 0x01, 0x20, 0x00}, {0x16, 0x01, 0x20, 0x01}, - {0x01, 0x01, 0x25, 0x00}, {0x16, 0x01, 0x25, 0x01}, - {0x01, 0x01, 0x2d, 0x00}, {0x16, 0x01, 0x2d, 0x01}, - {0x01, 0x01, 0x2e, 0x00}, {0x16, 0x01, 0x2e, 0x01} - ], - [ - {0x03, 0x01, 0x73, 0x00}, {0x06, 0x01, 0x73, 0x00}, - {0x0a, 0x01, 0x73, 0x00}, {0x0f, 0x01, 0x73, 0x00}, - {0x18, 0x01, 0x73, 0x00}, {0x1f, 0x01, 0x73, 0x00}, - {0x29, 0x01, 0x73, 0x00}, {0x38, 0x01, 0x73, 0x01}, - {0x03, 0x01, 0x74, 0x00}, {0x06, 0x01, 0x74, 0x00}, - {0x0a, 0x01, 0x74, 0x00}, {0x0f, 0x01, 0x74, 0x00}, - {0x18, 0x01, 0x74, 0x00}, {0x1f, 0x01, 0x74, 0x00}, - {0x29, 0x01, 0x74, 0x00}, {0x38, 0x01, 0x74, 0x01} - ], - [ - {0x02, 0x01, 0x20, 0x00}, {0x09, 0x01, 0x20, 0x00}, - {0x17, 0x01, 0x20, 0x00}, {0x28, 0x01, 0x20, 0x01}, - {0x02, 0x01, 0x25, 0x00}, {0x09, 0x01, 0x25, 0x00}, - {0x17, 0x01, 0x25, 0x00}, {0x28, 0x01, 0x25, 0x01}, - {0x02, 0x01, 0x2d, 0x00}, {0x09, 0x01, 0x2d, 0x00}, - {0x17, 0x01, 0x2d, 0x00}, {0x28, 0x01, 0x2d, 0x01}, - {0x02, 0x01, 0x2e, 0x00}, {0x09, 0x01, 0x2e, 0x00}, - {0x17, 0x01, 0x2e, 0x00}, {0x28, 0x01, 0x2e, 0x01} - ], - [ - {0x03, 0x01, 0x20, 0x00}, {0x06, 0x01, 0x20, 0x00}, - {0x0a, 0x01, 0x20, 0x00}, {0x0f, 0x01, 0x20, 0x00}, - {0x18, 0x01, 0x20, 0x00}, {0x1f, 0x01, 0x20, 0x00}, - {0x29, 0x01, 0x20, 0x00}, {0x38, 0x01, 0x20, 0x01}, - {0x03, 0x01, 0x25, 0x00}, {0x06, 0x01, 0x25, 0x00}, - {0x0a, 0x01, 0x25, 0x00}, {0x0f, 0x01, 0x25, 0x00}, - {0x18, 0x01, 0x25, 0x00}, {0x1f, 0x01, 0x25, 0x00}, - {0x29, 0x01, 0x25, 0x00}, {0x38, 0x01, 0x25, 0x01} - ], - [ - {0x03, 0x01, 0x2d, 0x00}, {0x06, 0x01, 0x2d, 0x00}, - {0x0a, 0x01, 0x2d, 0x00}, {0x0f, 0x01, 0x2d, 0x00}, - {0x18, 0x01, 0x2d, 0x00}, {0x1f, 0x01, 0x2d, 0x00}, - {0x29, 0x01, 0x2d, 0x00}, {0x38, 0x01, 0x2d, 0x01}, - {0x03, 0x01, 0x2e, 0x00}, {0x06, 0x01, 0x2e, 0x00}, - {0x0a, 0x01, 0x2e, 0x00}, {0x0f, 0x01, 0x2e, 0x00}, - {0x18, 0x01, 0x2e, 0x00}, {0x1f, 0x01, 0x2e, 0x00}, - {0x29, 0x01, 0x2e, 0x00}, {0x38, 0x01, 0x2e, 0x01} - ], - /* 15 */ - [ - {0x01, 0x01, 0x2f, 0x00}, {0x16, 0x01, 0x2f, 0x01}, - {0x01, 0x01, 0x33, 0x00}, {0x16, 0x01, 0x33, 0x01}, - {0x01, 0x01, 0x34, 0x00}, {0x16, 0x01, 0x34, 0x01}, - {0x01, 0x01, 0x35, 0x00}, {0x16, 0x01, 0x35, 0x01}, - {0x01, 0x01, 0x36, 0x00}, {0x16, 0x01, 0x36, 0x01}, - {0x01, 0x01, 0x37, 0x00}, {0x16, 0x01, 0x37, 0x01}, - {0x01, 0x01, 0x38, 0x00}, {0x16, 0x01, 0x38, 0x01}, - {0x01, 0x01, 0x39, 0x00}, {0x16, 0x01, 0x39, 0x01} - ], - [ - {0x02, 0x01, 0x2f, 0x00}, {0x09, 0x01, 0x2f, 0x00}, - {0x17, 0x01, 0x2f, 0x00}, {0x28, 0x01, 0x2f, 0x01}, - {0x02, 0x01, 0x33, 0x00}, {0x09, 0x01, 0x33, 0x00}, - {0x17, 0x01, 0x33, 0x00}, {0x28, 0x01, 0x33, 0x01}, - {0x02, 0x01, 0x34, 0x00}, {0x09, 0x01, 0x34, 0x00}, - {0x17, 0x01, 0x34, 0x00}, {0x28, 0x01, 0x34, 0x01}, - {0x02, 0x01, 0x35, 0x00}, {0x09, 0x01, 0x35, 0x00}, - {0x17, 0x01, 0x35, 0x00}, {0x28, 0x01, 0x35, 0x01} - ], - [ - {0x03, 0x01, 0x2f, 0x00}, {0x06, 0x01, 0x2f, 0x00}, - {0x0a, 0x01, 0x2f, 0x00}, {0x0f, 0x01, 0x2f, 0x00}, - {0x18, 0x01, 0x2f, 0x00}, {0x1f, 0x01, 0x2f, 0x00}, - {0x29, 0x01, 0x2f, 0x00}, {0x38, 0x01, 0x2f, 0x01}, - {0x03, 0x01, 0x33, 0x00}, {0x06, 0x01, 0x33, 0x00}, - {0x0a, 0x01, 0x33, 0x00}, {0x0f, 0x01, 0x33, 0x00}, - {0x18, 0x01, 0x33, 0x00}, {0x1f, 0x01, 0x33, 0x00}, - {0x29, 0x01, 0x33, 0x00}, {0x38, 0x01, 0x33, 0x01} - ], - [ - {0x03, 0x01, 0x34, 0x00}, {0x06, 0x01, 0x34, 0x00}, - {0x0a, 0x01, 0x34, 0x00}, {0x0f, 0x01, 0x34, 0x00}, - {0x18, 0x01, 0x34, 0x00}, {0x1f, 0x01, 0x34, 0x00}, - {0x29, 0x01, 0x34, 0x00}, {0x38, 0x01, 0x34, 0x01}, - {0x03, 0x01, 0x35, 0x00}, {0x06, 0x01, 0x35, 0x00}, - {0x0a, 0x01, 0x35, 0x00}, {0x0f, 0x01, 0x35, 0x00}, - {0x18, 0x01, 0x35, 0x00}, {0x1f, 0x01, 0x35, 0x00}, - {0x29, 0x01, 0x35, 0x00}, {0x38, 0x01, 0x35, 0x01} - ], - [ - {0x02, 0x01, 0x36, 0x00}, {0x09, 0x01, 0x36, 0x00}, - {0x17, 0x01, 0x36, 0x00}, {0x28, 0x01, 0x36, 0x01}, - {0x02, 0x01, 0x37, 0x00}, {0x09, 0x01, 0x37, 0x00}, - {0x17, 0x01, 0x37, 0x00}, {0x28, 0x01, 0x37, 0x01}, - {0x02, 0x01, 0x38, 0x00}, {0x09, 0x01, 0x38, 0x00}, - {0x17, 0x01, 0x38, 0x00}, {0x28, 0x01, 0x38, 0x01}, - {0x02, 0x01, 0x39, 0x00}, {0x09, 0x01, 0x39, 0x00}, - {0x17, 0x01, 0x39, 0x00}, {0x28, 0x01, 0x39, 0x01} - ], - /* 20 */ - [ - {0x03, 0x01, 0x36, 0x00}, {0x06, 0x01, 0x36, 0x00}, - {0x0a, 0x01, 0x36, 0x00}, {0x0f, 0x01, 0x36, 0x00}, - {0x18, 0x01, 0x36, 0x00}, {0x1f, 0x01, 0x36, 0x00}, - {0x29, 0x01, 0x36, 0x00}, {0x38, 0x01, 0x36, 0x01}, - {0x03, 0x01, 0x37, 0x00}, {0x06, 0x01, 0x37, 0x00}, - {0x0a, 0x01, 0x37, 0x00}, {0x0f, 0x01, 0x37, 0x00}, - {0x18, 0x01, 0x37, 0x00}, {0x1f, 0x01, 0x37, 0x00}, - {0x29, 0x01, 0x37, 0x00}, {0x38, 0x01, 0x37, 0x01} - ], - [ - {0x03, 0x01, 0x38, 0x00}, {0x06, 0x01, 0x38, 0x00}, - {0x0a, 0x01, 0x38, 0x00}, {0x0f, 0x01, 0x38, 0x00}, - {0x18, 0x01, 0x38, 0x00}, {0x1f, 0x01, 0x38, 0x00}, - {0x29, 0x01, 0x38, 0x00}, {0x38, 0x01, 0x38, 0x01}, - {0x03, 0x01, 0x39, 0x00}, {0x06, 0x01, 0x39, 0x00}, - {0x0a, 0x01, 0x39, 0x00}, {0x0f, 0x01, 0x39, 0x00}, - {0x18, 0x01, 0x39, 0x00}, {0x1f, 0x01, 0x39, 0x00}, - {0x29, 0x01, 0x39, 0x00}, {0x38, 0x01, 0x39, 0x01} - ], - [ - {0x1a, 0x00, 0x00, 0x00}, {0x1b, 0x00, 0x00, 0x00}, - {0x1d, 0x00, 0x00, 0x00}, {0x1e, 0x00, 0x00, 0x00}, - {0x21, 0x00, 0x00, 0x00}, {0x22, 0x00, 0x00, 0x00}, - {0x24, 0x00, 0x00, 0x00}, {0x25, 0x00, 0x00, 0x00}, - {0x2b, 0x00, 0x00, 0x00}, {0x2e, 0x00, 0x00, 0x00}, - {0x32, 0x00, 0x00, 0x00}, {0x35, 0x00, 0x00, 0x00}, - {0x3a, 0x00, 0x00, 0x00}, {0x3d, 0x00, 0x00, 0x00}, - {0x41, 0x00, 0x00, 0x00}, {0x44, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0x3d, 0x01}, {0x00, 0x01, 0x41, 0x01}, - {0x00, 0x01, 0x5f, 0x01}, {0x00, 0x01, 0x62, 0x01}, - {0x00, 0x01, 0x64, 0x01}, {0x00, 0x01, 0x66, 0x01}, - {0x00, 0x01, 0x67, 0x01}, {0x00, 0x01, 0x68, 0x01}, - {0x00, 0x01, 0x6c, 0x01}, {0x00, 0x01, 0x6d, 0x01}, - {0x00, 0x01, 0x6e, 0x01}, {0x00, 0x01, 0x70, 0x01}, - {0x00, 0x01, 0x72, 0x01}, {0x00, 0x01, 0x75, 0x01}, - {0x26, 0x00, 0x00, 0x00}, {0x27, 0x00, 0x00, 0x00} - ], - [ - {0x01, 0x01, 0x3d, 0x00}, {0x16, 0x01, 0x3d, 0x01}, - {0x01, 0x01, 0x41, 0x00}, {0x16, 0x01, 0x41, 0x01}, - {0x01, 0x01, 0x5f, 0x00}, {0x16, 0x01, 0x5f, 0x01}, - {0x01, 0x01, 0x62, 0x00}, {0x16, 0x01, 0x62, 0x01}, - {0x01, 0x01, 0x64, 0x00}, {0x16, 0x01, 0x64, 0x01}, - {0x01, 0x01, 0x66, 0x00}, {0x16, 0x01, 0x66, 0x01}, - {0x01, 0x01, 0x67, 0x00}, {0x16, 0x01, 0x67, 0x01}, - {0x01, 0x01, 0x68, 0x00}, {0x16, 0x01, 0x68, 0x01} - ], - /* 25 */ - [ - {0x02, 0x01, 0x3d, 0x00}, {0x09, 0x01, 0x3d, 0x00}, - {0x17, 0x01, 0x3d, 0x00}, {0x28, 0x01, 0x3d, 0x01}, - {0x02, 0x01, 0x41, 0x00}, {0x09, 0x01, 0x41, 0x00}, - {0x17, 0x01, 0x41, 0x00}, {0x28, 0x01, 0x41, 0x01}, - {0x02, 0x01, 0x5f, 0x00}, {0x09, 0x01, 0x5f, 0x00}, - {0x17, 0x01, 0x5f, 0x00}, {0x28, 0x01, 0x5f, 0x01}, - {0x02, 0x01, 0x62, 0x00}, {0x09, 0x01, 0x62, 0x00}, - {0x17, 0x01, 0x62, 0x00}, {0x28, 0x01, 0x62, 0x01} - ], - [ - {0x03, 0x01, 0x3d, 0x00}, {0x06, 0x01, 0x3d, 0x00}, - {0x0a, 0x01, 0x3d, 0x00}, {0x0f, 0x01, 0x3d, 0x00}, - {0x18, 0x01, 0x3d, 0x00}, {0x1f, 0x01, 0x3d, 0x00}, - {0x29, 0x01, 0x3d, 0x00}, {0x38, 0x01, 0x3d, 0x01}, - {0x03, 0x01, 0x41, 0x00}, {0x06, 0x01, 0x41, 0x00}, - {0x0a, 0x01, 0x41, 0x00}, {0x0f, 0x01, 0x41, 0x00}, - {0x18, 0x01, 0x41, 0x00}, {0x1f, 0x01, 0x41, 0x00}, - {0x29, 0x01, 0x41, 0x00}, {0x38, 0x01, 0x41, 0x01} - ], - [ - {0x03, 0x01, 0x5f, 0x00}, {0x06, 0x01, 0x5f, 0x00}, - {0x0a, 0x01, 0x5f, 0x00}, {0x0f, 0x01, 0x5f, 0x00}, - {0x18, 0x01, 0x5f, 0x00}, {0x1f, 0x01, 0x5f, 0x00}, - {0x29, 0x01, 0x5f, 0x00}, {0x38, 0x01, 0x5f, 0x01}, - {0x03, 0x01, 0x62, 0x00}, {0x06, 0x01, 0x62, 0x00}, - {0x0a, 0x01, 0x62, 0x00}, {0x0f, 0x01, 0x62, 0x00}, - {0x18, 0x01, 0x62, 0x00}, {0x1f, 0x01, 0x62, 0x00}, - {0x29, 0x01, 0x62, 0x00}, {0x38, 0x01, 0x62, 0x01} - ], - [ - {0x02, 0x01, 0x64, 0x00}, {0x09, 0x01, 0x64, 0x00}, - {0x17, 0x01, 0x64, 0x00}, {0x28, 0x01, 0x64, 0x01}, - {0x02, 0x01, 0x66, 0x00}, {0x09, 0x01, 0x66, 0x00}, - {0x17, 0x01, 0x66, 0x00}, {0x28, 0x01, 0x66, 0x01}, - {0x02, 0x01, 0x67, 0x00}, {0x09, 0x01, 0x67, 0x00}, - {0x17, 0x01, 0x67, 0x00}, {0x28, 0x01, 0x67, 0x01}, - {0x02, 0x01, 0x68, 0x00}, {0x09, 0x01, 0x68, 0x00}, - {0x17, 0x01, 0x68, 0x00}, {0x28, 0x01, 0x68, 0x01} - ], - [ - {0x03, 0x01, 0x64, 0x00}, {0x06, 0x01, 0x64, 0x00}, - {0x0a, 0x01, 0x64, 0x00}, {0x0f, 0x01, 0x64, 0x00}, - {0x18, 0x01, 0x64, 0x00}, {0x1f, 0x01, 0x64, 0x00}, - {0x29, 0x01, 0x64, 0x00}, {0x38, 0x01, 0x64, 0x01}, - {0x03, 0x01, 0x66, 0x00}, {0x06, 0x01, 0x66, 0x00}, - {0x0a, 0x01, 0x66, 0x00}, {0x0f, 0x01, 0x66, 0x00}, - {0x18, 0x01, 0x66, 0x00}, {0x1f, 0x01, 0x66, 0x00}, - {0x29, 0x01, 0x66, 0x00}, {0x38, 0x01, 0x66, 0x01} - ], - /* 30 */ - [ - {0x03, 0x01, 0x67, 0x00}, {0x06, 0x01, 0x67, 0x00}, - {0x0a, 0x01, 0x67, 0x00}, {0x0f, 0x01, 0x67, 0x00}, - {0x18, 0x01, 0x67, 0x00}, {0x1f, 0x01, 0x67, 0x00}, - {0x29, 0x01, 0x67, 0x00}, {0x38, 0x01, 0x67, 0x01}, - {0x03, 0x01, 0x68, 0x00}, {0x06, 0x01, 0x68, 0x00}, - {0x0a, 0x01, 0x68, 0x00}, {0x0f, 0x01, 0x68, 0x00}, - {0x18, 0x01, 0x68, 0x00}, {0x1f, 0x01, 0x68, 0x00}, - {0x29, 0x01, 0x68, 0x00}, {0x38, 0x01, 0x68, 0x01} - ], - [ - {0x01, 0x01, 0x6c, 0x00}, {0x16, 0x01, 0x6c, 0x01}, - {0x01, 0x01, 0x6d, 0x00}, {0x16, 0x01, 0x6d, 0x01}, - {0x01, 0x01, 0x6e, 0x00}, {0x16, 0x01, 0x6e, 0x01}, - {0x01, 0x01, 0x70, 0x00}, {0x16, 0x01, 0x70, 0x01}, - {0x01, 0x01, 0x72, 0x00}, {0x16, 0x01, 0x72, 0x01}, - {0x01, 0x01, 0x75, 0x00}, {0x16, 0x01, 0x75, 0x01}, - {0x00, 0x01, 0x3a, 0x01}, {0x00, 0x01, 0x42, 0x01}, - {0x00, 0x01, 0x43, 0x01}, {0x00, 0x01, 0x44, 0x01} - ], - [ - {0x02, 0x01, 0x6c, 0x00}, {0x09, 0x01, 0x6c, 0x00}, - {0x17, 0x01, 0x6c, 0x00}, {0x28, 0x01, 0x6c, 0x01}, - {0x02, 0x01, 0x6d, 0x00}, {0x09, 0x01, 0x6d, 0x00}, - {0x17, 0x01, 0x6d, 0x00}, {0x28, 0x01, 0x6d, 0x01}, - {0x02, 0x01, 0x6e, 0x00}, {0x09, 0x01, 0x6e, 0x00}, - {0x17, 0x01, 0x6e, 0x00}, {0x28, 0x01, 0x6e, 0x01}, - {0x02, 0x01, 0x70, 0x00}, {0x09, 0x01, 0x70, 0x00}, - {0x17, 0x01, 0x70, 0x00}, {0x28, 0x01, 0x70, 0x01} - ], - [ - {0x03, 0x01, 0x6c, 0x00}, {0x06, 0x01, 0x6c, 0x00}, - {0x0a, 0x01, 0x6c, 0x00}, {0x0f, 0x01, 0x6c, 0x00}, - {0x18, 0x01, 0x6c, 0x00}, {0x1f, 0x01, 0x6c, 0x00}, - {0x29, 0x01, 0x6c, 0x00}, {0x38, 0x01, 0x6c, 0x01}, - {0x03, 0x01, 0x6d, 0x00}, {0x06, 0x01, 0x6d, 0x00}, - {0x0a, 0x01, 0x6d, 0x00}, {0x0f, 0x01, 0x6d, 0x00}, - {0x18, 0x01, 0x6d, 0x00}, {0x1f, 0x01, 0x6d, 0x00}, - {0x29, 0x01, 0x6d, 0x00}, {0x38, 0x01, 0x6d, 0x01} - ], - [ - {0x03, 0x01, 0x6e, 0x00}, {0x06, 0x01, 0x6e, 0x00}, - {0x0a, 0x01, 0x6e, 0x00}, {0x0f, 0x01, 0x6e, 0x00}, - {0x18, 0x01, 0x6e, 0x00}, {0x1f, 0x01, 0x6e, 0x00}, - {0x29, 0x01, 0x6e, 0x00}, {0x38, 0x01, 0x6e, 0x01}, - {0x03, 0x01, 0x70, 0x00}, {0x06, 0x01, 0x70, 0x00}, - {0x0a, 0x01, 0x70, 0x00}, {0x0f, 0x01, 0x70, 0x00}, - {0x18, 0x01, 0x70, 0x00}, {0x1f, 0x01, 0x70, 0x00}, - {0x29, 0x01, 0x70, 0x00}, {0x38, 0x01, 0x70, 0x01} - ], - /* 35 */ - [ - {0x02, 0x01, 0x72, 0x00}, {0x09, 0x01, 0x72, 0x00}, - {0x17, 0x01, 0x72, 0x00}, {0x28, 0x01, 0x72, 0x01}, - {0x02, 0x01, 0x75, 0x00}, {0x09, 0x01, 0x75, 0x00}, - {0x17, 0x01, 0x75, 0x00}, {0x28, 0x01, 0x75, 0x01}, - {0x01, 0x01, 0x3a, 0x00}, {0x16, 0x01, 0x3a, 0x01}, - {0x01, 0x01, 0x42, 0x00}, {0x16, 0x01, 0x42, 0x01}, - {0x01, 0x01, 0x43, 0x00}, {0x16, 0x01, 0x43, 0x01}, - {0x01, 0x01, 0x44, 0x00}, {0x16, 0x01, 0x44, 0x01} - ], - [ - {0x03, 0x01, 0x72, 0x00}, {0x06, 0x01, 0x72, 0x00}, - {0x0a, 0x01, 0x72, 0x00}, {0x0f, 0x01, 0x72, 0x00}, - {0x18, 0x01, 0x72, 0x00}, {0x1f, 0x01, 0x72, 0x00}, - {0x29, 0x01, 0x72, 0x00}, {0x38, 0x01, 0x72, 0x01}, - {0x03, 0x01, 0x75, 0x00}, {0x06, 0x01, 0x75, 0x00}, - {0x0a, 0x01, 0x75, 0x00}, {0x0f, 0x01, 0x75, 0x00}, - {0x18, 0x01, 0x75, 0x00}, {0x1f, 0x01, 0x75, 0x00}, - {0x29, 0x01, 0x75, 0x00}, {0x38, 0x01, 0x75, 0x01} - ], - [ - {0x02, 0x01, 0x3a, 0x00}, {0x09, 0x01, 0x3a, 0x00}, - {0x17, 0x01, 0x3a, 0x00}, {0x28, 0x01, 0x3a, 0x01}, - {0x02, 0x01, 0x42, 0x00}, {0x09, 0x01, 0x42, 0x00}, - {0x17, 0x01, 0x42, 0x00}, {0x28, 0x01, 0x42, 0x01}, - {0x02, 0x01, 0x43, 0x00}, {0x09, 0x01, 0x43, 0x00}, - {0x17, 0x01, 0x43, 0x00}, {0x28, 0x01, 0x43, 0x01}, - {0x02, 0x01, 0x44, 0x00}, {0x09, 0x01, 0x44, 0x00}, - {0x17, 0x01, 0x44, 0x00}, {0x28, 0x01, 0x44, 0x01} - ], - [ - {0x03, 0x01, 0x3a, 0x00}, {0x06, 0x01, 0x3a, 0x00}, - {0x0a, 0x01, 0x3a, 0x00}, {0x0f, 0x01, 0x3a, 0x00}, - {0x18, 0x01, 0x3a, 0x00}, {0x1f, 0x01, 0x3a, 0x00}, - {0x29, 0x01, 0x3a, 0x00}, {0x38, 0x01, 0x3a, 0x01}, - {0x03, 0x01, 0x42, 0x00}, {0x06, 0x01, 0x42, 0x00}, - {0x0a, 0x01, 0x42, 0x00}, {0x0f, 0x01, 0x42, 0x00}, - {0x18, 0x01, 0x42, 0x00}, {0x1f, 0x01, 0x42, 0x00}, - {0x29, 0x01, 0x42, 0x00}, {0x38, 0x01, 0x42, 0x01} - ], - [ - {0x03, 0x01, 0x43, 0x00}, {0x06, 0x01, 0x43, 0x00}, - {0x0a, 0x01, 0x43, 0x00}, {0x0f, 0x01, 0x43, 0x00}, - {0x18, 0x01, 0x43, 0x00}, {0x1f, 0x01, 0x43, 0x00}, - {0x29, 0x01, 0x43, 0x00}, {0x38, 0x01, 0x43, 0x01}, - {0x03, 0x01, 0x44, 0x00}, {0x06, 0x01, 0x44, 0x00}, - {0x0a, 0x01, 0x44, 0x00}, {0x0f, 0x01, 0x44, 0x00}, - {0x18, 0x01, 0x44, 0x00}, {0x1f, 0x01, 0x44, 0x00}, - {0x29, 0x01, 0x44, 0x00}, {0x38, 0x01, 0x44, 0x01} - ], - /* 40 */ - [ - {0x2c, 0x00, 0x00, 0x00}, {0x2d, 0x00, 0x00, 0x00}, - {0x2f, 0x00, 0x00, 0x00}, {0x30, 0x00, 0x00, 0x00}, - {0x33, 0x00, 0x00, 0x00}, {0x34, 0x00, 0x00, 0x00}, - {0x36, 0x00, 0x00, 0x00}, {0x37, 0x00, 0x00, 0x00}, - {0x3b, 0x00, 0x00, 0x00}, {0x3c, 0x00, 0x00, 0x00}, - {0x3e, 0x00, 0x00, 0x00}, {0x3f, 0x00, 0x00, 0x00}, - {0x42, 0x00, 0x00, 0x00}, {0x43, 0x00, 0x00, 0x00}, - {0x45, 0x00, 0x00, 0x00}, {0x48, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0x45, 0x01}, {0x00, 0x01, 0x46, 0x01}, - {0x00, 0x01, 0x47, 0x01}, {0x00, 0x01, 0x48, 0x01}, - {0x00, 0x01, 0x49, 0x01}, {0x00, 0x01, 0x4a, 0x01}, - {0x00, 0x01, 0x4b, 0x01}, {0x00, 0x01, 0x4c, 0x01}, - {0x00, 0x01, 0x4d, 0x01}, {0x00, 0x01, 0x4e, 0x01}, - {0x00, 0x01, 0x4f, 0x01}, {0x00, 0x01, 0x50, 0x01}, - {0x00, 0x01, 0x51, 0x01}, {0x00, 0x01, 0x52, 0x01}, - {0x00, 0x01, 0x53, 0x01}, {0x00, 0x01, 0x54, 0x01} - ], - [ - {0x01, 0x01, 0x45, 0x00}, {0x16, 0x01, 0x45, 0x01}, - {0x01, 0x01, 0x46, 0x00}, {0x16, 0x01, 0x46, 0x01}, - {0x01, 0x01, 0x47, 0x00}, {0x16, 0x01, 0x47, 0x01}, - {0x01, 0x01, 0x48, 0x00}, {0x16, 0x01, 0x48, 0x01}, - {0x01, 0x01, 0x49, 0x00}, {0x16, 0x01, 0x49, 0x01}, - {0x01, 0x01, 0x4a, 0x00}, {0x16, 0x01, 0x4a, 0x01}, - {0x01, 0x01, 0x4b, 0x00}, {0x16, 0x01, 0x4b, 0x01}, - {0x01, 0x01, 0x4c, 0x00}, {0x16, 0x01, 0x4c, 0x01} - ], - [ - {0x02, 0x01, 0x45, 0x00}, {0x09, 0x01, 0x45, 0x00}, - {0x17, 0x01, 0x45, 0x00}, {0x28, 0x01, 0x45, 0x01}, - {0x02, 0x01, 0x46, 0x00}, {0x09, 0x01, 0x46, 0x00}, - {0x17, 0x01, 0x46, 0x00}, {0x28, 0x01, 0x46, 0x01}, - {0x02, 0x01, 0x47, 0x00}, {0x09, 0x01, 0x47, 0x00}, - {0x17, 0x01, 0x47, 0x00}, {0x28, 0x01, 0x47, 0x01}, - {0x02, 0x01, 0x48, 0x00}, {0x09, 0x01, 0x48, 0x00}, - {0x17, 0x01, 0x48, 0x00}, {0x28, 0x01, 0x48, 0x01} - ], - [ - {0x03, 0x01, 0x45, 0x00}, {0x06, 0x01, 0x45, 0x00}, - {0x0a, 0x01, 0x45, 0x00}, {0x0f, 0x01, 0x45, 0x00}, - {0x18, 0x01, 0x45, 0x00}, {0x1f, 0x01, 0x45, 0x00}, - {0x29, 0x01, 0x45, 0x00}, {0x38, 0x01, 0x45, 0x01}, - {0x03, 0x01, 0x46, 0x00}, {0x06, 0x01, 0x46, 0x00}, - {0x0a, 0x01, 0x46, 0x00}, {0x0f, 0x01, 0x46, 0x00}, - {0x18, 0x01, 0x46, 0x00}, {0x1f, 0x01, 0x46, 0x00}, - {0x29, 0x01, 0x46, 0x00}, {0x38, 0x01, 0x46, 0x01} - ], - /* 45 */ - [ - {0x03, 0x01, 0x47, 0x00}, {0x06, 0x01, 0x47, 0x00}, - {0x0a, 0x01, 0x47, 0x00}, {0x0f, 0x01, 0x47, 0x00}, - {0x18, 0x01, 0x47, 0x00}, {0x1f, 0x01, 0x47, 0x00}, - {0x29, 0x01, 0x47, 0x00}, {0x38, 0x01, 0x47, 0x01}, - {0x03, 0x01, 0x48, 0x00}, {0x06, 0x01, 0x48, 0x00}, - {0x0a, 0x01, 0x48, 0x00}, {0x0f, 0x01, 0x48, 0x00}, - {0x18, 0x01, 0x48, 0x00}, {0x1f, 0x01, 0x48, 0x00}, - {0x29, 0x01, 0x48, 0x00}, {0x38, 0x01, 0x48, 0x01} - ], - [ - {0x02, 0x01, 0x49, 0x00}, {0x09, 0x01, 0x49, 0x00}, - {0x17, 0x01, 0x49, 0x00}, {0x28, 0x01, 0x49, 0x01}, - {0x02, 0x01, 0x4a, 0x00}, {0x09, 0x01, 0x4a, 0x00}, - {0x17, 0x01, 0x4a, 0x00}, {0x28, 0x01, 0x4a, 0x01}, - {0x02, 0x01, 0x4b, 0x00}, {0x09, 0x01, 0x4b, 0x00}, - {0x17, 0x01, 0x4b, 0x00}, {0x28, 0x01, 0x4b, 0x01}, - {0x02, 0x01, 0x4c, 0x00}, {0x09, 0x01, 0x4c, 0x00}, - {0x17, 0x01, 0x4c, 0x00}, {0x28, 0x01, 0x4c, 0x01} - ], - [ - {0x03, 0x01, 0x49, 0x00}, {0x06, 0x01, 0x49, 0x00}, - {0x0a, 0x01, 0x49, 0x00}, {0x0f, 0x01, 0x49, 0x00}, - {0x18, 0x01, 0x49, 0x00}, {0x1f, 0x01, 0x49, 0x00}, - {0x29, 0x01, 0x49, 0x00}, {0x38, 0x01, 0x49, 0x01}, - {0x03, 0x01, 0x4a, 0x00}, {0x06, 0x01, 0x4a, 0x00}, - {0x0a, 0x01, 0x4a, 0x00}, {0x0f, 0x01, 0x4a, 0x00}, - {0x18, 0x01, 0x4a, 0x00}, {0x1f, 0x01, 0x4a, 0x00}, - {0x29, 0x01, 0x4a, 0x00}, {0x38, 0x01, 0x4a, 0x01} - ], - [ - {0x03, 0x01, 0x4b, 0x00}, {0x06, 0x01, 0x4b, 0x00}, - {0x0a, 0x01, 0x4b, 0x00}, {0x0f, 0x01, 0x4b, 0x00}, - {0x18, 0x01, 0x4b, 0x00}, {0x1f, 0x01, 0x4b, 0x00}, - {0x29, 0x01, 0x4b, 0x00}, {0x38, 0x01, 0x4b, 0x01}, - {0x03, 0x01, 0x4c, 0x00}, {0x06, 0x01, 0x4c, 0x00}, - {0x0a, 0x01, 0x4c, 0x00}, {0x0f, 0x01, 0x4c, 0x00}, - {0x18, 0x01, 0x4c, 0x00}, {0x1f, 0x01, 0x4c, 0x00}, - {0x29, 0x01, 0x4c, 0x00}, {0x38, 0x01, 0x4c, 0x01} - ], - [ - {0x01, 0x01, 0x4d, 0x00}, {0x16, 0x01, 0x4d, 0x01}, - {0x01, 0x01, 0x4e, 0x00}, {0x16, 0x01, 0x4e, 0x01}, - {0x01, 0x01, 0x4f, 0x00}, {0x16, 0x01, 0x4f, 0x01}, - {0x01, 0x01, 0x50, 0x00}, {0x16, 0x01, 0x50, 0x01}, - {0x01, 0x01, 0x51, 0x00}, {0x16, 0x01, 0x51, 0x01}, - {0x01, 0x01, 0x52, 0x00}, {0x16, 0x01, 0x52, 0x01}, - {0x01, 0x01, 0x53, 0x00}, {0x16, 0x01, 0x53, 0x01}, - {0x01, 0x01, 0x54, 0x00}, {0x16, 0x01, 0x54, 0x01} - ], - /* 50 */ - [ - {0x02, 0x01, 0x4d, 0x00}, {0x09, 0x01, 0x4d, 0x00}, - {0x17, 0x01, 0x4d, 0x00}, {0x28, 0x01, 0x4d, 0x01}, - {0x02, 0x01, 0x4e, 0x00}, {0x09, 0x01, 0x4e, 0x00}, - {0x17, 0x01, 0x4e, 0x00}, {0x28, 0x01, 0x4e, 0x01}, - {0x02, 0x01, 0x4f, 0x00}, {0x09, 0x01, 0x4f, 0x00}, - {0x17, 0x01, 0x4f, 0x00}, {0x28, 0x01, 0x4f, 0x01}, - {0x02, 0x01, 0x50, 0x00}, {0x09, 0x01, 0x50, 0x00}, - {0x17, 0x01, 0x50, 0x00}, {0x28, 0x01, 0x50, 0x01} - ], - [ - {0x03, 0x01, 0x4d, 0x00}, {0x06, 0x01, 0x4d, 0x00}, - {0x0a, 0x01, 0x4d, 0x00}, {0x0f, 0x01, 0x4d, 0x00}, - {0x18, 0x01, 0x4d, 0x00}, {0x1f, 0x01, 0x4d, 0x00}, - {0x29, 0x01, 0x4d, 0x00}, {0x38, 0x01, 0x4d, 0x01}, - {0x03, 0x01, 0x4e, 0x00}, {0x06, 0x01, 0x4e, 0x00}, - {0x0a, 0x01, 0x4e, 0x00}, {0x0f, 0x01, 0x4e, 0x00}, - {0x18, 0x01, 0x4e, 0x00}, {0x1f, 0x01, 0x4e, 0x00}, - {0x29, 0x01, 0x4e, 0x00}, {0x38, 0x01, 0x4e, 0x01} - ], - [ - {0x03, 0x01, 0x4f, 0x00}, {0x06, 0x01, 0x4f, 0x00}, - {0x0a, 0x01, 0x4f, 0x00}, {0x0f, 0x01, 0x4f, 0x00}, - {0x18, 0x01, 0x4f, 0x00}, {0x1f, 0x01, 0x4f, 0x00}, - {0x29, 0x01, 0x4f, 0x00}, {0x38, 0x01, 0x4f, 0x01}, - {0x03, 0x01, 0x50, 0x00}, {0x06, 0x01, 0x50, 0x00}, - {0x0a, 0x01, 0x50, 0x00}, {0x0f, 0x01, 0x50, 0x00}, - {0x18, 0x01, 0x50, 0x00}, {0x1f, 0x01, 0x50, 0x00}, - {0x29, 0x01, 0x50, 0x00}, {0x38, 0x01, 0x50, 0x01} - ], - [ - {0x02, 0x01, 0x51, 0x00}, {0x09, 0x01, 0x51, 0x00}, - {0x17, 0x01, 0x51, 0x00}, {0x28, 0x01, 0x51, 0x01}, - {0x02, 0x01, 0x52, 0x00}, {0x09, 0x01, 0x52, 0x00}, - {0x17, 0x01, 0x52, 0x00}, {0x28, 0x01, 0x52, 0x01}, - {0x02, 0x01, 0x53, 0x00}, {0x09, 0x01, 0x53, 0x00}, - {0x17, 0x01, 0x53, 0x00}, {0x28, 0x01, 0x53, 0x01}, - {0x02, 0x01, 0x54, 0x00}, {0x09, 0x01, 0x54, 0x00}, - {0x17, 0x01, 0x54, 0x00}, {0x28, 0x01, 0x54, 0x01} - ], - [ - {0x03, 0x01, 0x51, 0x00}, {0x06, 0x01, 0x51, 0x00}, - {0x0a, 0x01, 0x51, 0x00}, {0x0f, 0x01, 0x51, 0x00}, - {0x18, 0x01, 0x51, 0x00}, {0x1f, 0x01, 0x51, 0x00}, - {0x29, 0x01, 0x51, 0x00}, {0x38, 0x01, 0x51, 0x01}, - {0x03, 0x01, 0x52, 0x00}, {0x06, 0x01, 0x52, 0x00}, - {0x0a, 0x01, 0x52, 0x00}, {0x0f, 0x01, 0x52, 0x00}, - {0x18, 0x01, 0x52, 0x00}, {0x1f, 0x01, 0x52, 0x00}, - {0x29, 0x01, 0x52, 0x00}, {0x38, 0x01, 0x52, 0x01} - ], - /* 55 */ - [ - {0x03, 0x01, 0x53, 0x00}, {0x06, 0x01, 0x53, 0x00}, - {0x0a, 0x01, 0x53, 0x00}, {0x0f, 0x01, 0x53, 0x00}, - {0x18, 0x01, 0x53, 0x00}, {0x1f, 0x01, 0x53, 0x00}, - {0x29, 0x01, 0x53, 0x00}, {0x38, 0x01, 0x53, 0x01}, - {0x03, 0x01, 0x54, 0x00}, {0x06, 0x01, 0x54, 0x00}, - {0x0a, 0x01, 0x54, 0x00}, {0x0f, 0x01, 0x54, 0x00}, - {0x18, 0x01, 0x54, 0x00}, {0x1f, 0x01, 0x54, 0x00}, - {0x29, 0x01, 0x54, 0x00}, {0x38, 0x01, 0x54, 0x01} - ], - [ - {0x00, 0x01, 0x55, 0x01}, {0x00, 0x01, 0x56, 0x01}, - {0x00, 0x01, 0x57, 0x01}, {0x00, 0x01, 0x59, 0x01}, - {0x00, 0x01, 0x6a, 0x01}, {0x00, 0x01, 0x6b, 0x01}, - {0x00, 0x01, 0x71, 0x01}, {0x00, 0x01, 0x76, 0x01}, - {0x00, 0x01, 0x77, 0x01}, {0x00, 0x01, 0x78, 0x01}, - {0x00, 0x01, 0x79, 0x01}, {0x00, 0x01, 0x7a, 0x01}, - {0x46, 0x00, 0x00, 0x00}, {0x47, 0x00, 0x00, 0x00}, - {0x49, 0x00, 0x00, 0x00}, {0x4a, 0x00, 0x00, 0x01} - ], - [ - {0x01, 0x01, 0x55, 0x00}, {0x16, 0x01, 0x55, 0x01}, - {0x01, 0x01, 0x56, 0x00}, {0x16, 0x01, 0x56, 0x01}, - {0x01, 0x01, 0x57, 0x00}, {0x16, 0x01, 0x57, 0x01}, - {0x01, 0x01, 0x59, 0x00}, {0x16, 0x01, 0x59, 0x01}, - {0x01, 0x01, 0x6a, 0x00}, {0x16, 0x01, 0x6a, 0x01}, - {0x01, 0x01, 0x6b, 0x00}, {0x16, 0x01, 0x6b, 0x01}, - {0x01, 0x01, 0x71, 0x00}, {0x16, 0x01, 0x71, 0x01}, - {0x01, 0x01, 0x76, 0x00}, {0x16, 0x01, 0x76, 0x01} - ], - [ - {0x02, 0x01, 0x55, 0x00}, {0x09, 0x01, 0x55, 0x00}, - {0x17, 0x01, 0x55, 0x00}, {0x28, 0x01, 0x55, 0x01}, - {0x02, 0x01, 0x56, 0x00}, {0x09, 0x01, 0x56, 0x00}, - {0x17, 0x01, 0x56, 0x00}, {0x28, 0x01, 0x56, 0x01}, - {0x02, 0x01, 0x57, 0x00}, {0x09, 0x01, 0x57, 0x00}, - {0x17, 0x01, 0x57, 0x00}, {0x28, 0x01, 0x57, 0x01}, - {0x02, 0x01, 0x59, 0x00}, {0x09, 0x01, 0x59, 0x00}, - {0x17, 0x01, 0x59, 0x00}, {0x28, 0x01, 0x59, 0x01} - ], - [ - {0x03, 0x01, 0x55, 0x00}, {0x06, 0x01, 0x55, 0x00}, - {0x0a, 0x01, 0x55, 0x00}, {0x0f, 0x01, 0x55, 0x00}, - {0x18, 0x01, 0x55, 0x00}, {0x1f, 0x01, 0x55, 0x00}, - {0x29, 0x01, 0x55, 0x00}, {0x38, 0x01, 0x55, 0x01}, - {0x03, 0x01, 0x56, 0x00}, {0x06, 0x01, 0x56, 0x00}, - {0x0a, 0x01, 0x56, 0x00}, {0x0f, 0x01, 0x56, 0x00}, - {0x18, 0x01, 0x56, 0x00}, {0x1f, 0x01, 0x56, 0x00}, - {0x29, 0x01, 0x56, 0x00}, {0x38, 0x01, 0x56, 0x01} - ], - /* 60 */ - [ - {0x03, 0x01, 0x57, 0x00}, {0x06, 0x01, 0x57, 0x00}, - {0x0a, 0x01, 0x57, 0x00}, {0x0f, 0x01, 0x57, 0x00}, - {0x18, 0x01, 0x57, 0x00}, {0x1f, 0x01, 0x57, 0x00}, - {0x29, 0x01, 0x57, 0x00}, {0x38, 0x01, 0x57, 0x01}, - {0x03, 0x01, 0x59, 0x00}, {0x06, 0x01, 0x59, 0x00}, - {0x0a, 0x01, 0x59, 0x00}, {0x0f, 0x01, 0x59, 0x00}, - {0x18, 0x01, 0x59, 0x00}, {0x1f, 0x01, 0x59, 0x00}, - {0x29, 0x01, 0x59, 0x00}, {0x38, 0x01, 0x59, 0x01} - ], - [ - {0x02, 0x01, 0x6a, 0x00}, {0x09, 0x01, 0x6a, 0x00}, - {0x17, 0x01, 0x6a, 0x00}, {0x28, 0x01, 0x6a, 0x01}, - {0x02, 0x01, 0x6b, 0x00}, {0x09, 0x01, 0x6b, 0x00}, - {0x17, 0x01, 0x6b, 0x00}, {0x28, 0x01, 0x6b, 0x01}, - {0x02, 0x01, 0x71, 0x00}, {0x09, 0x01, 0x71, 0x00}, - {0x17, 0x01, 0x71, 0x00}, {0x28, 0x01, 0x71, 0x01}, - {0x02, 0x01, 0x76, 0x00}, {0x09, 0x01, 0x76, 0x00}, - {0x17, 0x01, 0x76, 0x00}, {0x28, 0x01, 0x76, 0x01} - ], - [ - {0x03, 0x01, 0x6a, 0x00}, {0x06, 0x01, 0x6a, 0x00}, - {0x0a, 0x01, 0x6a, 0x00}, {0x0f, 0x01, 0x6a, 0x00}, - {0x18, 0x01, 0x6a, 0x00}, {0x1f, 0x01, 0x6a, 0x00}, - {0x29, 0x01, 0x6a, 0x00}, {0x38, 0x01, 0x6a, 0x01}, - {0x03, 0x01, 0x6b, 0x00}, {0x06, 0x01, 0x6b, 0x00}, - {0x0a, 0x01, 0x6b, 0x00}, {0x0f, 0x01, 0x6b, 0x00}, - {0x18, 0x01, 0x6b, 0x00}, {0x1f, 0x01, 0x6b, 0x00}, - {0x29, 0x01, 0x6b, 0x00}, {0x38, 0x01, 0x6b, 0x01} - ], - [ - {0x03, 0x01, 0x71, 0x00}, {0x06, 0x01, 0x71, 0x00}, - {0x0a, 0x01, 0x71, 0x00}, {0x0f, 0x01, 0x71, 0x00}, - {0x18, 0x01, 0x71, 0x00}, {0x1f, 0x01, 0x71, 0x00}, - {0x29, 0x01, 0x71, 0x00}, {0x38, 0x01, 0x71, 0x01}, - {0x03, 0x01, 0x76, 0x00}, {0x06, 0x01, 0x76, 0x00}, - {0x0a, 0x01, 0x76, 0x00}, {0x0f, 0x01, 0x76, 0x00}, - {0x18, 0x01, 0x76, 0x00}, {0x1f, 0x01, 0x76, 0x00}, - {0x29, 0x01, 0x76, 0x00}, {0x38, 0x01, 0x76, 0x01} - ], - [ - {0x01, 0x01, 0x77, 0x00}, {0x16, 0x01, 0x77, 0x01}, - {0x01, 0x01, 0x78, 0x00}, {0x16, 0x01, 0x78, 0x01}, - {0x01, 0x01, 0x79, 0x00}, {0x16, 0x01, 0x79, 0x01}, - {0x01, 0x01, 0x7a, 0x00}, {0x16, 0x01, 0x7a, 0x01}, - {0x00, 0x01, 0x26, 0x01}, {0x00, 0x01, 0x2a, 0x01}, - {0x00, 0x01, 0x2c, 0x01}, {0x00, 0x01, 0x3b, 0x01}, - {0x00, 0x01, 0x58, 0x01}, {0x00, 0x01, 0x5a, 0x01}, - {0x4b, 0x00, 0x00, 0x00}, {0x4e, 0x00, 0x00, 0x01} - ], - /* 65 */ - [ - {0x02, 0x01, 0x77, 0x00}, {0x09, 0x01, 0x77, 0x00}, - {0x17, 0x01, 0x77, 0x00}, {0x28, 0x01, 0x77, 0x01}, - {0x02, 0x01, 0x78, 0x00}, {0x09, 0x01, 0x78, 0x00}, - {0x17, 0x01, 0x78, 0x00}, {0x28, 0x01, 0x78, 0x01}, - {0x02, 0x01, 0x79, 0x00}, {0x09, 0x01, 0x79, 0x00}, - {0x17, 0x01, 0x79, 0x00}, {0x28, 0x01, 0x79, 0x01}, - {0x02, 0x01, 0x7a, 0x00}, {0x09, 0x01, 0x7a, 0x00}, - {0x17, 0x01, 0x7a, 0x00}, {0x28, 0x01, 0x7a, 0x01} - ], - [ - {0x03, 0x01, 0x77, 0x00}, {0x06, 0x01, 0x77, 0x00}, - {0x0a, 0x01, 0x77, 0x00}, {0x0f, 0x01, 0x77, 0x00}, - {0x18, 0x01, 0x77, 0x00}, {0x1f, 0x01, 0x77, 0x00}, - {0x29, 0x01, 0x77, 0x00}, {0x38, 0x01, 0x77, 0x01}, - {0x03, 0x01, 0x78, 0x00}, {0x06, 0x01, 0x78, 0x00}, - {0x0a, 0x01, 0x78, 0x00}, {0x0f, 0x01, 0x78, 0x00}, - {0x18, 0x01, 0x78, 0x00}, {0x1f, 0x01, 0x78, 0x00}, - {0x29, 0x01, 0x78, 0x00}, {0x38, 0x01, 0x78, 0x01} - ], - [ - {0x03, 0x01, 0x79, 0x00}, {0x06, 0x01, 0x79, 0x00}, - {0x0a, 0x01, 0x79, 0x00}, {0x0f, 0x01, 0x79, 0x00}, - {0x18, 0x01, 0x79, 0x00}, {0x1f, 0x01, 0x79, 0x00}, - {0x29, 0x01, 0x79, 0x00}, {0x38, 0x01, 0x79, 0x01}, - {0x03, 0x01, 0x7a, 0x00}, {0x06, 0x01, 0x7a, 0x00}, - {0x0a, 0x01, 0x7a, 0x00}, {0x0f, 0x01, 0x7a, 0x00}, - {0x18, 0x01, 0x7a, 0x00}, {0x1f, 0x01, 0x7a, 0x00}, - {0x29, 0x01, 0x7a, 0x00}, {0x38, 0x01, 0x7a, 0x01} - ], - [ - {0x01, 0x01, 0x26, 0x00}, {0x16, 0x01, 0x26, 0x01}, - {0x01, 0x01, 0x2a, 0x00}, {0x16, 0x01, 0x2a, 0x01}, - {0x01, 0x01, 0x2c, 0x00}, {0x16, 0x01, 0x2c, 0x01}, - {0x01, 0x01, 0x3b, 0x00}, {0x16, 0x01, 0x3b, 0x01}, - {0x01, 0x01, 0x58, 0x00}, {0x16, 0x01, 0x58, 0x01}, - {0x01, 0x01, 0x5a, 0x00}, {0x16, 0x01, 0x5a, 0x01}, - {0x4c, 0x00, 0x00, 0x00}, {0x4d, 0x00, 0x00, 0x00}, - {0x4f, 0x00, 0x00, 0x00}, {0x51, 0x00, 0x00, 0x01} - ], - [ - {0x02, 0x01, 0x26, 0x00}, {0x09, 0x01, 0x26, 0x00}, - {0x17, 0x01, 0x26, 0x00}, {0x28, 0x01, 0x26, 0x01}, - {0x02, 0x01, 0x2a, 0x00}, {0x09, 0x01, 0x2a, 0x00}, - {0x17, 0x01, 0x2a, 0x00}, {0x28, 0x01, 0x2a, 0x01}, - {0x02, 0x01, 0x2c, 0x00}, {0x09, 0x01, 0x2c, 0x00}, - {0x17, 0x01, 0x2c, 0x00}, {0x28, 0x01, 0x2c, 0x01}, - {0x02, 0x01, 0x3b, 0x00}, {0x09, 0x01, 0x3b, 0x00}, - {0x17, 0x01, 0x3b, 0x00}, {0x28, 0x01, 0x3b, 0x01} - ], - /* 70 */ - [ - {0x03, 0x01, 0x26, 0x00}, {0x06, 0x01, 0x26, 0x00}, - {0x0a, 0x01, 0x26, 0x00}, {0x0f, 0x01, 0x26, 0x00}, - {0x18, 0x01, 0x26, 0x00}, {0x1f, 0x01, 0x26, 0x00}, - {0x29, 0x01, 0x26, 0x00}, {0x38, 0x01, 0x26, 0x01}, - {0x03, 0x01, 0x2a, 0x00}, {0x06, 0x01, 0x2a, 0x00}, - {0x0a, 0x01, 0x2a, 0x00}, {0x0f, 0x01, 0x2a, 0x00}, - {0x18, 0x01, 0x2a, 0x00}, {0x1f, 0x01, 0x2a, 0x00}, - {0x29, 0x01, 0x2a, 0x00}, {0x38, 0x01, 0x2a, 0x01} - ], - [ - {0x03, 0x01, 0x2c, 0x00}, {0x06, 0x01, 0x2c, 0x00}, - {0x0a, 0x01, 0x2c, 0x00}, {0x0f, 0x01, 0x2c, 0x00}, - {0x18, 0x01, 0x2c, 0x00}, {0x1f, 0x01, 0x2c, 0x00}, - {0x29, 0x01, 0x2c, 0x00}, {0x38, 0x01, 0x2c, 0x01}, - {0x03, 0x01, 0x3b, 0x00}, {0x06, 0x01, 0x3b, 0x00}, - {0x0a, 0x01, 0x3b, 0x00}, {0x0f, 0x01, 0x3b, 0x00}, - {0x18, 0x01, 0x3b, 0x00}, {0x1f, 0x01, 0x3b, 0x00}, - {0x29, 0x01, 0x3b, 0x00}, {0x38, 0x01, 0x3b, 0x01} - ], - [ - {0x02, 0x01, 0x58, 0x00}, {0x09, 0x01, 0x58, 0x00}, - {0x17, 0x01, 0x58, 0x00}, {0x28, 0x01, 0x58, 0x01}, - {0x02, 0x01, 0x5a, 0x00}, {0x09, 0x01, 0x5a, 0x00}, - {0x17, 0x01, 0x5a, 0x00}, {0x28, 0x01, 0x5a, 0x01}, - {0x00, 0x01, 0x21, 0x01}, {0x00, 0x01, 0x22, 0x01}, - {0x00, 0x01, 0x28, 0x01}, {0x00, 0x01, 0x29, 0x01}, - {0x00, 0x01, 0x3f, 0x01}, {0x50, 0x00, 0x00, 0x00}, - {0x52, 0x00, 0x00, 0x00}, {0x54, 0x00, 0x00, 0x01} - ], - [ - {0x03, 0x01, 0x58, 0x00}, {0x06, 0x01, 0x58, 0x00}, - {0x0a, 0x01, 0x58, 0x00}, {0x0f, 0x01, 0x58, 0x00}, - {0x18, 0x01, 0x58, 0x00}, {0x1f, 0x01, 0x58, 0x00}, - {0x29, 0x01, 0x58, 0x00}, {0x38, 0x01, 0x58, 0x01}, - {0x03, 0x01, 0x5a, 0x00}, {0x06, 0x01, 0x5a, 0x00}, - {0x0a, 0x01, 0x5a, 0x00}, {0x0f, 0x01, 0x5a, 0x00}, - {0x18, 0x01, 0x5a, 0x00}, {0x1f, 0x01, 0x5a, 0x00}, - {0x29, 0x01, 0x5a, 0x00}, {0x38, 0x01, 0x5a, 0x01} - ], - [ - {0x01, 0x01, 0x21, 0x00}, {0x16, 0x01, 0x21, 0x01}, - {0x01, 0x01, 0x22, 0x00}, {0x16, 0x01, 0x22, 0x01}, - {0x01, 0x01, 0x28, 0x00}, {0x16, 0x01, 0x28, 0x01}, - {0x01, 0x01, 0x29, 0x00}, {0x16, 0x01, 0x29, 0x01}, - {0x01, 0x01, 0x3f, 0x00}, {0x16, 0x01, 0x3f, 0x01}, - {0x00, 0x01, 0x27, 0x01}, {0x00, 0x01, 0x2b, 0x01}, - {0x00, 0x01, 0x7c, 0x01}, {0x53, 0x00, 0x00, 0x00}, - {0x55, 0x00, 0x00, 0x00}, {0x58, 0x00, 0x00, 0x01} - ], - /* 75 */ - [ - {0x02, 0x01, 0x21, 0x00}, {0x09, 0x01, 0x21, 0x00}, - {0x17, 0x01, 0x21, 0x00}, {0x28, 0x01, 0x21, 0x01}, - {0x02, 0x01, 0x22, 0x00}, {0x09, 0x01, 0x22, 0x00}, - {0x17, 0x01, 0x22, 0x00}, {0x28, 0x01, 0x22, 0x01}, - {0x02, 0x01, 0x28, 0x00}, {0x09, 0x01, 0x28, 0x00}, - {0x17, 0x01, 0x28, 0x00}, {0x28, 0x01, 0x28, 0x01}, - {0x02, 0x01, 0x29, 0x00}, {0x09, 0x01, 0x29, 0x00}, - {0x17, 0x01, 0x29, 0x00}, {0x28, 0x01, 0x29, 0x01} - ], - [ - {0x03, 0x01, 0x21, 0x00}, {0x06, 0x01, 0x21, 0x00}, - {0x0a, 0x01, 0x21, 0x00}, {0x0f, 0x01, 0x21, 0x00}, - {0x18, 0x01, 0x21, 0x00}, {0x1f, 0x01, 0x21, 0x00}, - {0x29, 0x01, 0x21, 0x00}, {0x38, 0x01, 0x21, 0x01}, - {0x03, 0x01, 0x22, 0x00}, {0x06, 0x01, 0x22, 0x00}, - {0x0a, 0x01, 0x22, 0x00}, {0x0f, 0x01, 0x22, 0x00}, - {0x18, 0x01, 0x22, 0x00}, {0x1f, 0x01, 0x22, 0x00}, - {0x29, 0x01, 0x22, 0x00}, {0x38, 0x01, 0x22, 0x01} - ], - [ - {0x03, 0x01, 0x28, 0x00}, {0x06, 0x01, 0x28, 0x00}, - {0x0a, 0x01, 0x28, 0x00}, {0x0f, 0x01, 0x28, 0x00}, - {0x18, 0x01, 0x28, 0x00}, {0x1f, 0x01, 0x28, 0x00}, - {0x29, 0x01, 0x28, 0x00}, {0x38, 0x01, 0x28, 0x01}, - {0x03, 0x01, 0x29, 0x00}, {0x06, 0x01, 0x29, 0x00}, - {0x0a, 0x01, 0x29, 0x00}, {0x0f, 0x01, 0x29, 0x00}, - {0x18, 0x01, 0x29, 0x00}, {0x1f, 0x01, 0x29, 0x00}, - {0x29, 0x01, 0x29, 0x00}, {0x38, 0x01, 0x29, 0x01} - ], - [ - {0x02, 0x01, 0x3f, 0x00}, {0x09, 0x01, 0x3f, 0x00}, - {0x17, 0x01, 0x3f, 0x00}, {0x28, 0x01, 0x3f, 0x01}, - {0x01, 0x01, 0x27, 0x00}, {0x16, 0x01, 0x27, 0x01}, - {0x01, 0x01, 0x2b, 0x00}, {0x16, 0x01, 0x2b, 0x01}, - {0x01, 0x01, 0x7c, 0x00}, {0x16, 0x01, 0x7c, 0x01}, - {0x00, 0x01, 0x23, 0x01}, {0x00, 0x01, 0x3e, 0x01}, - {0x56, 0x00, 0x00, 0x00}, {0x57, 0x00, 0x00, 0x00}, - {0x59, 0x00, 0x00, 0x00}, {0x5a, 0x00, 0x00, 0x01} - ], - [ - {0x03, 0x01, 0x3f, 0x00}, {0x06, 0x01, 0x3f, 0x00}, - {0x0a, 0x01, 0x3f, 0x00}, {0x0f, 0x01, 0x3f, 0x00}, - {0x18, 0x01, 0x3f, 0x00}, {0x1f, 0x01, 0x3f, 0x00}, - {0x29, 0x01, 0x3f, 0x00}, {0x38, 0x01, 0x3f, 0x01}, - {0x02, 0x01, 0x27, 0x00}, {0x09, 0x01, 0x27, 0x00}, - {0x17, 0x01, 0x27, 0x00}, {0x28, 0x01, 0x27, 0x01}, - {0x02, 0x01, 0x2b, 0x00}, {0x09, 0x01, 0x2b, 0x00}, - {0x17, 0x01, 0x2b, 0x00}, {0x28, 0x01, 0x2b, 0x01} - ], - /* 80 */ - [ - {0x03, 0x01, 0x27, 0x00}, {0x06, 0x01, 0x27, 0x00}, - {0x0a, 0x01, 0x27, 0x00}, {0x0f, 0x01, 0x27, 0x00}, - {0x18, 0x01, 0x27, 0x00}, {0x1f, 0x01, 0x27, 0x00}, - {0x29, 0x01, 0x27, 0x00}, {0x38, 0x01, 0x27, 0x01}, - {0x03, 0x01, 0x2b, 0x00}, {0x06, 0x01, 0x2b, 0x00}, - {0x0a, 0x01, 0x2b, 0x00}, {0x0f, 0x01, 0x2b, 0x00}, - {0x18, 0x01, 0x2b, 0x00}, {0x1f, 0x01, 0x2b, 0x00}, - {0x29, 0x01, 0x2b, 0x00}, {0x38, 0x01, 0x2b, 0x01} - ], - [ - {0x02, 0x01, 0x7c, 0x00}, {0x09, 0x01, 0x7c, 0x00}, - {0x17, 0x01, 0x7c, 0x00}, {0x28, 0x01, 0x7c, 0x01}, - {0x01, 0x01, 0x23, 0x00}, {0x16, 0x01, 0x23, 0x01}, - {0x01, 0x01, 0x3e, 0x00}, {0x16, 0x01, 0x3e, 0x01}, - {0x00, 0x01, 0x00, 0x01}, {0x00, 0x01, 0x24, 0x01}, - {0x00, 0x01, 0x40, 0x01}, {0x00, 0x01, 0x5b, 0x01}, - {0x00, 0x01, 0x5d, 0x01}, {0x00, 0x01, 0x7e, 0x01}, - {0x5b, 0x00, 0x00, 0x00}, {0x5c, 0x00, 0x00, 0x01} - ], - [ - {0x03, 0x01, 0x7c, 0x00}, {0x06, 0x01, 0x7c, 0x00}, - {0x0a, 0x01, 0x7c, 0x00}, {0x0f, 0x01, 0x7c, 0x00}, - {0x18, 0x01, 0x7c, 0x00}, {0x1f, 0x01, 0x7c, 0x00}, - {0x29, 0x01, 0x7c, 0x00}, {0x38, 0x01, 0x7c, 0x01}, - {0x02, 0x01, 0x23, 0x00}, {0x09, 0x01, 0x23, 0x00}, - {0x17, 0x01, 0x23, 0x00}, {0x28, 0x01, 0x23, 0x01}, - {0x02, 0x01, 0x3e, 0x00}, {0x09, 0x01, 0x3e, 0x00}, - {0x17, 0x01, 0x3e, 0x00}, {0x28, 0x01, 0x3e, 0x01} - ], - [ - {0x03, 0x01, 0x23, 0x00}, {0x06, 0x01, 0x23, 0x00}, - {0x0a, 0x01, 0x23, 0x00}, {0x0f, 0x01, 0x23, 0x00}, - {0x18, 0x01, 0x23, 0x00}, {0x1f, 0x01, 0x23, 0x00}, - {0x29, 0x01, 0x23, 0x00}, {0x38, 0x01, 0x23, 0x01}, - {0x03, 0x01, 0x3e, 0x00}, {0x06, 0x01, 0x3e, 0x00}, - {0x0a, 0x01, 0x3e, 0x00}, {0x0f, 0x01, 0x3e, 0x00}, - {0x18, 0x01, 0x3e, 0x00}, {0x1f, 0x01, 0x3e, 0x00}, - {0x29, 0x01, 0x3e, 0x00}, {0x38, 0x01, 0x3e, 0x01} - ], - [ - {0x01, 0x01, 0x00, 0x00}, {0x16, 0x01, 0x00, 0x01}, - {0x01, 0x01, 0x24, 0x00}, {0x16, 0x01, 0x24, 0x01}, - {0x01, 0x01, 0x40, 0x00}, {0x16, 0x01, 0x40, 0x01}, - {0x01, 0x01, 0x5b, 0x00}, {0x16, 0x01, 0x5b, 0x01}, - {0x01, 0x01, 0x5d, 0x00}, {0x16, 0x01, 0x5d, 0x01}, - {0x01, 0x01, 0x7e, 0x00}, {0x16, 0x01, 0x7e, 0x01}, - {0x00, 0x01, 0x5e, 0x01}, {0x00, 0x01, 0x7d, 0x01}, - {0x5d, 0x00, 0x00, 0x00}, {0x5e, 0x00, 0x00, 0x01} - ], - /* 85 */ - [ - {0x02, 0x01, 0x00, 0x00}, {0x09, 0x01, 0x00, 0x00}, - {0x17, 0x01, 0x00, 0x00}, {0x28, 0x01, 0x00, 0x01}, - {0x02, 0x01, 0x24, 0x00}, {0x09, 0x01, 0x24, 0x00}, - {0x17, 0x01, 0x24, 0x00}, {0x28, 0x01, 0x24, 0x01}, - {0x02, 0x01, 0x40, 0x00}, {0x09, 0x01, 0x40, 0x00}, - {0x17, 0x01, 0x40, 0x00}, {0x28, 0x01, 0x40, 0x01}, - {0x02, 0x01, 0x5b, 0x00}, {0x09, 0x01, 0x5b, 0x00}, - {0x17, 0x01, 0x5b, 0x00}, {0x28, 0x01, 0x5b, 0x01} - ], - [ - {0x03, 0x01, 0x00, 0x00}, {0x06, 0x01, 0x00, 0x00}, - {0x0a, 0x01, 0x00, 0x00}, {0x0f, 0x01, 0x00, 0x00}, - {0x18, 0x01, 0x00, 0x00}, {0x1f, 0x01, 0x00, 0x00}, - {0x29, 0x01, 0x00, 0x00}, {0x38, 0x01, 0x00, 0x01}, - {0x03, 0x01, 0x24, 0x00}, {0x06, 0x01, 0x24, 0x00}, - {0x0a, 0x01, 0x24, 0x00}, {0x0f, 0x01, 0x24, 0x00}, - {0x18, 0x01, 0x24, 0x00}, {0x1f, 0x01, 0x24, 0x00}, - {0x29, 0x01, 0x24, 0x00}, {0x38, 0x01, 0x24, 0x01} - ], - [ - {0x03, 0x01, 0x40, 0x00}, {0x06, 0x01, 0x40, 0x00}, - {0x0a, 0x01, 0x40, 0x00}, {0x0f, 0x01, 0x40, 0x00}, - {0x18, 0x01, 0x40, 0x00}, {0x1f, 0x01, 0x40, 0x00}, - {0x29, 0x01, 0x40, 0x00}, {0x38, 0x01, 0x40, 0x01}, - {0x03, 0x01, 0x5b, 0x00}, {0x06, 0x01, 0x5b, 0x00}, - {0x0a, 0x01, 0x5b, 0x00}, {0x0f, 0x01, 0x5b, 0x00}, - {0x18, 0x01, 0x5b, 0x00}, {0x1f, 0x01, 0x5b, 0x00}, - {0x29, 0x01, 0x5b, 0x00}, {0x38, 0x01, 0x5b, 0x01} - ], - [ - {0x02, 0x01, 0x5d, 0x00}, {0x09, 0x01, 0x5d, 0x00}, - {0x17, 0x01, 0x5d, 0x00}, {0x28, 0x01, 0x5d, 0x01}, - {0x02, 0x01, 0x7e, 0x00}, {0x09, 0x01, 0x7e, 0x00}, - {0x17, 0x01, 0x7e, 0x00}, {0x28, 0x01, 0x7e, 0x01}, - {0x01, 0x01, 0x5e, 0x00}, {0x16, 0x01, 0x5e, 0x01}, - {0x01, 0x01, 0x7d, 0x00}, {0x16, 0x01, 0x7d, 0x01}, - {0x00, 0x01, 0x3c, 0x01}, {0x00, 0x01, 0x60, 0x01}, - {0x00, 0x01, 0x7b, 0x01}, {0x5f, 0x00, 0x00, 0x01} - ], - [ - {0x03, 0x01, 0x5d, 0x00}, {0x06, 0x01, 0x5d, 0x00}, - {0x0a, 0x01, 0x5d, 0x00}, {0x0f, 0x01, 0x5d, 0x00}, - {0x18, 0x01, 0x5d, 0x00}, {0x1f, 0x01, 0x5d, 0x00}, - {0x29, 0x01, 0x5d, 0x00}, {0x38, 0x01, 0x5d, 0x01}, - {0x03, 0x01, 0x7e, 0x00}, {0x06, 0x01, 0x7e, 0x00}, - {0x0a, 0x01, 0x7e, 0x00}, {0x0f, 0x01, 0x7e, 0x00}, - {0x18, 0x01, 0x7e, 0x00}, {0x1f, 0x01, 0x7e, 0x00}, - {0x29, 0x01, 0x7e, 0x00}, {0x38, 0x01, 0x7e, 0x01} - ], - /* 90 */ - [ - {0x02, 0x01, 0x5e, 0x00}, {0x09, 0x01, 0x5e, 0x00}, - {0x17, 0x01, 0x5e, 0x00}, {0x28, 0x01, 0x5e, 0x01}, - {0x02, 0x01, 0x7d, 0x00}, {0x09, 0x01, 0x7d, 0x00}, - {0x17, 0x01, 0x7d, 0x00}, {0x28, 0x01, 0x7d, 0x01}, - {0x01, 0x01, 0x3c, 0x00}, {0x16, 0x01, 0x3c, 0x01}, - {0x01, 0x01, 0x60, 0x00}, {0x16, 0x01, 0x60, 0x01}, - {0x01, 0x01, 0x7b, 0x00}, {0x16, 0x01, 0x7b, 0x01}, - {0x60, 0x00, 0x00, 0x00}, {0x6e, 0x00, 0x00, 0x01} - ], - [ - {0x03, 0x01, 0x5e, 0x00}, {0x06, 0x01, 0x5e, 0x00}, - {0x0a, 0x01, 0x5e, 0x00}, {0x0f, 0x01, 0x5e, 0x00}, - {0x18, 0x01, 0x5e, 0x00}, {0x1f, 0x01, 0x5e, 0x00}, - {0x29, 0x01, 0x5e, 0x00}, {0x38, 0x01, 0x5e, 0x01}, - {0x03, 0x01, 0x7d, 0x00}, {0x06, 0x01, 0x7d, 0x00}, - {0x0a, 0x01, 0x7d, 0x00}, {0x0f, 0x01, 0x7d, 0x00}, - {0x18, 0x01, 0x7d, 0x00}, {0x1f, 0x01, 0x7d, 0x00}, - {0x29, 0x01, 0x7d, 0x00}, {0x38, 0x01, 0x7d, 0x01} - ], - [ - {0x02, 0x01, 0x3c, 0x00}, {0x09, 0x01, 0x3c, 0x00}, - {0x17, 0x01, 0x3c, 0x00}, {0x28, 0x01, 0x3c, 0x01}, - {0x02, 0x01, 0x60, 0x00}, {0x09, 0x01, 0x60, 0x00}, - {0x17, 0x01, 0x60, 0x00}, {0x28, 0x01, 0x60, 0x01}, - {0x02, 0x01, 0x7b, 0x00}, {0x09, 0x01, 0x7b, 0x00}, - {0x17, 0x01, 0x7b, 0x00}, {0x28, 0x01, 0x7b, 0x01}, - {0x61, 0x00, 0x00, 0x00}, {0x65, 0x00, 0x00, 0x00}, - {0x6f, 0x00, 0x00, 0x00}, {0x85, 0x00, 0x00, 0x01} - ], - [ - {0x03, 0x01, 0x3c, 0x00}, {0x06, 0x01, 0x3c, 0x00}, - {0x0a, 0x01, 0x3c, 0x00}, {0x0f, 0x01, 0x3c, 0x00}, - {0x18, 0x01, 0x3c, 0x00}, {0x1f, 0x01, 0x3c, 0x00}, - {0x29, 0x01, 0x3c, 0x00}, {0x38, 0x01, 0x3c, 0x01}, - {0x03, 0x01, 0x60, 0x00}, {0x06, 0x01, 0x60, 0x00}, - {0x0a, 0x01, 0x60, 0x00}, {0x0f, 0x01, 0x60, 0x00}, - {0x18, 0x01, 0x60, 0x00}, {0x1f, 0x01, 0x60, 0x00}, - {0x29, 0x01, 0x60, 0x00}, {0x38, 0x01, 0x60, 0x01} - ], - [ - {0x03, 0x01, 0x7b, 0x00}, {0x06, 0x01, 0x7b, 0x00}, - {0x0a, 0x01, 0x7b, 0x00}, {0x0f, 0x01, 0x7b, 0x00}, - {0x18, 0x01, 0x7b, 0x00}, {0x1f, 0x01, 0x7b, 0x00}, - {0x29, 0x01, 0x7b, 0x00}, {0x38, 0x01, 0x7b, 0x01}, - {0x62, 0x00, 0x00, 0x00}, {0x63, 0x00, 0x00, 0x00}, - {0x66, 0x00, 0x00, 0x00}, {0x69, 0x00, 0x00, 0x00}, - {0x70, 0x00, 0x00, 0x00}, {0x77, 0x00, 0x00, 0x00}, - {0x86, 0x00, 0x00, 0x00}, {0x99, 0x00, 0x00, 0x01} - ], - /* 95 */ - [ - {0x00, 0x01, 0x5c, 0x01}, {0x00, 0x01, 0xc3, 0x01}, - {0x00, 0x01, 0xd0, 0x01}, {0x64, 0x00, 0x00, 0x00}, - {0x67, 0x00, 0x00, 0x00}, {0x68, 0x00, 0x00, 0x00}, - {0x6a, 0x00, 0x00, 0x00}, {0x6b, 0x00, 0x00, 0x00}, - {0x71, 0x00, 0x00, 0x00}, {0x74, 0x00, 0x00, 0x00}, - {0x78, 0x00, 0x00, 0x00}, {0x7e, 0x00, 0x00, 0x00}, - {0x87, 0x00, 0x00, 0x00}, {0x8e, 0x00, 0x00, 0x00}, - {0x9a, 0x00, 0x00, 0x00}, {0xa9, 0x00, 0x00, 0x01} - ], - [ - {0x01, 0x01, 0x5c, 0x00}, {0x16, 0x01, 0x5c, 0x01}, - {0x01, 0x01, 0xc3, 0x00}, {0x16, 0x01, 0xc3, 0x01}, - {0x01, 0x01, 0xd0, 0x00}, {0x16, 0x01, 0xd0, 0x01}, - {0x00, 0x01, 0x80, 0x01}, {0x00, 0x01, 0x82, 0x01}, - {0x00, 0x01, 0x83, 0x01}, {0x00, 0x01, 0xa2, 0x01}, - {0x00, 0x01, 0xb8, 0x01}, {0x00, 0x01, 0xc2, 0x01}, - {0x00, 0x01, 0xe0, 0x01}, {0x00, 0x01, 0xe2, 0x01}, - {0x6c, 0x00, 0x00, 0x00}, {0x6d, 0x00, 0x00, 0x00} - ], - [ - {0x02, 0x01, 0x5c, 0x00}, {0x09, 0x01, 0x5c, 0x00}, - {0x17, 0x01, 0x5c, 0x00}, {0x28, 0x01, 0x5c, 0x01}, - {0x02, 0x01, 0xc3, 0x00}, {0x09, 0x01, 0xc3, 0x00}, - {0x17, 0x01, 0xc3, 0x00}, {0x28, 0x01, 0xc3, 0x01}, - {0x02, 0x01, 0xd0, 0x00}, {0x09, 0x01, 0xd0, 0x00}, - {0x17, 0x01, 0xd0, 0x00}, {0x28, 0x01, 0xd0, 0x01}, - {0x01, 0x01, 0x80, 0x00}, {0x16, 0x01, 0x80, 0x01}, - {0x01, 0x01, 0x82, 0x00}, {0x16, 0x01, 0x82, 0x01} - ], - [ - {0x03, 0x01, 0x5c, 0x00}, {0x06, 0x01, 0x5c, 0x00}, - {0x0a, 0x01, 0x5c, 0x00}, {0x0f, 0x01, 0x5c, 0x00}, - {0x18, 0x01, 0x5c, 0x00}, {0x1f, 0x01, 0x5c, 0x00}, - {0x29, 0x01, 0x5c, 0x00}, {0x38, 0x01, 0x5c, 0x01}, - {0x03, 0x01, 0xc3, 0x00}, {0x06, 0x01, 0xc3, 0x00}, - {0x0a, 0x01, 0xc3, 0x00}, {0x0f, 0x01, 0xc3, 0x00}, - {0x18, 0x01, 0xc3, 0x00}, {0x1f, 0x01, 0xc3, 0x00}, - {0x29, 0x01, 0xc3, 0x00}, {0x38, 0x01, 0xc3, 0x01} - ], - [ - {0x03, 0x01, 0xd0, 0x00}, {0x06, 0x01, 0xd0, 0x00}, - {0x0a, 0x01, 0xd0, 0x00}, {0x0f, 0x01, 0xd0, 0x00}, - {0x18, 0x01, 0xd0, 0x00}, {0x1f, 0x01, 0xd0, 0x00}, - {0x29, 0x01, 0xd0, 0x00}, {0x38, 0x01, 0xd0, 0x01}, - {0x02, 0x01, 0x80, 0x00}, {0x09, 0x01, 0x80, 0x00}, - {0x17, 0x01, 0x80, 0x00}, {0x28, 0x01, 0x80, 0x01}, - {0x02, 0x01, 0x82, 0x00}, {0x09, 0x01, 0x82, 0x00}, - {0x17, 0x01, 0x82, 0x00}, {0x28, 0x01, 0x82, 0x01} - ], - /* 100 */ - [ - {0x03, 0x01, 0x80, 0x00}, {0x06, 0x01, 0x80, 0x00}, - {0x0a, 0x01, 0x80, 0x00}, {0x0f, 0x01, 0x80, 0x00}, - {0x18, 0x01, 0x80, 0x00}, {0x1f, 0x01, 0x80, 0x00}, - {0x29, 0x01, 0x80, 0x00}, {0x38, 0x01, 0x80, 0x01}, - {0x03, 0x01, 0x82, 0x00}, {0x06, 0x01, 0x82, 0x00}, - {0x0a, 0x01, 0x82, 0x00}, {0x0f, 0x01, 0x82, 0x00}, - {0x18, 0x01, 0x82, 0x00}, {0x1f, 0x01, 0x82, 0x00}, - {0x29, 0x01, 0x82, 0x00}, {0x38, 0x01, 0x82, 0x01} - ], - [ - {0x01, 0x01, 0x83, 0x00}, {0x16, 0x01, 0x83, 0x01}, - {0x01, 0x01, 0xa2, 0x00}, {0x16, 0x01, 0xa2, 0x01}, - {0x01, 0x01, 0xb8, 0x00}, {0x16, 0x01, 0xb8, 0x01}, - {0x01, 0x01, 0xc2, 0x00}, {0x16, 0x01, 0xc2, 0x01}, - {0x01, 0x01, 0xe0, 0x00}, {0x16, 0x01, 0xe0, 0x01}, - {0x01, 0x01, 0xe2, 0x00}, {0x16, 0x01, 0xe2, 0x01}, - {0x00, 0x01, 0x99, 0x01}, {0x00, 0x01, 0xa1, 0x01}, - {0x00, 0x01, 0xa7, 0x01}, {0x00, 0x01, 0xac, 0x01} - ], - [ - {0x02, 0x01, 0x83, 0x00}, {0x09, 0x01, 0x83, 0x00}, - {0x17, 0x01, 0x83, 0x00}, {0x28, 0x01, 0x83, 0x01}, - {0x02, 0x01, 0xa2, 0x00}, {0x09, 0x01, 0xa2, 0x00}, - {0x17, 0x01, 0xa2, 0x00}, {0x28, 0x01, 0xa2, 0x01}, - {0x02, 0x01, 0xb8, 0x00}, {0x09, 0x01, 0xb8, 0x00}, - {0x17, 0x01, 0xb8, 0x00}, {0x28, 0x01, 0xb8, 0x01}, - {0x02, 0x01, 0xc2, 0x00}, {0x09, 0x01, 0xc2, 0x00}, - {0x17, 0x01, 0xc2, 0x00}, {0x28, 0x01, 0xc2, 0x01} - ], - [ - {0x03, 0x01, 0x83, 0x00}, {0x06, 0x01, 0x83, 0x00}, - {0x0a, 0x01, 0x83, 0x00}, {0x0f, 0x01, 0x83, 0x00}, - {0x18, 0x01, 0x83, 0x00}, {0x1f, 0x01, 0x83, 0x00}, - {0x29, 0x01, 0x83, 0x00}, {0x38, 0x01, 0x83, 0x01}, - {0x03, 0x01, 0xa2, 0x00}, {0x06, 0x01, 0xa2, 0x00}, - {0x0a, 0x01, 0xa2, 0x00}, {0x0f, 0x01, 0xa2, 0x00}, - {0x18, 0x01, 0xa2, 0x00}, {0x1f, 0x01, 0xa2, 0x00}, - {0x29, 0x01, 0xa2, 0x00}, {0x38, 0x01, 0xa2, 0x01} - ], - [ - {0x03, 0x01, 0xb8, 0x00}, {0x06, 0x01, 0xb8, 0x00}, - {0x0a, 0x01, 0xb8, 0x00}, {0x0f, 0x01, 0xb8, 0x00}, - {0x18, 0x01, 0xb8, 0x00}, {0x1f, 0x01, 0xb8, 0x00}, - {0x29, 0x01, 0xb8, 0x00}, {0x38, 0x01, 0xb8, 0x01}, - {0x03, 0x01, 0xc2, 0x00}, {0x06, 0x01, 0xc2, 0x00}, - {0x0a, 0x01, 0xc2, 0x00}, {0x0f, 0x01, 0xc2, 0x00}, - {0x18, 0x01, 0xc2, 0x00}, {0x1f, 0x01, 0xc2, 0x00}, - {0x29, 0x01, 0xc2, 0x00}, {0x38, 0x01, 0xc2, 0x01} - ], - /* 105 */ - [ - {0x02, 0x01, 0xe0, 0x00}, {0x09, 0x01, 0xe0, 0x00}, - {0x17, 0x01, 0xe0, 0x00}, {0x28, 0x01, 0xe0, 0x01}, - {0x02, 0x01, 0xe2, 0x00}, {0x09, 0x01, 0xe2, 0x00}, - {0x17, 0x01, 0xe2, 0x00}, {0x28, 0x01, 0xe2, 0x01}, - {0x01, 0x01, 0x99, 0x00}, {0x16, 0x01, 0x99, 0x01}, - {0x01, 0x01, 0xa1, 0x00}, {0x16, 0x01, 0xa1, 0x01}, - {0x01, 0x01, 0xa7, 0x00}, {0x16, 0x01, 0xa7, 0x01}, - {0x01, 0x01, 0xac, 0x00}, {0x16, 0x01, 0xac, 0x01} - ], - [ - {0x03, 0x01, 0xe0, 0x00}, {0x06, 0x01, 0xe0, 0x00}, - {0x0a, 0x01, 0xe0, 0x00}, {0x0f, 0x01, 0xe0, 0x00}, - {0x18, 0x01, 0xe0, 0x00}, {0x1f, 0x01, 0xe0, 0x00}, - {0x29, 0x01, 0xe0, 0x00}, {0x38, 0x01, 0xe0, 0x01}, - {0x03, 0x01, 0xe2, 0x00}, {0x06, 0x01, 0xe2, 0x00}, - {0x0a, 0x01, 0xe2, 0x00}, {0x0f, 0x01, 0xe2, 0x00}, - {0x18, 0x01, 0xe2, 0x00}, {0x1f, 0x01, 0xe2, 0x00}, - {0x29, 0x01, 0xe2, 0x00}, {0x38, 0x01, 0xe2, 0x01} - ], - [ - {0x02, 0x01, 0x99, 0x00}, {0x09, 0x01, 0x99, 0x00}, - {0x17, 0x01, 0x99, 0x00}, {0x28, 0x01, 0x99, 0x01}, - {0x02, 0x01, 0xa1, 0x00}, {0x09, 0x01, 0xa1, 0x00}, - {0x17, 0x01, 0xa1, 0x00}, {0x28, 0x01, 0xa1, 0x01}, - {0x02, 0x01, 0xa7, 0x00}, {0x09, 0x01, 0xa7, 0x00}, - {0x17, 0x01, 0xa7, 0x00}, {0x28, 0x01, 0xa7, 0x01}, - {0x02, 0x01, 0xac, 0x00}, {0x09, 0x01, 0xac, 0x00}, - {0x17, 0x01, 0xac, 0x00}, {0x28, 0x01, 0xac, 0x01} - ], - [ - {0x03, 0x01, 0x99, 0x00}, {0x06, 0x01, 0x99, 0x00}, - {0x0a, 0x01, 0x99, 0x00}, {0x0f, 0x01, 0x99, 0x00}, - {0x18, 0x01, 0x99, 0x00}, {0x1f, 0x01, 0x99, 0x00}, - {0x29, 0x01, 0x99, 0x00}, {0x38, 0x01, 0x99, 0x01}, - {0x03, 0x01, 0xa1, 0x00}, {0x06, 0x01, 0xa1, 0x00}, - {0x0a, 0x01, 0xa1, 0x00}, {0x0f, 0x01, 0xa1, 0x00}, - {0x18, 0x01, 0xa1, 0x00}, {0x1f, 0x01, 0xa1, 0x00}, - {0x29, 0x01, 0xa1, 0x00}, {0x38, 0x01, 0xa1, 0x01} - ], - [ - {0x03, 0x01, 0xa7, 0x00}, {0x06, 0x01, 0xa7, 0x00}, - {0x0a, 0x01, 0xa7, 0x00}, {0x0f, 0x01, 0xa7, 0x00}, - {0x18, 0x01, 0xa7, 0x00}, {0x1f, 0x01, 0xa7, 0x00}, - {0x29, 0x01, 0xa7, 0x00}, {0x38, 0x01, 0xa7, 0x01}, - {0x03, 0x01, 0xac, 0x00}, {0x06, 0x01, 0xac, 0x00}, - {0x0a, 0x01, 0xac, 0x00}, {0x0f, 0x01, 0xac, 0x00}, - {0x18, 0x01, 0xac, 0x00}, {0x1f, 0x01, 0xac, 0x00}, - {0x29, 0x01, 0xac, 0x00}, {0x38, 0x01, 0xac, 0x01} - ], - /* 110 */ - [ - {0x72, 0x00, 0x00, 0x00}, {0x73, 0x00, 0x00, 0x00}, - {0x75, 0x00, 0x00, 0x00}, {0x76, 0x00, 0x00, 0x00}, - {0x79, 0x00, 0x00, 0x00}, {0x7b, 0x00, 0x00, 0x00}, - {0x7f, 0x00, 0x00, 0x00}, {0x82, 0x00, 0x00, 0x00}, - {0x88, 0x00, 0x00, 0x00}, {0x8b, 0x00, 0x00, 0x00}, - {0x8f, 0x00, 0x00, 0x00}, {0x92, 0x00, 0x00, 0x00}, - {0x9b, 0x00, 0x00, 0x00}, {0xa2, 0x00, 0x00, 0x00}, - {0xaa, 0x00, 0x00, 0x00}, {0xb4, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0xb0, 0x01}, {0x00, 0x01, 0xb1, 0x01}, - {0x00, 0x01, 0xb3, 0x01}, {0x00, 0x01, 0xd1, 0x01}, - {0x00, 0x01, 0xd8, 0x01}, {0x00, 0x01, 0xd9, 0x01}, - {0x00, 0x01, 0xe3, 0x01}, {0x00, 0x01, 0xe5, 0x01}, - {0x00, 0x01, 0xe6, 0x01}, {0x7a, 0x00, 0x00, 0x00}, - {0x7c, 0x00, 0x00, 0x00}, {0x7d, 0x00, 0x00, 0x00}, - {0x80, 0x00, 0x00, 0x00}, {0x81, 0x00, 0x00, 0x00}, - {0x83, 0x00, 0x00, 0x00}, {0x84, 0x00, 0x00, 0x00} - ], - [ - {0x01, 0x01, 0xb0, 0x00}, {0x16, 0x01, 0xb0, 0x01}, - {0x01, 0x01, 0xb1, 0x00}, {0x16, 0x01, 0xb1, 0x01}, - {0x01, 0x01, 0xb3, 0x00}, {0x16, 0x01, 0xb3, 0x01}, - {0x01, 0x01, 0xd1, 0x00}, {0x16, 0x01, 0xd1, 0x01}, - {0x01, 0x01, 0xd8, 0x00}, {0x16, 0x01, 0xd8, 0x01}, - {0x01, 0x01, 0xd9, 0x00}, {0x16, 0x01, 0xd9, 0x01}, - {0x01, 0x01, 0xe3, 0x00}, {0x16, 0x01, 0xe3, 0x01}, - {0x01, 0x01, 0xe5, 0x00}, {0x16, 0x01, 0xe5, 0x01} - ], - [ - {0x02, 0x01, 0xb0, 0x00}, {0x09, 0x01, 0xb0, 0x00}, - {0x17, 0x01, 0xb0, 0x00}, {0x28, 0x01, 0xb0, 0x01}, - {0x02, 0x01, 0xb1, 0x00}, {0x09, 0x01, 0xb1, 0x00}, - {0x17, 0x01, 0xb1, 0x00}, {0x28, 0x01, 0xb1, 0x01}, - {0x02, 0x01, 0xb3, 0x00}, {0x09, 0x01, 0xb3, 0x00}, - {0x17, 0x01, 0xb3, 0x00}, {0x28, 0x01, 0xb3, 0x01}, - {0x02, 0x01, 0xd1, 0x00}, {0x09, 0x01, 0xd1, 0x00}, - {0x17, 0x01, 0xd1, 0x00}, {0x28, 0x01, 0xd1, 0x01} - ], - [ - {0x03, 0x01, 0xb0, 0x00}, {0x06, 0x01, 0xb0, 0x00}, - {0x0a, 0x01, 0xb0, 0x00}, {0x0f, 0x01, 0xb0, 0x00}, - {0x18, 0x01, 0xb0, 0x00}, {0x1f, 0x01, 0xb0, 0x00}, - {0x29, 0x01, 0xb0, 0x00}, {0x38, 0x01, 0xb0, 0x01}, - {0x03, 0x01, 0xb1, 0x00}, {0x06, 0x01, 0xb1, 0x00}, - {0x0a, 0x01, 0xb1, 0x00}, {0x0f, 0x01, 0xb1, 0x00}, - {0x18, 0x01, 0xb1, 0x00}, {0x1f, 0x01, 0xb1, 0x00}, - {0x29, 0x01, 0xb1, 0x00}, {0x38, 0x01, 0xb1, 0x01} - ], - /* 115 */ - [ - {0x03, 0x01, 0xb3, 0x00}, {0x06, 0x01, 0xb3, 0x00}, - {0x0a, 0x01, 0xb3, 0x00}, {0x0f, 0x01, 0xb3, 0x00}, - {0x18, 0x01, 0xb3, 0x00}, {0x1f, 0x01, 0xb3, 0x00}, - {0x29, 0x01, 0xb3, 0x00}, {0x38, 0x01, 0xb3, 0x01}, - {0x03, 0x01, 0xd1, 0x00}, {0x06, 0x01, 0xd1, 0x00}, - {0x0a, 0x01, 0xd1, 0x00}, {0x0f, 0x01, 0xd1, 0x00}, - {0x18, 0x01, 0xd1, 0x00}, {0x1f, 0x01, 0xd1, 0x00}, - {0x29, 0x01, 0xd1, 0x00}, {0x38, 0x01, 0xd1, 0x01} - ], - [ - {0x02, 0x01, 0xd8, 0x00}, {0x09, 0x01, 0xd8, 0x00}, - {0x17, 0x01, 0xd8, 0x00}, {0x28, 0x01, 0xd8, 0x01}, - {0x02, 0x01, 0xd9, 0x00}, {0x09, 0x01, 0xd9, 0x00}, - {0x17, 0x01, 0xd9, 0x00}, {0x28, 0x01, 0xd9, 0x01}, - {0x02, 0x01, 0xe3, 0x00}, {0x09, 0x01, 0xe3, 0x00}, - {0x17, 0x01, 0xe3, 0x00}, {0x28, 0x01, 0xe3, 0x01}, - {0x02, 0x01, 0xe5, 0x00}, {0x09, 0x01, 0xe5, 0x00}, - {0x17, 0x01, 0xe5, 0x00}, {0x28, 0x01, 0xe5, 0x01} - ], - [ - {0x03, 0x01, 0xd8, 0x00}, {0x06, 0x01, 0xd8, 0x00}, - {0x0a, 0x01, 0xd8, 0x00}, {0x0f, 0x01, 0xd8, 0x00}, - {0x18, 0x01, 0xd8, 0x00}, {0x1f, 0x01, 0xd8, 0x00}, - {0x29, 0x01, 0xd8, 0x00}, {0x38, 0x01, 0xd8, 0x01}, - {0x03, 0x01, 0xd9, 0x00}, {0x06, 0x01, 0xd9, 0x00}, - {0x0a, 0x01, 0xd9, 0x00}, {0x0f, 0x01, 0xd9, 0x00}, - {0x18, 0x01, 0xd9, 0x00}, {0x1f, 0x01, 0xd9, 0x00}, - {0x29, 0x01, 0xd9, 0x00}, {0x38, 0x01, 0xd9, 0x01} - ], - [ - {0x03, 0x01, 0xe3, 0x00}, {0x06, 0x01, 0xe3, 0x00}, - {0x0a, 0x01, 0xe3, 0x00}, {0x0f, 0x01, 0xe3, 0x00}, - {0x18, 0x01, 0xe3, 0x00}, {0x1f, 0x01, 0xe3, 0x00}, - {0x29, 0x01, 0xe3, 0x00}, {0x38, 0x01, 0xe3, 0x01}, - {0x03, 0x01, 0xe5, 0x00}, {0x06, 0x01, 0xe5, 0x00}, - {0x0a, 0x01, 0xe5, 0x00}, {0x0f, 0x01, 0xe5, 0x00}, - {0x18, 0x01, 0xe5, 0x00}, {0x1f, 0x01, 0xe5, 0x00}, - {0x29, 0x01, 0xe5, 0x00}, {0x38, 0x01, 0xe5, 0x01} - ], - [ - {0x01, 0x01, 0xe6, 0x00}, {0x16, 0x01, 0xe6, 0x01}, - {0x00, 0x01, 0x81, 0x01}, {0x00, 0x01, 0x84, 0x01}, - {0x00, 0x01, 0x85, 0x01}, {0x00, 0x01, 0x86, 0x01}, - {0x00, 0x01, 0x88, 0x01}, {0x00, 0x01, 0x92, 0x01}, - {0x00, 0x01, 0x9a, 0x01}, {0x00, 0x01, 0x9c, 0x01}, - {0x00, 0x01, 0xa0, 0x01}, {0x00, 0x01, 0xa3, 0x01}, - {0x00, 0x01, 0xa4, 0x01}, {0x00, 0x01, 0xa9, 0x01}, - {0x00, 0x01, 0xaa, 0x01}, {0x00, 0x01, 0xad, 0x01} - ], - /* 120 */ - [ - {0x02, 0x01, 0xe6, 0x00}, {0x09, 0x01, 0xe6, 0x00}, - {0x17, 0x01, 0xe6, 0x00}, {0x28, 0x01, 0xe6, 0x01}, - {0x01, 0x01, 0x81, 0x00}, {0x16, 0x01, 0x81, 0x01}, - {0x01, 0x01, 0x84, 0x00}, {0x16, 0x01, 0x84, 0x01}, - {0x01, 0x01, 0x85, 0x00}, {0x16, 0x01, 0x85, 0x01}, - {0x01, 0x01, 0x86, 0x00}, {0x16, 0x01, 0x86, 0x01}, - {0x01, 0x01, 0x88, 0x00}, {0x16, 0x01, 0x88, 0x01}, - {0x01, 0x01, 0x92, 0x00}, {0x16, 0x01, 0x92, 0x01} - ], - [ - {0x03, 0x01, 0xe6, 0x00}, {0x06, 0x01, 0xe6, 0x00}, - {0x0a, 0x01, 0xe6, 0x00}, {0x0f, 0x01, 0xe6, 0x00}, - {0x18, 0x01, 0xe6, 0x00}, {0x1f, 0x01, 0xe6, 0x00}, - {0x29, 0x01, 0xe6, 0x00}, {0x38, 0x01, 0xe6, 0x01}, - {0x02, 0x01, 0x81, 0x00}, {0x09, 0x01, 0x81, 0x00}, - {0x17, 0x01, 0x81, 0x00}, {0x28, 0x01, 0x81, 0x01}, - {0x02, 0x01, 0x84, 0x00}, {0x09, 0x01, 0x84, 0x00}, - {0x17, 0x01, 0x84, 0x00}, {0x28, 0x01, 0x84, 0x01} - ], - [ - {0x03, 0x01, 0x81, 0x00}, {0x06, 0x01, 0x81, 0x00}, - {0x0a, 0x01, 0x81, 0x00}, {0x0f, 0x01, 0x81, 0x00}, - {0x18, 0x01, 0x81, 0x00}, {0x1f, 0x01, 0x81, 0x00}, - {0x29, 0x01, 0x81, 0x00}, {0x38, 0x01, 0x81, 0x01}, - {0x03, 0x01, 0x84, 0x00}, {0x06, 0x01, 0x84, 0x00}, - {0x0a, 0x01, 0x84, 0x00}, {0x0f, 0x01, 0x84, 0x00}, - {0x18, 0x01, 0x84, 0x00}, {0x1f, 0x01, 0x84, 0x00}, - {0x29, 0x01, 0x84, 0x00}, {0x38, 0x01, 0x84, 0x01} - ], - [ - {0x02, 0x01, 0x85, 0x00}, {0x09, 0x01, 0x85, 0x00}, - {0x17, 0x01, 0x85, 0x00}, {0x28, 0x01, 0x85, 0x01}, - {0x02, 0x01, 0x86, 0x00}, {0x09, 0x01, 0x86, 0x00}, - {0x17, 0x01, 0x86, 0x00}, {0x28, 0x01, 0x86, 0x01}, - {0x02, 0x01, 0x88, 0x00}, {0x09, 0x01, 0x88, 0x00}, - {0x17, 0x01, 0x88, 0x00}, {0x28, 0x01, 0x88, 0x01}, - {0x02, 0x01, 0x92, 0x00}, {0x09, 0x01, 0x92, 0x00}, - {0x17, 0x01, 0x92, 0x00}, {0x28, 0x01, 0x92, 0x01} - ], - [ - {0x03, 0x01, 0x85, 0x00}, {0x06, 0x01, 0x85, 0x00}, - {0x0a, 0x01, 0x85, 0x00}, {0x0f, 0x01, 0x85, 0x00}, - {0x18, 0x01, 0x85, 0x00}, {0x1f, 0x01, 0x85, 0x00}, - {0x29, 0x01, 0x85, 0x00}, {0x38, 0x01, 0x85, 0x01}, - {0x03, 0x01, 0x86, 0x00}, {0x06, 0x01, 0x86, 0x00}, - {0x0a, 0x01, 0x86, 0x00}, {0x0f, 0x01, 0x86, 0x00}, - {0x18, 0x01, 0x86, 0x00}, {0x1f, 0x01, 0x86, 0x00}, - {0x29, 0x01, 0x86, 0x00}, {0x38, 0x01, 0x86, 0x01} - ], - /* 125 */ - [ - {0x03, 0x01, 0x88, 0x00}, {0x06, 0x01, 0x88, 0x00}, - {0x0a, 0x01, 0x88, 0x00}, {0x0f, 0x01, 0x88, 0x00}, - {0x18, 0x01, 0x88, 0x00}, {0x1f, 0x01, 0x88, 0x00}, - {0x29, 0x01, 0x88, 0x00}, {0x38, 0x01, 0x88, 0x01}, - {0x03, 0x01, 0x92, 0x00}, {0x06, 0x01, 0x92, 0x00}, - {0x0a, 0x01, 0x92, 0x00}, {0x0f, 0x01, 0x92, 0x00}, - {0x18, 0x01, 0x92, 0x00}, {0x1f, 0x01, 0x92, 0x00}, - {0x29, 0x01, 0x92, 0x00}, {0x38, 0x01, 0x92, 0x01} - ], - [ - {0x01, 0x01, 0x9a, 0x00}, {0x16, 0x01, 0x9a, 0x01}, - {0x01, 0x01, 0x9c, 0x00}, {0x16, 0x01, 0x9c, 0x01}, - {0x01, 0x01, 0xa0, 0x00}, {0x16, 0x01, 0xa0, 0x01}, - {0x01, 0x01, 0xa3, 0x00}, {0x16, 0x01, 0xa3, 0x01}, - {0x01, 0x01, 0xa4, 0x00}, {0x16, 0x01, 0xa4, 0x01}, - {0x01, 0x01, 0xa9, 0x00}, {0x16, 0x01, 0xa9, 0x01}, - {0x01, 0x01, 0xaa, 0x00}, {0x16, 0x01, 0xaa, 0x01}, - {0x01, 0x01, 0xad, 0x00}, {0x16, 0x01, 0xad, 0x01} - ], - [ - {0x02, 0x01, 0x9a, 0x00}, {0x09, 0x01, 0x9a, 0x00}, - {0x17, 0x01, 0x9a, 0x00}, {0x28, 0x01, 0x9a, 0x01}, - {0x02, 0x01, 0x9c, 0x00}, {0x09, 0x01, 0x9c, 0x00}, - {0x17, 0x01, 0x9c, 0x00}, {0x28, 0x01, 0x9c, 0x01}, - {0x02, 0x01, 0xa0, 0x00}, {0x09, 0x01, 0xa0, 0x00}, - {0x17, 0x01, 0xa0, 0x00}, {0x28, 0x01, 0xa0, 0x01}, - {0x02, 0x01, 0xa3, 0x00}, {0x09, 0x01, 0xa3, 0x00}, - {0x17, 0x01, 0xa3, 0x00}, {0x28, 0x01, 0xa3, 0x01} - ], - [ - {0x03, 0x01, 0x9a, 0x00}, {0x06, 0x01, 0x9a, 0x00}, - {0x0a, 0x01, 0x9a, 0x00}, {0x0f, 0x01, 0x9a, 0x00}, - {0x18, 0x01, 0x9a, 0x00}, {0x1f, 0x01, 0x9a, 0x00}, - {0x29, 0x01, 0x9a, 0x00}, {0x38, 0x01, 0x9a, 0x01}, - {0x03, 0x01, 0x9c, 0x00}, {0x06, 0x01, 0x9c, 0x00}, - {0x0a, 0x01, 0x9c, 0x00}, {0x0f, 0x01, 0x9c, 0x00}, - {0x18, 0x01, 0x9c, 0x00}, {0x1f, 0x01, 0x9c, 0x00}, - {0x29, 0x01, 0x9c, 0x00}, {0x38, 0x01, 0x9c, 0x01} - ], - [ - {0x03, 0x01, 0xa0, 0x00}, {0x06, 0x01, 0xa0, 0x00}, - {0x0a, 0x01, 0xa0, 0x00}, {0x0f, 0x01, 0xa0, 0x00}, - {0x18, 0x01, 0xa0, 0x00}, {0x1f, 0x01, 0xa0, 0x00}, - {0x29, 0x01, 0xa0, 0x00}, {0x38, 0x01, 0xa0, 0x01}, - {0x03, 0x01, 0xa3, 0x00}, {0x06, 0x01, 0xa3, 0x00}, - {0x0a, 0x01, 0xa3, 0x00}, {0x0f, 0x01, 0xa3, 0x00}, - {0x18, 0x01, 0xa3, 0x00}, {0x1f, 0x01, 0xa3, 0x00}, - {0x29, 0x01, 0xa3, 0x00}, {0x38, 0x01, 0xa3, 0x01} - ], - /* 130 */ - [ - {0x02, 0x01, 0xa4, 0x00}, {0x09, 0x01, 0xa4, 0x00}, - {0x17, 0x01, 0xa4, 0x00}, {0x28, 0x01, 0xa4, 0x01}, - {0x02, 0x01, 0xa9, 0x00}, {0x09, 0x01, 0xa9, 0x00}, - {0x17, 0x01, 0xa9, 0x00}, {0x28, 0x01, 0xa9, 0x01}, - {0x02, 0x01, 0xaa, 0x00}, {0x09, 0x01, 0xaa, 0x00}, - {0x17, 0x01, 0xaa, 0x00}, {0x28, 0x01, 0xaa, 0x01}, - {0x02, 0x01, 0xad, 0x00}, {0x09, 0x01, 0xad, 0x00}, - {0x17, 0x01, 0xad, 0x00}, {0x28, 0x01, 0xad, 0x01} - ], - [ - {0x03, 0x01, 0xa4, 0x00}, {0x06, 0x01, 0xa4, 0x00}, - {0x0a, 0x01, 0xa4, 0x00}, {0x0f, 0x01, 0xa4, 0x00}, - {0x18, 0x01, 0xa4, 0x00}, {0x1f, 0x01, 0xa4, 0x00}, - {0x29, 0x01, 0xa4, 0x00}, {0x38, 0x01, 0xa4, 0x01}, - {0x03, 0x01, 0xa9, 0x00}, {0x06, 0x01, 0xa9, 0x00}, - {0x0a, 0x01, 0xa9, 0x00}, {0x0f, 0x01, 0xa9, 0x00}, - {0x18, 0x01, 0xa9, 0x00}, {0x1f, 0x01, 0xa9, 0x00}, - {0x29, 0x01, 0xa9, 0x00}, {0x38, 0x01, 0xa9, 0x01} - ], - [ - {0x03, 0x01, 0xaa, 0x00}, {0x06, 0x01, 0xaa, 0x00}, - {0x0a, 0x01, 0xaa, 0x00}, {0x0f, 0x01, 0xaa, 0x00}, - {0x18, 0x01, 0xaa, 0x00}, {0x1f, 0x01, 0xaa, 0x00}, - {0x29, 0x01, 0xaa, 0x00}, {0x38, 0x01, 0xaa, 0x01}, - {0x03, 0x01, 0xad, 0x00}, {0x06, 0x01, 0xad, 0x00}, - {0x0a, 0x01, 0xad, 0x00}, {0x0f, 0x01, 0xad, 0x00}, - {0x18, 0x01, 0xad, 0x00}, {0x1f, 0x01, 0xad, 0x00}, - {0x29, 0x01, 0xad, 0x00}, {0x38, 0x01, 0xad, 0x01} - ], - [ - {0x89, 0x00, 0x00, 0x00}, {0x8a, 0x00, 0x00, 0x00}, - {0x8c, 0x00, 0x00, 0x00}, {0x8d, 0x00, 0x00, 0x00}, - {0x90, 0x00, 0x00, 0x00}, {0x91, 0x00, 0x00, 0x00}, - {0x93, 0x00, 0x00, 0x00}, {0x96, 0x00, 0x00, 0x00}, - {0x9c, 0x00, 0x00, 0x00}, {0x9f, 0x00, 0x00, 0x00}, - {0xa3, 0x00, 0x00, 0x00}, {0xa6, 0x00, 0x00, 0x00}, - {0xab, 0x00, 0x00, 0x00}, {0xae, 0x00, 0x00, 0x00}, - {0xb5, 0x00, 0x00, 0x00}, {0xbe, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0xb2, 0x01}, {0x00, 0x01, 0xb5, 0x01}, - {0x00, 0x01, 0xb9, 0x01}, {0x00, 0x01, 0xba, 0x01}, - {0x00, 0x01, 0xbb, 0x01}, {0x00, 0x01, 0xbd, 0x01}, - {0x00, 0x01, 0xbe, 0x01}, {0x00, 0x01, 0xc4, 0x01}, - {0x00, 0x01, 0xc6, 0x01}, {0x00, 0x01, 0xe4, 0x01}, - {0x00, 0x01, 0xe8, 0x01}, {0x00, 0x01, 0xe9, 0x01}, - {0x94, 0x00, 0x00, 0x00}, {0x95, 0x00, 0x00, 0x00}, - {0x97, 0x00, 0x00, 0x00}, {0x98, 0x00, 0x00, 0x00} - ], - /* 135 */ - [ - {0x01, 0x01, 0xb2, 0x00}, {0x16, 0x01, 0xb2, 0x01}, - {0x01, 0x01, 0xb5, 0x00}, {0x16, 0x01, 0xb5, 0x01}, - {0x01, 0x01, 0xb9, 0x00}, {0x16, 0x01, 0xb9, 0x01}, - {0x01, 0x01, 0xba, 0x00}, {0x16, 0x01, 0xba, 0x01}, - {0x01, 0x01, 0xbb, 0x00}, {0x16, 0x01, 0xbb, 0x01}, - {0x01, 0x01, 0xbd, 0x00}, {0x16, 0x01, 0xbd, 0x01}, - {0x01, 0x01, 0xbe, 0x00}, {0x16, 0x01, 0xbe, 0x01}, - {0x01, 0x01, 0xc4, 0x00}, {0x16, 0x01, 0xc4, 0x01} - ], - [ - {0x02, 0x01, 0xb2, 0x00}, {0x09, 0x01, 0xb2, 0x00}, - {0x17, 0x01, 0xb2, 0x00}, {0x28, 0x01, 0xb2, 0x01}, - {0x02, 0x01, 0xb5, 0x00}, {0x09, 0x01, 0xb5, 0x00}, - {0x17, 0x01, 0xb5, 0x00}, {0x28, 0x01, 0xb5, 0x01}, - {0x02, 0x01, 0xb9, 0x00}, {0x09, 0x01, 0xb9, 0x00}, - {0x17, 0x01, 0xb9, 0x00}, {0x28, 0x01, 0xb9, 0x01}, - {0x02, 0x01, 0xba, 0x00}, {0x09, 0x01, 0xba, 0x00}, - {0x17, 0x01, 0xba, 0x00}, {0x28, 0x01, 0xba, 0x01} - ], - [ - {0x03, 0x01, 0xb2, 0x00}, {0x06, 0x01, 0xb2, 0x00}, - {0x0a, 0x01, 0xb2, 0x00}, {0x0f, 0x01, 0xb2, 0x00}, - {0x18, 0x01, 0xb2, 0x00}, {0x1f, 0x01, 0xb2, 0x00}, - {0x29, 0x01, 0xb2, 0x00}, {0x38, 0x01, 0xb2, 0x01}, - {0x03, 0x01, 0xb5, 0x00}, {0x06, 0x01, 0xb5, 0x00}, - {0x0a, 0x01, 0xb5, 0x00}, {0x0f, 0x01, 0xb5, 0x00}, - {0x18, 0x01, 0xb5, 0x00}, {0x1f, 0x01, 0xb5, 0x00}, - {0x29, 0x01, 0xb5, 0x00}, {0x38, 0x01, 0xb5, 0x01} - ], - [ - {0x03, 0x01, 0xb9, 0x00}, {0x06, 0x01, 0xb9, 0x00}, - {0x0a, 0x01, 0xb9, 0x00}, {0x0f, 0x01, 0xb9, 0x00}, - {0x18, 0x01, 0xb9, 0x00}, {0x1f, 0x01, 0xb9, 0x00}, - {0x29, 0x01, 0xb9, 0x00}, {0x38, 0x01, 0xb9, 0x01}, - {0x03, 0x01, 0xba, 0x00}, {0x06, 0x01, 0xba, 0x00}, - {0x0a, 0x01, 0xba, 0x00}, {0x0f, 0x01, 0xba, 0x00}, - {0x18, 0x01, 0xba, 0x00}, {0x1f, 0x01, 0xba, 0x00}, - {0x29, 0x01, 0xba, 0x00}, {0x38, 0x01, 0xba, 0x01} - ], - [ - {0x02, 0x01, 0xbb, 0x00}, {0x09, 0x01, 0xbb, 0x00}, - {0x17, 0x01, 0xbb, 0x00}, {0x28, 0x01, 0xbb, 0x01}, - {0x02, 0x01, 0xbd, 0x00}, {0x09, 0x01, 0xbd, 0x00}, - {0x17, 0x01, 0xbd, 0x00}, {0x28, 0x01, 0xbd, 0x01}, - {0x02, 0x01, 0xbe, 0x00}, {0x09, 0x01, 0xbe, 0x00}, - {0x17, 0x01, 0xbe, 0x00}, {0x28, 0x01, 0xbe, 0x01}, - {0x02, 0x01, 0xc4, 0x00}, {0x09, 0x01, 0xc4, 0x00}, - {0x17, 0x01, 0xc4, 0x00}, {0x28, 0x01, 0xc4, 0x01} - ], - /* 140 */ - [ - {0x03, 0x01, 0xbb, 0x00}, {0x06, 0x01, 0xbb, 0x00}, - {0x0a, 0x01, 0xbb, 0x00}, {0x0f, 0x01, 0xbb, 0x00}, - {0x18, 0x01, 0xbb, 0x00}, {0x1f, 0x01, 0xbb, 0x00}, - {0x29, 0x01, 0xbb, 0x00}, {0x38, 0x01, 0xbb, 0x01}, - {0x03, 0x01, 0xbd, 0x00}, {0x06, 0x01, 0xbd, 0x00}, - {0x0a, 0x01, 0xbd, 0x00}, {0x0f, 0x01, 0xbd, 0x00}, - {0x18, 0x01, 0xbd, 0x00}, {0x1f, 0x01, 0xbd, 0x00}, - {0x29, 0x01, 0xbd, 0x00}, {0x38, 0x01, 0xbd, 0x01} - ], - [ - {0x03, 0x01, 0xbe, 0x00}, {0x06, 0x01, 0xbe, 0x00}, - {0x0a, 0x01, 0xbe, 0x00}, {0x0f, 0x01, 0xbe, 0x00}, - {0x18, 0x01, 0xbe, 0x00}, {0x1f, 0x01, 0xbe, 0x00}, - {0x29, 0x01, 0xbe, 0x00}, {0x38, 0x01, 0xbe, 0x01}, - {0x03, 0x01, 0xc4, 0x00}, {0x06, 0x01, 0xc4, 0x00}, - {0x0a, 0x01, 0xc4, 0x00}, {0x0f, 0x01, 0xc4, 0x00}, - {0x18, 0x01, 0xc4, 0x00}, {0x1f, 0x01, 0xc4, 0x00}, - {0x29, 0x01, 0xc4, 0x00}, {0x38, 0x01, 0xc4, 0x01} - ], - [ - {0x01, 0x01, 0xc6, 0x00}, {0x16, 0x01, 0xc6, 0x01}, - {0x01, 0x01, 0xe4, 0x00}, {0x16, 0x01, 0xe4, 0x01}, - {0x01, 0x01, 0xe8, 0x00}, {0x16, 0x01, 0xe8, 0x01}, - {0x01, 0x01, 0xe9, 0x00}, {0x16, 0x01, 0xe9, 0x01}, - {0x00, 0x01, 0x01, 0x01}, {0x00, 0x01, 0x87, 0x01}, - {0x00, 0x01, 0x89, 0x01}, {0x00, 0x01, 0x8a, 0x01}, - {0x00, 0x01, 0x8b, 0x01}, {0x00, 0x01, 0x8c, 0x01}, - {0x00, 0x01, 0x8d, 0x01}, {0x00, 0x01, 0x8f, 0x01} - ], - [ - {0x02, 0x01, 0xc6, 0x00}, {0x09, 0x01, 0xc6, 0x00}, - {0x17, 0x01, 0xc6, 0x00}, {0x28, 0x01, 0xc6, 0x01}, - {0x02, 0x01, 0xe4, 0x00}, {0x09, 0x01, 0xe4, 0x00}, - {0x17, 0x01, 0xe4, 0x00}, {0x28, 0x01, 0xe4, 0x01}, - {0x02, 0x01, 0xe8, 0x00}, {0x09, 0x01, 0xe8, 0x00}, - {0x17, 0x01, 0xe8, 0x00}, {0x28, 0x01, 0xe8, 0x01}, - {0x02, 0x01, 0xe9, 0x00}, {0x09, 0x01, 0xe9, 0x00}, - {0x17, 0x01, 0xe9, 0x00}, {0x28, 0x01, 0xe9, 0x01} - ], - [ - {0x03, 0x01, 0xc6, 0x00}, {0x06, 0x01, 0xc6, 0x00}, - {0x0a, 0x01, 0xc6, 0x00}, {0x0f, 0x01, 0xc6, 0x00}, - {0x18, 0x01, 0xc6, 0x00}, {0x1f, 0x01, 0xc6, 0x00}, - {0x29, 0x01, 0xc6, 0x00}, {0x38, 0x01, 0xc6, 0x01}, - {0x03, 0x01, 0xe4, 0x00}, {0x06, 0x01, 0xe4, 0x00}, - {0x0a, 0x01, 0xe4, 0x00}, {0x0f, 0x01, 0xe4, 0x00}, - {0x18, 0x01, 0xe4, 0x00}, {0x1f, 0x01, 0xe4, 0x00}, - {0x29, 0x01, 0xe4, 0x00}, {0x38, 0x01, 0xe4, 0x01} - ], - /* 145 */ - [ - {0x03, 0x01, 0xe8, 0x00}, {0x06, 0x01, 0xe8, 0x00}, - {0x0a, 0x01, 0xe8, 0x00}, {0x0f, 0x01, 0xe8, 0x00}, - {0x18, 0x01, 0xe8, 0x00}, {0x1f, 0x01, 0xe8, 0x00}, - {0x29, 0x01, 0xe8, 0x00}, {0x38, 0x01, 0xe8, 0x01}, - {0x03, 0x01, 0xe9, 0x00}, {0x06, 0x01, 0xe9, 0x00}, - {0x0a, 0x01, 0xe9, 0x00}, {0x0f, 0x01, 0xe9, 0x00}, - {0x18, 0x01, 0xe9, 0x00}, {0x1f, 0x01, 0xe9, 0x00}, - {0x29, 0x01, 0xe9, 0x00}, {0x38, 0x01, 0xe9, 0x01} - ], - [ - {0x01, 0x01, 0x01, 0x00}, {0x16, 0x01, 0x01, 0x01}, - {0x01, 0x01, 0x87, 0x00}, {0x16, 0x01, 0x87, 0x01}, - {0x01, 0x01, 0x89, 0x00}, {0x16, 0x01, 0x89, 0x01}, - {0x01, 0x01, 0x8a, 0x00}, {0x16, 0x01, 0x8a, 0x01}, - {0x01, 0x01, 0x8b, 0x00}, {0x16, 0x01, 0x8b, 0x01}, - {0x01, 0x01, 0x8c, 0x00}, {0x16, 0x01, 0x8c, 0x01}, - {0x01, 0x01, 0x8d, 0x00}, {0x16, 0x01, 0x8d, 0x01}, - {0x01, 0x01, 0x8f, 0x00}, {0x16, 0x01, 0x8f, 0x01} - ], - [ - {0x02, 0x01, 0x01, 0x00}, {0x09, 0x01, 0x01, 0x00}, - {0x17, 0x01, 0x01, 0x00}, {0x28, 0x01, 0x01, 0x01}, - {0x02, 0x01, 0x87, 0x00}, {0x09, 0x01, 0x87, 0x00}, - {0x17, 0x01, 0x87, 0x00}, {0x28, 0x01, 0x87, 0x01}, - {0x02, 0x01, 0x89, 0x00}, {0x09, 0x01, 0x89, 0x00}, - {0x17, 0x01, 0x89, 0x00}, {0x28, 0x01, 0x89, 0x01}, - {0x02, 0x01, 0x8a, 0x00}, {0x09, 0x01, 0x8a, 0x00}, - {0x17, 0x01, 0x8a, 0x00}, {0x28, 0x01, 0x8a, 0x01} - ], - [ - {0x03, 0x01, 0x01, 0x00}, {0x06, 0x01, 0x01, 0x00}, - {0x0a, 0x01, 0x01, 0x00}, {0x0f, 0x01, 0x01, 0x00}, - {0x18, 0x01, 0x01, 0x00}, {0x1f, 0x01, 0x01, 0x00}, - {0x29, 0x01, 0x01, 0x00}, {0x38, 0x01, 0x01, 0x01}, - {0x03, 0x01, 0x87, 0x00}, {0x06, 0x01, 0x87, 0x00}, - {0x0a, 0x01, 0x87, 0x00}, {0x0f, 0x01, 0x87, 0x00}, - {0x18, 0x01, 0x87, 0x00}, {0x1f, 0x01, 0x87, 0x00}, - {0x29, 0x01, 0x87, 0x00}, {0x38, 0x01, 0x87, 0x01} - ], - [ - {0x03, 0x01, 0x89, 0x00}, {0x06, 0x01, 0x89, 0x00}, - {0x0a, 0x01, 0x89, 0x00}, {0x0f, 0x01, 0x89, 0x00}, - {0x18, 0x01, 0x89, 0x00}, {0x1f, 0x01, 0x89, 0x00}, - {0x29, 0x01, 0x89, 0x00}, {0x38, 0x01, 0x89, 0x01}, - {0x03, 0x01, 0x8a, 0x00}, {0x06, 0x01, 0x8a, 0x00}, - {0x0a, 0x01, 0x8a, 0x00}, {0x0f, 0x01, 0x8a, 0x00}, - {0x18, 0x01, 0x8a, 0x00}, {0x1f, 0x01, 0x8a, 0x00}, - {0x29, 0x01, 0x8a, 0x00}, {0x38, 0x01, 0x8a, 0x01} - ], - /* 150 */ - [ - {0x02, 0x01, 0x8b, 0x00}, {0x09, 0x01, 0x8b, 0x00}, - {0x17, 0x01, 0x8b, 0x00}, {0x28, 0x01, 0x8b, 0x01}, - {0x02, 0x01, 0x8c, 0x00}, {0x09, 0x01, 0x8c, 0x00}, - {0x17, 0x01, 0x8c, 0x00}, {0x28, 0x01, 0x8c, 0x01}, - {0x02, 0x01, 0x8d, 0x00}, {0x09, 0x01, 0x8d, 0x00}, - {0x17, 0x01, 0x8d, 0x00}, {0x28, 0x01, 0x8d, 0x01}, - {0x02, 0x01, 0x8f, 0x00}, {0x09, 0x01, 0x8f, 0x00}, - {0x17, 0x01, 0x8f, 0x00}, {0x28, 0x01, 0x8f, 0x01} - ], - [ - {0x03, 0x01, 0x8b, 0x00}, {0x06, 0x01, 0x8b, 0x00}, - {0x0a, 0x01, 0x8b, 0x00}, {0x0f, 0x01, 0x8b, 0x00}, - {0x18, 0x01, 0x8b, 0x00}, {0x1f, 0x01, 0x8b, 0x00}, - {0x29, 0x01, 0x8b, 0x00}, {0x38, 0x01, 0x8b, 0x01}, - {0x03, 0x01, 0x8c, 0x00}, {0x06, 0x01, 0x8c, 0x00}, - {0x0a, 0x01, 0x8c, 0x00}, {0x0f, 0x01, 0x8c, 0x00}, - {0x18, 0x01, 0x8c, 0x00}, {0x1f, 0x01, 0x8c, 0x00}, - {0x29, 0x01, 0x8c, 0x00}, {0x38, 0x01, 0x8c, 0x01} - ], - [ - {0x03, 0x01, 0x8d, 0x00}, {0x06, 0x01, 0x8d, 0x00}, - {0x0a, 0x01, 0x8d, 0x00}, {0x0f, 0x01, 0x8d, 0x00}, - {0x18, 0x01, 0x8d, 0x00}, {0x1f, 0x01, 0x8d, 0x00}, - {0x29, 0x01, 0x8d, 0x00}, {0x38, 0x01, 0x8d, 0x01}, - {0x03, 0x01, 0x8f, 0x00}, {0x06, 0x01, 0x8f, 0x00}, - {0x0a, 0x01, 0x8f, 0x00}, {0x0f, 0x01, 0x8f, 0x00}, - {0x18, 0x01, 0x8f, 0x00}, {0x1f, 0x01, 0x8f, 0x00}, - {0x29, 0x01, 0x8f, 0x00}, {0x38, 0x01, 0x8f, 0x01} - ], - [ - {0x9d, 0x00, 0x00, 0x00}, {0x9e, 0x00, 0x00, 0x00}, - {0xa0, 0x00, 0x00, 0x00}, {0xa1, 0x00, 0x00, 0x00}, - {0xa4, 0x00, 0x00, 0x00}, {0xa5, 0x00, 0x00, 0x00}, - {0xa7, 0x00, 0x00, 0x00}, {0xa8, 0x00, 0x00, 0x00}, - {0xac, 0x00, 0x00, 0x00}, {0xad, 0x00, 0x00, 0x00}, - {0xaf, 0x00, 0x00, 0x00}, {0xb1, 0x00, 0x00, 0x00}, - {0xb6, 0x00, 0x00, 0x00}, {0xb9, 0x00, 0x00, 0x00}, - {0xbf, 0x00, 0x00, 0x00}, {0xcf, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0x93, 0x01}, {0x00, 0x01, 0x95, 0x01}, - {0x00, 0x01, 0x96, 0x01}, {0x00, 0x01, 0x97, 0x01}, - {0x00, 0x01, 0x98, 0x01}, {0x00, 0x01, 0x9b, 0x01}, - {0x00, 0x01, 0x9d, 0x01}, {0x00, 0x01, 0x9e, 0x01}, - {0x00, 0x01, 0xa5, 0x01}, {0x00, 0x01, 0xa6, 0x01}, - {0x00, 0x01, 0xa8, 0x01}, {0x00, 0x01, 0xae, 0x01}, - {0x00, 0x01, 0xaf, 0x01}, {0x00, 0x01, 0xb4, 0x01}, - {0x00, 0x01, 0xb6, 0x01}, {0x00, 0x01, 0xb7, 0x01} - ], - /* 155 */ - [ - {0x01, 0x01, 0x93, 0x00}, {0x16, 0x01, 0x93, 0x01}, - {0x01, 0x01, 0x95, 0x00}, {0x16, 0x01, 0x95, 0x01}, - {0x01, 0x01, 0x96, 0x00}, {0x16, 0x01, 0x96, 0x01}, - {0x01, 0x01, 0x97, 0x00}, {0x16, 0x01, 0x97, 0x01}, - {0x01, 0x01, 0x98, 0x00}, {0x16, 0x01, 0x98, 0x01}, - {0x01, 0x01, 0x9b, 0x00}, {0x16, 0x01, 0x9b, 0x01}, - {0x01, 0x01, 0x9d, 0x00}, {0x16, 0x01, 0x9d, 0x01}, - {0x01, 0x01, 0x9e, 0x00}, {0x16, 0x01, 0x9e, 0x01} - ], - [ - {0x02, 0x01, 0x93, 0x00}, {0x09, 0x01, 0x93, 0x00}, - {0x17, 0x01, 0x93, 0x00}, {0x28, 0x01, 0x93, 0x01}, - {0x02, 0x01, 0x95, 0x00}, {0x09, 0x01, 0x95, 0x00}, - {0x17, 0x01, 0x95, 0x00}, {0x28, 0x01, 0x95, 0x01}, - {0x02, 0x01, 0x96, 0x00}, {0x09, 0x01, 0x96, 0x00}, - {0x17, 0x01, 0x96, 0x00}, {0x28, 0x01, 0x96, 0x01}, - {0x02, 0x01, 0x97, 0x00}, {0x09, 0x01, 0x97, 0x00}, - {0x17, 0x01, 0x97, 0x00}, {0x28, 0x01, 0x97, 0x01} - ], - [ - {0x03, 0x01, 0x93, 0x00}, {0x06, 0x01, 0x93, 0x00}, - {0x0a, 0x01, 0x93, 0x00}, {0x0f, 0x01, 0x93, 0x00}, - {0x18, 0x01, 0x93, 0x00}, {0x1f, 0x01, 0x93, 0x00}, - {0x29, 0x01, 0x93, 0x00}, {0x38, 0x01, 0x93, 0x01}, - {0x03, 0x01, 0x95, 0x00}, {0x06, 0x01, 0x95, 0x00}, - {0x0a, 0x01, 0x95, 0x00}, {0x0f, 0x01, 0x95, 0x00}, - {0x18, 0x01, 0x95, 0x00}, {0x1f, 0x01, 0x95, 0x00}, - {0x29, 0x01, 0x95, 0x00}, {0x38, 0x01, 0x95, 0x01} - ], - [ - {0x03, 0x01, 0x96, 0x00}, {0x06, 0x01, 0x96, 0x00}, - {0x0a, 0x01, 0x96, 0x00}, {0x0f, 0x01, 0x96, 0x00}, - {0x18, 0x01, 0x96, 0x00}, {0x1f, 0x01, 0x96, 0x00}, - {0x29, 0x01, 0x96, 0x00}, {0x38, 0x01, 0x96, 0x01}, - {0x03, 0x01, 0x97, 0x00}, {0x06, 0x01, 0x97, 0x00}, - {0x0a, 0x01, 0x97, 0x00}, {0x0f, 0x01, 0x97, 0x00}, - {0x18, 0x01, 0x97, 0x00}, {0x1f, 0x01, 0x97, 0x00}, - {0x29, 0x01, 0x97, 0x00}, {0x38, 0x01, 0x97, 0x01} - ], - [ - {0x02, 0x01, 0x98, 0x00}, {0x09, 0x01, 0x98, 0x00}, - {0x17, 0x01, 0x98, 0x00}, {0x28, 0x01, 0x98, 0x01}, - {0x02, 0x01, 0x9b, 0x00}, {0x09, 0x01, 0x9b, 0x00}, - {0x17, 0x01, 0x9b, 0x00}, {0x28, 0x01, 0x9b, 0x01}, - {0x02, 0x01, 0x9d, 0x00}, {0x09, 0x01, 0x9d, 0x00}, - {0x17, 0x01, 0x9d, 0x00}, {0x28, 0x01, 0x9d, 0x01}, - {0x02, 0x01, 0x9e, 0x00}, {0x09, 0x01, 0x9e, 0x00}, - {0x17, 0x01, 0x9e, 0x00}, {0x28, 0x01, 0x9e, 0x01} - ], - /* 160 */ - [ - {0x03, 0x01, 0x98, 0x00}, {0x06, 0x01, 0x98, 0x00}, - {0x0a, 0x01, 0x98, 0x00}, {0x0f, 0x01, 0x98, 0x00}, - {0x18, 0x01, 0x98, 0x00}, {0x1f, 0x01, 0x98, 0x00}, - {0x29, 0x01, 0x98, 0x00}, {0x38, 0x01, 0x98, 0x01}, - {0x03, 0x01, 0x9b, 0x00}, {0x06, 0x01, 0x9b, 0x00}, - {0x0a, 0x01, 0x9b, 0x00}, {0x0f, 0x01, 0x9b, 0x00}, - {0x18, 0x01, 0x9b, 0x00}, {0x1f, 0x01, 0x9b, 0x00}, - {0x29, 0x01, 0x9b, 0x00}, {0x38, 0x01, 0x9b, 0x01} - ], - [ - {0x03, 0x01, 0x9d, 0x00}, {0x06, 0x01, 0x9d, 0x00}, - {0x0a, 0x01, 0x9d, 0x00}, {0x0f, 0x01, 0x9d, 0x00}, - {0x18, 0x01, 0x9d, 0x00}, {0x1f, 0x01, 0x9d, 0x00}, - {0x29, 0x01, 0x9d, 0x00}, {0x38, 0x01, 0x9d, 0x01}, - {0x03, 0x01, 0x9e, 0x00}, {0x06, 0x01, 0x9e, 0x00}, - {0x0a, 0x01, 0x9e, 0x00}, {0x0f, 0x01, 0x9e, 0x00}, - {0x18, 0x01, 0x9e, 0x00}, {0x1f, 0x01, 0x9e, 0x00}, - {0x29, 0x01, 0x9e, 0x00}, {0x38, 0x01, 0x9e, 0x01} - ], - [ - {0x01, 0x01, 0xa5, 0x00}, {0x16, 0x01, 0xa5, 0x01}, - {0x01, 0x01, 0xa6, 0x00}, {0x16, 0x01, 0xa6, 0x01}, - {0x01, 0x01, 0xa8, 0x00}, {0x16, 0x01, 0xa8, 0x01}, - {0x01, 0x01, 0xae, 0x00}, {0x16, 0x01, 0xae, 0x01}, - {0x01, 0x01, 0xaf, 0x00}, {0x16, 0x01, 0xaf, 0x01}, - {0x01, 0x01, 0xb4, 0x00}, {0x16, 0x01, 0xb4, 0x01}, - {0x01, 0x01, 0xb6, 0x00}, {0x16, 0x01, 0xb6, 0x01}, - {0x01, 0x01, 0xb7, 0x00}, {0x16, 0x01, 0xb7, 0x01} - ], - [ - {0x02, 0x01, 0xa5, 0x00}, {0x09, 0x01, 0xa5, 0x00}, - {0x17, 0x01, 0xa5, 0x00}, {0x28, 0x01, 0xa5, 0x01}, - {0x02, 0x01, 0xa6, 0x00}, {0x09, 0x01, 0xa6, 0x00}, - {0x17, 0x01, 0xa6, 0x00}, {0x28, 0x01, 0xa6, 0x01}, - {0x02, 0x01, 0xa8, 0x00}, {0x09, 0x01, 0xa8, 0x00}, - {0x17, 0x01, 0xa8, 0x00}, {0x28, 0x01, 0xa8, 0x01}, - {0x02, 0x01, 0xae, 0x00}, {0x09, 0x01, 0xae, 0x00}, - {0x17, 0x01, 0xae, 0x00}, {0x28, 0x01, 0xae, 0x01} - ], - [ - {0x03, 0x01, 0xa5, 0x00}, {0x06, 0x01, 0xa5, 0x00}, - {0x0a, 0x01, 0xa5, 0x00}, {0x0f, 0x01, 0xa5, 0x00}, - {0x18, 0x01, 0xa5, 0x00}, {0x1f, 0x01, 0xa5, 0x00}, - {0x29, 0x01, 0xa5, 0x00}, {0x38, 0x01, 0xa5, 0x01}, - {0x03, 0x01, 0xa6, 0x00}, {0x06, 0x01, 0xa6, 0x00}, - {0x0a, 0x01, 0xa6, 0x00}, {0x0f, 0x01, 0xa6, 0x00}, - {0x18, 0x01, 0xa6, 0x00}, {0x1f, 0x01, 0xa6, 0x00}, - {0x29, 0x01, 0xa6, 0x00}, {0x38, 0x01, 0xa6, 0x01} - ], - /* 165 */ - [ - {0x03, 0x01, 0xa8, 0x00}, {0x06, 0x01, 0xa8, 0x00}, - {0x0a, 0x01, 0xa8, 0x00}, {0x0f, 0x01, 0xa8, 0x00}, - {0x18, 0x01, 0xa8, 0x00}, {0x1f, 0x01, 0xa8, 0x00}, - {0x29, 0x01, 0xa8, 0x00}, {0x38, 0x01, 0xa8, 0x01}, - {0x03, 0x01, 0xae, 0x00}, {0x06, 0x01, 0xae, 0x00}, - {0x0a, 0x01, 0xae, 0x00}, {0x0f, 0x01, 0xae, 0x00}, - {0x18, 0x01, 0xae, 0x00}, {0x1f, 0x01, 0xae, 0x00}, - {0x29, 0x01, 0xae, 0x00}, {0x38, 0x01, 0xae, 0x01} - ], - [ - {0x02, 0x01, 0xaf, 0x00}, {0x09, 0x01, 0xaf, 0x00}, - {0x17, 0x01, 0xaf, 0x00}, {0x28, 0x01, 0xaf, 0x01}, - {0x02, 0x01, 0xb4, 0x00}, {0x09, 0x01, 0xb4, 0x00}, - {0x17, 0x01, 0xb4, 0x00}, {0x28, 0x01, 0xb4, 0x01}, - {0x02, 0x01, 0xb6, 0x00}, {0x09, 0x01, 0xb6, 0x00}, - {0x17, 0x01, 0xb6, 0x00}, {0x28, 0x01, 0xb6, 0x01}, - {0x02, 0x01, 0xb7, 0x00}, {0x09, 0x01, 0xb7, 0x00}, - {0x17, 0x01, 0xb7, 0x00}, {0x28, 0x01, 0xb7, 0x01} - ], - [ - {0x03, 0x01, 0xaf, 0x00}, {0x06, 0x01, 0xaf, 0x00}, - {0x0a, 0x01, 0xaf, 0x00}, {0x0f, 0x01, 0xaf, 0x00}, - {0x18, 0x01, 0xaf, 0x00}, {0x1f, 0x01, 0xaf, 0x00}, - {0x29, 0x01, 0xaf, 0x00}, {0x38, 0x01, 0xaf, 0x01}, - {0x03, 0x01, 0xb4, 0x00}, {0x06, 0x01, 0xb4, 0x00}, - {0x0a, 0x01, 0xb4, 0x00}, {0x0f, 0x01, 0xb4, 0x00}, - {0x18, 0x01, 0xb4, 0x00}, {0x1f, 0x01, 0xb4, 0x00}, - {0x29, 0x01, 0xb4, 0x00}, {0x38, 0x01, 0xb4, 0x01} - ], - [ - {0x03, 0x01, 0xb6, 0x00}, {0x06, 0x01, 0xb6, 0x00}, - {0x0a, 0x01, 0xb6, 0x00}, {0x0f, 0x01, 0xb6, 0x00}, - {0x18, 0x01, 0xb6, 0x00}, {0x1f, 0x01, 0xb6, 0x00}, - {0x29, 0x01, 0xb6, 0x00}, {0x38, 0x01, 0xb6, 0x01}, - {0x03, 0x01, 0xb7, 0x00}, {0x06, 0x01, 0xb7, 0x00}, - {0x0a, 0x01, 0xb7, 0x00}, {0x0f, 0x01, 0xb7, 0x00}, - {0x18, 0x01, 0xb7, 0x00}, {0x1f, 0x01, 0xb7, 0x00}, - {0x29, 0x01, 0xb7, 0x00}, {0x38, 0x01, 0xb7, 0x01} - ], - [ - {0x00, 0x01, 0xbc, 0x01}, {0x00, 0x01, 0xbf, 0x01}, - {0x00, 0x01, 0xc5, 0x01}, {0x00, 0x01, 0xe7, 0x01}, - {0x00, 0x01, 0xef, 0x01}, {0xb0, 0x00, 0x00, 0x00}, - {0xb2, 0x00, 0x00, 0x00}, {0xb3, 0x00, 0x00, 0x00}, - {0xb7, 0x00, 0x00, 0x00}, {0xb8, 0x00, 0x00, 0x00}, - {0xba, 0x00, 0x00, 0x00}, {0xbb, 0x00, 0x00, 0x00}, - {0xc0, 0x00, 0x00, 0x00}, {0xc7, 0x00, 0x00, 0x00}, - {0xd0, 0x00, 0x00, 0x00}, {0xdf, 0x00, 0x00, 0x01} - ], - /* 170 */ - [ - {0x01, 0x01, 0xbc, 0x00}, {0x16, 0x01, 0xbc, 0x01}, - {0x01, 0x01, 0xbf, 0x00}, {0x16, 0x01, 0xbf, 0x01}, - {0x01, 0x01, 0xc5, 0x00}, {0x16, 0x01, 0xc5, 0x01}, - {0x01, 0x01, 0xe7, 0x00}, {0x16, 0x01, 0xe7, 0x01}, - {0x01, 0x01, 0xef, 0x00}, {0x16, 0x01, 0xef, 0x01}, - {0x00, 0x01, 0x09, 0x01}, {0x00, 0x01, 0x8e, 0x01}, - {0x00, 0x01, 0x90, 0x01}, {0x00, 0x01, 0x91, 0x01}, - {0x00, 0x01, 0x94, 0x01}, {0x00, 0x01, 0x9f, 0x01} - ], - [ - {0x02, 0x01, 0xbc, 0x00}, {0x09, 0x01, 0xbc, 0x00}, - {0x17, 0x01, 0xbc, 0x00}, {0x28, 0x01, 0xbc, 0x01}, - {0x02, 0x01, 0xbf, 0x00}, {0x09, 0x01, 0xbf, 0x00}, - {0x17, 0x01, 0xbf, 0x00}, {0x28, 0x01, 0xbf, 0x01}, - {0x02, 0x01, 0xc5, 0x00}, {0x09, 0x01, 0xc5, 0x00}, - {0x17, 0x01, 0xc5, 0x00}, {0x28, 0x01, 0xc5, 0x01}, - {0x02, 0x01, 0xe7, 0x00}, {0x09, 0x01, 0xe7, 0x00}, - {0x17, 0x01, 0xe7, 0x00}, {0x28, 0x01, 0xe7, 0x01} - ], - [ - {0x03, 0x01, 0xbc, 0x00}, {0x06, 0x01, 0xbc, 0x00}, - {0x0a, 0x01, 0xbc, 0x00}, {0x0f, 0x01, 0xbc, 0x00}, - {0x18, 0x01, 0xbc, 0x00}, {0x1f, 0x01, 0xbc, 0x00}, - {0x29, 0x01, 0xbc, 0x00}, {0x38, 0x01, 0xbc, 0x01}, - {0x03, 0x01, 0xbf, 0x00}, {0x06, 0x01, 0xbf, 0x00}, - {0x0a, 0x01, 0xbf, 0x00}, {0x0f, 0x01, 0xbf, 0x00}, - {0x18, 0x01, 0xbf, 0x00}, {0x1f, 0x01, 0xbf, 0x00}, - {0x29, 0x01, 0xbf, 0x00}, {0x38, 0x01, 0xbf, 0x01} - ], - [ - {0x03, 0x01, 0xc5, 0x00}, {0x06, 0x01, 0xc5, 0x00}, - {0x0a, 0x01, 0xc5, 0x00}, {0x0f, 0x01, 0xc5, 0x00}, - {0x18, 0x01, 0xc5, 0x00}, {0x1f, 0x01, 0xc5, 0x00}, - {0x29, 0x01, 0xc5, 0x00}, {0x38, 0x01, 0xc5, 0x01}, - {0x03, 0x01, 0xe7, 0x00}, {0x06, 0x01, 0xe7, 0x00}, - {0x0a, 0x01, 0xe7, 0x00}, {0x0f, 0x01, 0xe7, 0x00}, - {0x18, 0x01, 0xe7, 0x00}, {0x1f, 0x01, 0xe7, 0x00}, - {0x29, 0x01, 0xe7, 0x00}, {0x38, 0x01, 0xe7, 0x01} - ], - [ - {0x02, 0x01, 0xef, 0x00}, {0x09, 0x01, 0xef, 0x00}, - {0x17, 0x01, 0xef, 0x00}, {0x28, 0x01, 0xef, 0x01}, - {0x01, 0x01, 0x09, 0x00}, {0x16, 0x01, 0x09, 0x01}, - {0x01, 0x01, 0x8e, 0x00}, {0x16, 0x01, 0x8e, 0x01}, - {0x01, 0x01, 0x90, 0x00}, {0x16, 0x01, 0x90, 0x01}, - {0x01, 0x01, 0x91, 0x00}, {0x16, 0x01, 0x91, 0x01}, - {0x01, 0x01, 0x94, 0x00}, {0x16, 0x01, 0x94, 0x01}, - {0x01, 0x01, 0x9f, 0x00}, {0x16, 0x01, 0x9f, 0x01} - ], - /* 175 */ - [ - {0x03, 0x01, 0xef, 0x00}, {0x06, 0x01, 0xef, 0x00}, - {0x0a, 0x01, 0xef, 0x00}, {0x0f, 0x01, 0xef, 0x00}, - {0x18, 0x01, 0xef, 0x00}, {0x1f, 0x01, 0xef, 0x00}, - {0x29, 0x01, 0xef, 0x00}, {0x38, 0x01, 0xef, 0x01}, - {0x02, 0x01, 0x09, 0x00}, {0x09, 0x01, 0x09, 0x00}, - {0x17, 0x01, 0x09, 0x00}, {0x28, 0x01, 0x09, 0x01}, - {0x02, 0x01, 0x8e, 0x00}, {0x09, 0x01, 0x8e, 0x00}, - {0x17, 0x01, 0x8e, 0x00}, {0x28, 0x01, 0x8e, 0x01} - ], - [ - {0x03, 0x01, 0x09, 0x00}, {0x06, 0x01, 0x09, 0x00}, - {0x0a, 0x01, 0x09, 0x00}, {0x0f, 0x01, 0x09, 0x00}, - {0x18, 0x01, 0x09, 0x00}, {0x1f, 0x01, 0x09, 0x00}, - {0x29, 0x01, 0x09, 0x00}, {0x38, 0x01, 0x09, 0x01}, - {0x03, 0x01, 0x8e, 0x00}, {0x06, 0x01, 0x8e, 0x00}, - {0x0a, 0x01, 0x8e, 0x00}, {0x0f, 0x01, 0x8e, 0x00}, - {0x18, 0x01, 0x8e, 0x00}, {0x1f, 0x01, 0x8e, 0x00}, - {0x29, 0x01, 0x8e, 0x00}, {0x38, 0x01, 0x8e, 0x01} - ], - [ - {0x02, 0x01, 0x90, 0x00}, {0x09, 0x01, 0x90, 0x00}, - {0x17, 0x01, 0x90, 0x00}, {0x28, 0x01, 0x90, 0x01}, - {0x02, 0x01, 0x91, 0x00}, {0x09, 0x01, 0x91, 0x00}, - {0x17, 0x01, 0x91, 0x00}, {0x28, 0x01, 0x91, 0x01}, - {0x02, 0x01, 0x94, 0x00}, {0x09, 0x01, 0x94, 0x00}, - {0x17, 0x01, 0x94, 0x00}, {0x28, 0x01, 0x94, 0x01}, - {0x02, 0x01, 0x9f, 0x00}, {0x09, 0x01, 0x9f, 0x00}, - {0x17, 0x01, 0x9f, 0x00}, {0x28, 0x01, 0x9f, 0x01} - ], - [ - {0x03, 0x01, 0x90, 0x00}, {0x06, 0x01, 0x90, 0x00}, - {0x0a, 0x01, 0x90, 0x00}, {0x0f, 0x01, 0x90, 0x00}, - {0x18, 0x01, 0x90, 0x00}, {0x1f, 0x01, 0x90, 0x00}, - {0x29, 0x01, 0x90, 0x00}, {0x38, 0x01, 0x90, 0x01}, - {0x03, 0x01, 0x91, 0x00}, {0x06, 0x01, 0x91, 0x00}, - {0x0a, 0x01, 0x91, 0x00}, {0x0f, 0x01, 0x91, 0x00}, - {0x18, 0x01, 0x91, 0x00}, {0x1f, 0x01, 0x91, 0x00}, - {0x29, 0x01, 0x91, 0x00}, {0x38, 0x01, 0x91, 0x01} - ], - [ - {0x03, 0x01, 0x94, 0x00}, {0x06, 0x01, 0x94, 0x00}, - {0x0a, 0x01, 0x94, 0x00}, {0x0f, 0x01, 0x94, 0x00}, - {0x18, 0x01, 0x94, 0x00}, {0x1f, 0x01, 0x94, 0x00}, - {0x29, 0x01, 0x94, 0x00}, {0x38, 0x01, 0x94, 0x01}, - {0x03, 0x01, 0x9f, 0x00}, {0x06, 0x01, 0x9f, 0x00}, - {0x0a, 0x01, 0x9f, 0x00}, {0x0f, 0x01, 0x9f, 0x00}, - {0x18, 0x01, 0x9f, 0x00}, {0x1f, 0x01, 0x9f, 0x00}, - {0x29, 0x01, 0x9f, 0x00}, {0x38, 0x01, 0x9f, 0x01} - ], - /* 180 */ - [ - {0x00, 0x01, 0xab, 0x01}, {0x00, 0x01, 0xce, 0x01}, - {0x00, 0x01, 0xd7, 0x01}, {0x00, 0x01, 0xe1, 0x01}, - {0x00, 0x01, 0xec, 0x01}, {0x00, 0x01, 0xed, 0x01}, - {0xbc, 0x00, 0x00, 0x00}, {0xbd, 0x00, 0x00, 0x00}, - {0xc1, 0x00, 0x00, 0x00}, {0xc4, 0x00, 0x00, 0x00}, - {0xc8, 0x00, 0x00, 0x00}, {0xcb, 0x00, 0x00, 0x00}, - {0xd1, 0x00, 0x00, 0x00}, {0xd8, 0x00, 0x00, 0x00}, - {0xe0, 0x00, 0x00, 0x00}, {0xee, 0x00, 0x00, 0x01} - ], - [ - {0x01, 0x01, 0xab, 0x00}, {0x16, 0x01, 0xab, 0x01}, - {0x01, 0x01, 0xce, 0x00}, {0x16, 0x01, 0xce, 0x01}, - {0x01, 0x01, 0xd7, 0x00}, {0x16, 0x01, 0xd7, 0x01}, - {0x01, 0x01, 0xe1, 0x00}, {0x16, 0x01, 0xe1, 0x01}, - {0x01, 0x01, 0xec, 0x00}, {0x16, 0x01, 0xec, 0x01}, - {0x01, 0x01, 0xed, 0x00}, {0x16, 0x01, 0xed, 0x01}, - {0x00, 0x01, 0xc7, 0x01}, {0x00, 0x01, 0xcf, 0x01}, - {0x00, 0x01, 0xea, 0x01}, {0x00, 0x01, 0xeb, 0x01} - ], - [ - {0x02, 0x01, 0xab, 0x00}, {0x09, 0x01, 0xab, 0x00}, - {0x17, 0x01, 0xab, 0x00}, {0x28, 0x01, 0xab, 0x01}, - {0x02, 0x01, 0xce, 0x00}, {0x09, 0x01, 0xce, 0x00}, - {0x17, 0x01, 0xce, 0x00}, {0x28, 0x01, 0xce, 0x01}, - {0x02, 0x01, 0xd7, 0x00}, {0x09, 0x01, 0xd7, 0x00}, - {0x17, 0x01, 0xd7, 0x00}, {0x28, 0x01, 0xd7, 0x01}, - {0x02, 0x01, 0xe1, 0x00}, {0x09, 0x01, 0xe1, 0x00}, - {0x17, 0x01, 0xe1, 0x00}, {0x28, 0x01, 0xe1, 0x01} - ], - [ - {0x03, 0x01, 0xab, 0x00}, {0x06, 0x01, 0xab, 0x00}, - {0x0a, 0x01, 0xab, 0x00}, {0x0f, 0x01, 0xab, 0x00}, - {0x18, 0x01, 0xab, 0x00}, {0x1f, 0x01, 0xab, 0x00}, - {0x29, 0x01, 0xab, 0x00}, {0x38, 0x01, 0xab, 0x01}, - {0x03, 0x01, 0xce, 0x00}, {0x06, 0x01, 0xce, 0x00}, - {0x0a, 0x01, 0xce, 0x00}, {0x0f, 0x01, 0xce, 0x00}, - {0x18, 0x01, 0xce, 0x00}, {0x1f, 0x01, 0xce, 0x00}, - {0x29, 0x01, 0xce, 0x00}, {0x38, 0x01, 0xce, 0x01} - ], - [ - {0x03, 0x01, 0xd7, 0x00}, {0x06, 0x01, 0xd7, 0x00}, - {0x0a, 0x01, 0xd7, 0x00}, {0x0f, 0x01, 0xd7, 0x00}, - {0x18, 0x01, 0xd7, 0x00}, {0x1f, 0x01, 0xd7, 0x00}, - {0x29, 0x01, 0xd7, 0x00}, {0x38, 0x01, 0xd7, 0x01}, - {0x03, 0x01, 0xe1, 0x00}, {0x06, 0x01, 0xe1, 0x00}, - {0x0a, 0x01, 0xe1, 0x00}, {0x0f, 0x01, 0xe1, 0x00}, - {0x18, 0x01, 0xe1, 0x00}, {0x1f, 0x01, 0xe1, 0x00}, - {0x29, 0x01, 0xe1, 0x00}, {0x38, 0x01, 0xe1, 0x01} - ], - /* 185 */ - [ - {0x02, 0x01, 0xec, 0x00}, {0x09, 0x01, 0xec, 0x00}, - {0x17, 0x01, 0xec, 0x00}, {0x28, 0x01, 0xec, 0x01}, - {0x02, 0x01, 0xed, 0x00}, {0x09, 0x01, 0xed, 0x00}, - {0x17, 0x01, 0xed, 0x00}, {0x28, 0x01, 0xed, 0x01}, - {0x01, 0x01, 0xc7, 0x00}, {0x16, 0x01, 0xc7, 0x01}, - {0x01, 0x01, 0xcf, 0x00}, {0x16, 0x01, 0xcf, 0x01}, - {0x01, 0x01, 0xea, 0x00}, {0x16, 0x01, 0xea, 0x01}, - {0x01, 0x01, 0xeb, 0x00}, {0x16, 0x01, 0xeb, 0x01} - ], - [ - {0x03, 0x01, 0xec, 0x00}, {0x06, 0x01, 0xec, 0x00}, - {0x0a, 0x01, 0xec, 0x00}, {0x0f, 0x01, 0xec, 0x00}, - {0x18, 0x01, 0xec, 0x00}, {0x1f, 0x01, 0xec, 0x00}, - {0x29, 0x01, 0xec, 0x00}, {0x38, 0x01, 0xec, 0x01}, - {0x03, 0x01, 0xed, 0x00}, {0x06, 0x01, 0xed, 0x00}, - {0x0a, 0x01, 0xed, 0x00}, {0x0f, 0x01, 0xed, 0x00}, - {0x18, 0x01, 0xed, 0x00}, {0x1f, 0x01, 0xed, 0x00}, - {0x29, 0x01, 0xed, 0x00}, {0x38, 0x01, 0xed, 0x01} - ], - [ - {0x02, 0x01, 0xc7, 0x00}, {0x09, 0x01, 0xc7, 0x00}, - {0x17, 0x01, 0xc7, 0x00}, {0x28, 0x01, 0xc7, 0x01}, - {0x02, 0x01, 0xcf, 0x00}, {0x09, 0x01, 0xcf, 0x00}, - {0x17, 0x01, 0xcf, 0x00}, {0x28, 0x01, 0xcf, 0x01}, - {0x02, 0x01, 0xea, 0x00}, {0x09, 0x01, 0xea, 0x00}, - {0x17, 0x01, 0xea, 0x00}, {0x28, 0x01, 0xea, 0x01}, - {0x02, 0x01, 0xeb, 0x00}, {0x09, 0x01, 0xeb, 0x00}, - {0x17, 0x01, 0xeb, 0x00}, {0x28, 0x01, 0xeb, 0x01} - ], - [ - {0x03, 0x01, 0xc7, 0x00}, {0x06, 0x01, 0xc7, 0x00}, - {0x0a, 0x01, 0xc7, 0x00}, {0x0f, 0x01, 0xc7, 0x00}, - {0x18, 0x01, 0xc7, 0x00}, {0x1f, 0x01, 0xc7, 0x00}, - {0x29, 0x01, 0xc7, 0x00}, {0x38, 0x01, 0xc7, 0x01}, - {0x03, 0x01, 0xcf, 0x00}, {0x06, 0x01, 0xcf, 0x00}, - {0x0a, 0x01, 0xcf, 0x00}, {0x0f, 0x01, 0xcf, 0x00}, - {0x18, 0x01, 0xcf, 0x00}, {0x1f, 0x01, 0xcf, 0x00}, - {0x29, 0x01, 0xcf, 0x00}, {0x38, 0x01, 0xcf, 0x01} - ], - [ - {0x03, 0x01, 0xea, 0x00}, {0x06, 0x01, 0xea, 0x00}, - {0x0a, 0x01, 0xea, 0x00}, {0x0f, 0x01, 0xea, 0x00}, - {0x18, 0x01, 0xea, 0x00}, {0x1f, 0x01, 0xea, 0x00}, - {0x29, 0x01, 0xea, 0x00}, {0x38, 0x01, 0xea, 0x01}, - {0x03, 0x01, 0xeb, 0x00}, {0x06, 0x01, 0xeb, 0x00}, - {0x0a, 0x01, 0xeb, 0x00}, {0x0f, 0x01, 0xeb, 0x00}, - {0x18, 0x01, 0xeb, 0x00}, {0x1f, 0x01, 0xeb, 0x00}, - {0x29, 0x01, 0xeb, 0x00}, {0x38, 0x01, 0xeb, 0x01} - ], - /* 190 */ - [ - {0xc2, 0x00, 0x00, 0x00}, {0xc3, 0x00, 0x00, 0x00}, - {0xc5, 0x00, 0x00, 0x00}, {0xc6, 0x00, 0x00, 0x00}, - {0xc9, 0x00, 0x00, 0x00}, {0xca, 0x00, 0x00, 0x00}, - {0xcc, 0x00, 0x00, 0x00}, {0xcd, 0x00, 0x00, 0x00}, - {0xd2, 0x00, 0x00, 0x00}, {0xd5, 0x00, 0x00, 0x00}, - {0xd9, 0x00, 0x00, 0x00}, {0xdc, 0x00, 0x00, 0x00}, - {0xe1, 0x00, 0x00, 0x00}, {0xe7, 0x00, 0x00, 0x00}, - {0xef, 0x00, 0x00, 0x00}, {0xf6, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0xc0, 0x01}, {0x00, 0x01, 0xc1, 0x01}, - {0x00, 0x01, 0xc8, 0x01}, {0x00, 0x01, 0xc9, 0x01}, - {0x00, 0x01, 0xca, 0x01}, {0x00, 0x01, 0xcd, 0x01}, - {0x00, 0x01, 0xd2, 0x01}, {0x00, 0x01, 0xd5, 0x01}, - {0x00, 0x01, 0xda, 0x01}, {0x00, 0x01, 0xdb, 0x01}, - {0x00, 0x01, 0xee, 0x01}, {0x00, 0x01, 0xf0, 0x01}, - {0x00, 0x01, 0xf2, 0x01}, {0x00, 0x01, 0xf3, 0x01}, - {0x00, 0x01, 0xff, 0x01}, {0xce, 0x00, 0x00, 0x00} - ], - [ - {0x01, 0x01, 0xc0, 0x00}, {0x16, 0x01, 0xc0, 0x01}, - {0x01, 0x01, 0xc1, 0x00}, {0x16, 0x01, 0xc1, 0x01}, - {0x01, 0x01, 0xc8, 0x00}, {0x16, 0x01, 0xc8, 0x01}, - {0x01, 0x01, 0xc9, 0x00}, {0x16, 0x01, 0xc9, 0x01}, - {0x01, 0x01, 0xca, 0x00}, {0x16, 0x01, 0xca, 0x01}, - {0x01, 0x01, 0xcd, 0x00}, {0x16, 0x01, 0xcd, 0x01}, - {0x01, 0x01, 0xd2, 0x00}, {0x16, 0x01, 0xd2, 0x01}, - {0x01, 0x01, 0xd5, 0x00}, {0x16, 0x01, 0xd5, 0x01} - ], - [ - {0x02, 0x01, 0xc0, 0x00}, {0x09, 0x01, 0xc0, 0x00}, - {0x17, 0x01, 0xc0, 0x00}, {0x28, 0x01, 0xc0, 0x01}, - {0x02, 0x01, 0xc1, 0x00}, {0x09, 0x01, 0xc1, 0x00}, - {0x17, 0x01, 0xc1, 0x00}, {0x28, 0x01, 0xc1, 0x01}, - {0x02, 0x01, 0xc8, 0x00}, {0x09, 0x01, 0xc8, 0x00}, - {0x17, 0x01, 0xc8, 0x00}, {0x28, 0x01, 0xc8, 0x01}, - {0x02, 0x01, 0xc9, 0x00}, {0x09, 0x01, 0xc9, 0x00}, - {0x17, 0x01, 0xc9, 0x00}, {0x28, 0x01, 0xc9, 0x01} - ], - [ - {0x03, 0x01, 0xc0, 0x00}, {0x06, 0x01, 0xc0, 0x00}, - {0x0a, 0x01, 0xc0, 0x00}, {0x0f, 0x01, 0xc0, 0x00}, - {0x18, 0x01, 0xc0, 0x00}, {0x1f, 0x01, 0xc0, 0x00}, - {0x29, 0x01, 0xc0, 0x00}, {0x38, 0x01, 0xc0, 0x01}, - {0x03, 0x01, 0xc1, 0x00}, {0x06, 0x01, 0xc1, 0x00}, - {0x0a, 0x01, 0xc1, 0x00}, {0x0f, 0x01, 0xc1, 0x00}, - {0x18, 0x01, 0xc1, 0x00}, {0x1f, 0x01, 0xc1, 0x00}, - {0x29, 0x01, 0xc1, 0x00}, {0x38, 0x01, 0xc1, 0x01} - ], - /* 195 */ - [ - {0x03, 0x01, 0xc8, 0x00}, {0x06, 0x01, 0xc8, 0x00}, - {0x0a, 0x01, 0xc8, 0x00}, {0x0f, 0x01, 0xc8, 0x00}, - {0x18, 0x01, 0xc8, 0x00}, {0x1f, 0x01, 0xc8, 0x00}, - {0x29, 0x01, 0xc8, 0x00}, {0x38, 0x01, 0xc8, 0x01}, - {0x03, 0x01, 0xc9, 0x00}, {0x06, 0x01, 0xc9, 0x00}, - {0x0a, 0x01, 0xc9, 0x00}, {0x0f, 0x01, 0xc9, 0x00}, - {0x18, 0x01, 0xc9, 0x00}, {0x1f, 0x01, 0xc9, 0x00}, - {0x29, 0x01, 0xc9, 0x00}, {0x38, 0x01, 0xc9, 0x01} - ], - [ - {0x02, 0x01, 0xca, 0x00}, {0x09, 0x01, 0xca, 0x00}, - {0x17, 0x01, 0xca, 0x00}, {0x28, 0x01, 0xca, 0x01}, - {0x02, 0x01, 0xcd, 0x00}, {0x09, 0x01, 0xcd, 0x00}, - {0x17, 0x01, 0xcd, 0x00}, {0x28, 0x01, 0xcd, 0x01}, - {0x02, 0x01, 0xd2, 0x00}, {0x09, 0x01, 0xd2, 0x00}, - {0x17, 0x01, 0xd2, 0x00}, {0x28, 0x01, 0xd2, 0x01}, - {0x02, 0x01, 0xd5, 0x00}, {0x09, 0x01, 0xd5, 0x00}, - {0x17, 0x01, 0xd5, 0x00}, {0x28, 0x01, 0xd5, 0x01} - ], - [ - {0x03, 0x01, 0xca, 0x00}, {0x06, 0x01, 0xca, 0x00}, - {0x0a, 0x01, 0xca, 0x00}, {0x0f, 0x01, 0xca, 0x00}, - {0x18, 0x01, 0xca, 0x00}, {0x1f, 0x01, 0xca, 0x00}, - {0x29, 0x01, 0xca, 0x00}, {0x38, 0x01, 0xca, 0x01}, - {0x03, 0x01, 0xcd, 0x00}, {0x06, 0x01, 0xcd, 0x00}, - {0x0a, 0x01, 0xcd, 0x00}, {0x0f, 0x01, 0xcd, 0x00}, - {0x18, 0x01, 0xcd, 0x00}, {0x1f, 0x01, 0xcd, 0x00}, - {0x29, 0x01, 0xcd, 0x00}, {0x38, 0x01, 0xcd, 0x01} - ], - [ - {0x03, 0x01, 0xd2, 0x00}, {0x06, 0x01, 0xd2, 0x00}, - {0x0a, 0x01, 0xd2, 0x00}, {0x0f, 0x01, 0xd2, 0x00}, - {0x18, 0x01, 0xd2, 0x00}, {0x1f, 0x01, 0xd2, 0x00}, - {0x29, 0x01, 0xd2, 0x00}, {0x38, 0x01, 0xd2, 0x01}, - {0x03, 0x01, 0xd5, 0x00}, {0x06, 0x01, 0xd5, 0x00}, - {0x0a, 0x01, 0xd5, 0x00}, {0x0f, 0x01, 0xd5, 0x00}, - {0x18, 0x01, 0xd5, 0x00}, {0x1f, 0x01, 0xd5, 0x00}, - {0x29, 0x01, 0xd5, 0x00}, {0x38, 0x01, 0xd5, 0x01} - ], - [ - {0x01, 0x01, 0xda, 0x00}, {0x16, 0x01, 0xda, 0x01}, - {0x01, 0x01, 0xdb, 0x00}, {0x16, 0x01, 0xdb, 0x01}, - {0x01, 0x01, 0xee, 0x00}, {0x16, 0x01, 0xee, 0x01}, - {0x01, 0x01, 0xf0, 0x00}, {0x16, 0x01, 0xf0, 0x01}, - {0x01, 0x01, 0xf2, 0x00}, {0x16, 0x01, 0xf2, 0x01}, - {0x01, 0x01, 0xf3, 0x00}, {0x16, 0x01, 0xf3, 0x01}, - {0x01, 0x01, 0xff, 0x00}, {0x16, 0x01, 0xff, 0x01}, - {0x00, 0x01, 0xcb, 0x01}, {0x00, 0x01, 0xcc, 0x01} - ], - /* 200 */ - [ - {0x02, 0x01, 0xda, 0x00}, {0x09, 0x01, 0xda, 0x00}, - {0x17, 0x01, 0xda, 0x00}, {0x28, 0x01, 0xda, 0x01}, - {0x02, 0x01, 0xdb, 0x00}, {0x09, 0x01, 0xdb, 0x00}, - {0x17, 0x01, 0xdb, 0x00}, {0x28, 0x01, 0xdb, 0x01}, - {0x02, 0x01, 0xee, 0x00}, {0x09, 0x01, 0xee, 0x00}, - {0x17, 0x01, 0xee, 0x00}, {0x28, 0x01, 0xee, 0x01}, - {0x02, 0x01, 0xf0, 0x00}, {0x09, 0x01, 0xf0, 0x00}, - {0x17, 0x01, 0xf0, 0x00}, {0x28, 0x01, 0xf0, 0x01} - ], - [ - {0x03, 0x01, 0xda, 0x00}, {0x06, 0x01, 0xda, 0x00}, - {0x0a, 0x01, 0xda, 0x00}, {0x0f, 0x01, 0xda, 0x00}, - {0x18, 0x01, 0xda, 0x00}, {0x1f, 0x01, 0xda, 0x00}, - {0x29, 0x01, 0xda, 0x00}, {0x38, 0x01, 0xda, 0x01}, - {0x03, 0x01, 0xdb, 0x00}, {0x06, 0x01, 0xdb, 0x00}, - {0x0a, 0x01, 0xdb, 0x00}, {0x0f, 0x01, 0xdb, 0x00}, - {0x18, 0x01, 0xdb, 0x00}, {0x1f, 0x01, 0xdb, 0x00}, - {0x29, 0x01, 0xdb, 0x00}, {0x38, 0x01, 0xdb, 0x01} - ], - [ - {0x03, 0x01, 0xee, 0x00}, {0x06, 0x01, 0xee, 0x00}, - {0x0a, 0x01, 0xee, 0x00}, {0x0f, 0x01, 0xee, 0x00}, - {0x18, 0x01, 0xee, 0x00}, {0x1f, 0x01, 0xee, 0x00}, - {0x29, 0x01, 0xee, 0x00}, {0x38, 0x01, 0xee, 0x01}, - {0x03, 0x01, 0xf0, 0x00}, {0x06, 0x01, 0xf0, 0x00}, - {0x0a, 0x01, 0xf0, 0x00}, {0x0f, 0x01, 0xf0, 0x00}, - {0x18, 0x01, 0xf0, 0x00}, {0x1f, 0x01, 0xf0, 0x00}, - {0x29, 0x01, 0xf0, 0x00}, {0x38, 0x01, 0xf0, 0x01} - ], - [ - {0x02, 0x01, 0xf2, 0x00}, {0x09, 0x01, 0xf2, 0x00}, - {0x17, 0x01, 0xf2, 0x00}, {0x28, 0x01, 0xf2, 0x01}, - {0x02, 0x01, 0xf3, 0x00}, {0x09, 0x01, 0xf3, 0x00}, - {0x17, 0x01, 0xf3, 0x00}, {0x28, 0x01, 0xf3, 0x01}, - {0x02, 0x01, 0xff, 0x00}, {0x09, 0x01, 0xff, 0x00}, - {0x17, 0x01, 0xff, 0x00}, {0x28, 0x01, 0xff, 0x01}, - {0x01, 0x01, 0xcb, 0x00}, {0x16, 0x01, 0xcb, 0x01}, - {0x01, 0x01, 0xcc, 0x00}, {0x16, 0x01, 0xcc, 0x01} - ], - [ - {0x03, 0x01, 0xf2, 0x00}, {0x06, 0x01, 0xf2, 0x00}, - {0x0a, 0x01, 0xf2, 0x00}, {0x0f, 0x01, 0xf2, 0x00}, - {0x18, 0x01, 0xf2, 0x00}, {0x1f, 0x01, 0xf2, 0x00}, - {0x29, 0x01, 0xf2, 0x00}, {0x38, 0x01, 0xf2, 0x01}, - {0x03, 0x01, 0xf3, 0x00}, {0x06, 0x01, 0xf3, 0x00}, - {0x0a, 0x01, 0xf3, 0x00}, {0x0f, 0x01, 0xf3, 0x00}, - {0x18, 0x01, 0xf3, 0x00}, {0x1f, 0x01, 0xf3, 0x00}, - {0x29, 0x01, 0xf3, 0x00}, {0x38, 0x01, 0xf3, 0x01} - ], - /* 205 */ - [ - {0x03, 0x01, 0xff, 0x00}, {0x06, 0x01, 0xff, 0x00}, - {0x0a, 0x01, 0xff, 0x00}, {0x0f, 0x01, 0xff, 0x00}, - {0x18, 0x01, 0xff, 0x00}, {0x1f, 0x01, 0xff, 0x00}, - {0x29, 0x01, 0xff, 0x00}, {0x38, 0x01, 0xff, 0x01}, - {0x02, 0x01, 0xcb, 0x00}, {0x09, 0x01, 0xcb, 0x00}, - {0x17, 0x01, 0xcb, 0x00}, {0x28, 0x01, 0xcb, 0x01}, - {0x02, 0x01, 0xcc, 0x00}, {0x09, 0x01, 0xcc, 0x00}, - {0x17, 0x01, 0xcc, 0x00}, {0x28, 0x01, 0xcc, 0x01} - ], - [ - {0x03, 0x01, 0xcb, 0x00}, {0x06, 0x01, 0xcb, 0x00}, - {0x0a, 0x01, 0xcb, 0x00}, {0x0f, 0x01, 0xcb, 0x00}, - {0x18, 0x01, 0xcb, 0x00}, {0x1f, 0x01, 0xcb, 0x00}, - {0x29, 0x01, 0xcb, 0x00}, {0x38, 0x01, 0xcb, 0x01}, - {0x03, 0x01, 0xcc, 0x00}, {0x06, 0x01, 0xcc, 0x00}, - {0x0a, 0x01, 0xcc, 0x00}, {0x0f, 0x01, 0xcc, 0x00}, - {0x18, 0x01, 0xcc, 0x00}, {0x1f, 0x01, 0xcc, 0x00}, - {0x29, 0x01, 0xcc, 0x00}, {0x38, 0x01, 0xcc, 0x01} - ], - [ - {0xd3, 0x00, 0x00, 0x00}, {0xd4, 0x00, 0x00, 0x00}, - {0xd6, 0x00, 0x00, 0x00}, {0xd7, 0x00, 0x00, 0x00}, - {0xda, 0x00, 0x00, 0x00}, {0xdb, 0x00, 0x00, 0x00}, - {0xdd, 0x00, 0x00, 0x00}, {0xde, 0x00, 0x00, 0x00}, - {0xe2, 0x00, 0x00, 0x00}, {0xe4, 0x00, 0x00, 0x00}, - {0xe8, 0x00, 0x00, 0x00}, {0xeb, 0x00, 0x00, 0x00}, - {0xf0, 0x00, 0x00, 0x00}, {0xf3, 0x00, 0x00, 0x00}, - {0xf7, 0x00, 0x00, 0x00}, {0xfa, 0x00, 0x00, 0x01} - ], - [ - {0x00, 0x01, 0xd3, 0x01}, {0x00, 0x01, 0xd4, 0x01}, - {0x00, 0x01, 0xd6, 0x01}, {0x00, 0x01, 0xdd, 0x01}, - {0x00, 0x01, 0xde, 0x01}, {0x00, 0x01, 0xdf, 0x01}, - {0x00, 0x01, 0xf1, 0x01}, {0x00, 0x01, 0xf4, 0x01}, - {0x00, 0x01, 0xf5, 0x01}, {0x00, 0x01, 0xf6, 0x01}, - {0x00, 0x01, 0xf7, 0x01}, {0x00, 0x01, 0xf8, 0x01}, - {0x00, 0x01, 0xfa, 0x01}, {0x00, 0x01, 0xfb, 0x01}, - {0x00, 0x01, 0xfc, 0x01}, {0x00, 0x01, 0xfd, 0x01} - ], - [ - {0x01, 0x01, 0xd3, 0x00}, {0x16, 0x01, 0xd3, 0x01}, - {0x01, 0x01, 0xd4, 0x00}, {0x16, 0x01, 0xd4, 0x01}, - {0x01, 0x01, 0xd6, 0x00}, {0x16, 0x01, 0xd6, 0x01}, - {0x01, 0x01, 0xdd, 0x00}, {0x16, 0x01, 0xdd, 0x01}, - {0x01, 0x01, 0xde, 0x00}, {0x16, 0x01, 0xde, 0x01}, - {0x01, 0x01, 0xdf, 0x00}, {0x16, 0x01, 0xdf, 0x01}, - {0x01, 0x01, 0xf1, 0x00}, {0x16, 0x01, 0xf1, 0x01}, - {0x01, 0x01, 0xf4, 0x00}, {0x16, 0x01, 0xf4, 0x01} - ], - /* 210 */ - [ - {0x02, 0x01, 0xd3, 0x00}, {0x09, 0x01, 0xd3, 0x00}, - {0x17, 0x01, 0xd3, 0x00}, {0x28, 0x01, 0xd3, 0x01}, - {0x02, 0x01, 0xd4, 0x00}, {0x09, 0x01, 0xd4, 0x00}, - {0x17, 0x01, 0xd4, 0x00}, {0x28, 0x01, 0xd4, 0x01}, - {0x02, 0x01, 0xd6, 0x00}, {0x09, 0x01, 0xd6, 0x00}, - {0x17, 0x01, 0xd6, 0x00}, {0x28, 0x01, 0xd6, 0x01}, - {0x02, 0x01, 0xdd, 0x00}, {0x09, 0x01, 0xdd, 0x00}, - {0x17, 0x01, 0xdd, 0x00}, {0x28, 0x01, 0xdd, 0x01} - ], - [ - {0x03, 0x01, 0xd3, 0x00}, {0x06, 0x01, 0xd3, 0x00}, - {0x0a, 0x01, 0xd3, 0x00}, {0x0f, 0x01, 0xd3, 0x00}, - {0x18, 0x01, 0xd3, 0x00}, {0x1f, 0x01, 0xd3, 0x00}, - {0x29, 0x01, 0xd3, 0x00}, {0x38, 0x01, 0xd3, 0x01}, - {0x03, 0x01, 0xd4, 0x00}, {0x06, 0x01, 0xd4, 0x00}, - {0x0a, 0x01, 0xd4, 0x00}, {0x0f, 0x01, 0xd4, 0x00}, - {0x18, 0x01, 0xd4, 0x00}, {0x1f, 0x01, 0xd4, 0x00}, - {0x29, 0x01, 0xd4, 0x00}, {0x38, 0x01, 0xd4, 0x01} - ], - [ - {0x03, 0x01, 0xd6, 0x00}, {0x06, 0x01, 0xd6, 0x00}, - {0x0a, 0x01, 0xd6, 0x00}, {0x0f, 0x01, 0xd6, 0x00}, - {0x18, 0x01, 0xd6, 0x00}, {0x1f, 0x01, 0xd6, 0x00}, - {0x29, 0x01, 0xd6, 0x00}, {0x38, 0x01, 0xd6, 0x01}, - {0x03, 0x01, 0xdd, 0x00}, {0x06, 0x01, 0xdd, 0x00}, - {0x0a, 0x01, 0xdd, 0x00}, {0x0f, 0x01, 0xdd, 0x00}, - {0x18, 0x01, 0xdd, 0x00}, {0x1f, 0x01, 0xdd, 0x00}, - {0x29, 0x01, 0xdd, 0x00}, {0x38, 0x01, 0xdd, 0x01} - ], - [ - {0x02, 0x01, 0xde, 0x00}, {0x09, 0x01, 0xde, 0x00}, - {0x17, 0x01, 0xde, 0x00}, {0x28, 0x01, 0xde, 0x01}, - {0x02, 0x01, 0xdf, 0x00}, {0x09, 0x01, 0xdf, 0x00}, - {0x17, 0x01, 0xdf, 0x00}, {0x28, 0x01, 0xdf, 0x01}, - {0x02, 0x01, 0xf1, 0x00}, {0x09, 0x01, 0xf1, 0x00}, - {0x17, 0x01, 0xf1, 0x00}, {0x28, 0x01, 0xf1, 0x01}, - {0x02, 0x01, 0xf4, 0x00}, {0x09, 0x01, 0xf4, 0x00}, - {0x17, 0x01, 0xf4, 0x00}, {0x28, 0x01, 0xf4, 0x01} - ], - [ - {0x03, 0x01, 0xde, 0x00}, {0x06, 0x01, 0xde, 0x00}, - {0x0a, 0x01, 0xde, 0x00}, {0x0f, 0x01, 0xde, 0x00}, - {0x18, 0x01, 0xde, 0x00}, {0x1f, 0x01, 0xde, 0x00}, - {0x29, 0x01, 0xde, 0x00}, {0x38, 0x01, 0xde, 0x01}, - {0x03, 0x01, 0xdf, 0x00}, {0x06, 0x01, 0xdf, 0x00}, - {0x0a, 0x01, 0xdf, 0x00}, {0x0f, 0x01, 0xdf, 0x00}, - {0x18, 0x01, 0xdf, 0x00}, {0x1f, 0x01, 0xdf, 0x00}, - {0x29, 0x01, 0xdf, 0x00}, {0x38, 0x01, 0xdf, 0x01} - ], - /* 215 */ - [ - {0x03, 0x01, 0xf1, 0x00}, {0x06, 0x01, 0xf1, 0x00}, - {0x0a, 0x01, 0xf1, 0x00}, {0x0f, 0x01, 0xf1, 0x00}, - {0x18, 0x01, 0xf1, 0x00}, {0x1f, 0x01, 0xf1, 0x00}, - {0x29, 0x01, 0xf1, 0x00}, {0x38, 0x01, 0xf1, 0x01}, - {0x03, 0x01, 0xf4, 0x00}, {0x06, 0x01, 0xf4, 0x00}, - {0x0a, 0x01, 0xf4, 0x00}, {0x0f, 0x01, 0xf4, 0x00}, - {0x18, 0x01, 0xf4, 0x00}, {0x1f, 0x01, 0xf4, 0x00}, - {0x29, 0x01, 0xf4, 0x00}, {0x38, 0x01, 0xf4, 0x01} - ], - [ - {0x01, 0x01, 0xf5, 0x00}, {0x16, 0x01, 0xf5, 0x01}, - {0x01, 0x01, 0xf6, 0x00}, {0x16, 0x01, 0xf6, 0x01}, - {0x01, 0x01, 0xf7, 0x00}, {0x16, 0x01, 0xf7, 0x01}, - {0x01, 0x01, 0xf8, 0x00}, {0x16, 0x01, 0xf8, 0x01}, - {0x01, 0x01, 0xfa, 0x00}, {0x16, 0x01, 0xfa, 0x01}, - {0x01, 0x01, 0xfb, 0x00}, {0x16, 0x01, 0xfb, 0x01}, - {0x01, 0x01, 0xfc, 0x00}, {0x16, 0x01, 0xfc, 0x01}, - {0x01, 0x01, 0xfd, 0x00}, {0x16, 0x01, 0xfd, 0x01} - ], - [ - {0x02, 0x01, 0xf5, 0x00}, {0x09, 0x01, 0xf5, 0x00}, - {0x17, 0x01, 0xf5, 0x00}, {0x28, 0x01, 0xf5, 0x01}, - {0x02, 0x01, 0xf6, 0x00}, {0x09, 0x01, 0xf6, 0x00}, - {0x17, 0x01, 0xf6, 0x00}, {0x28, 0x01, 0xf6, 0x01}, - {0x02, 0x01, 0xf7, 0x00}, {0x09, 0x01, 0xf7, 0x00}, - {0x17, 0x01, 0xf7, 0x00}, {0x28, 0x01, 0xf7, 0x01}, - {0x02, 0x01, 0xf8, 0x00}, {0x09, 0x01, 0xf8, 0x00}, - {0x17, 0x01, 0xf8, 0x00}, {0x28, 0x01, 0xf8, 0x01} - ], - [ - {0x03, 0x01, 0xf5, 0x00}, {0x06, 0x01, 0xf5, 0x00}, - {0x0a, 0x01, 0xf5, 0x00}, {0x0f, 0x01, 0xf5, 0x00}, - {0x18, 0x01, 0xf5, 0x00}, {0x1f, 0x01, 0xf5, 0x00}, - {0x29, 0x01, 0xf5, 0x00}, {0x38, 0x01, 0xf5, 0x01}, - {0x03, 0x01, 0xf6, 0x00}, {0x06, 0x01, 0xf6, 0x00}, - {0x0a, 0x01, 0xf6, 0x00}, {0x0f, 0x01, 0xf6, 0x00}, - {0x18, 0x01, 0xf6, 0x00}, {0x1f, 0x01, 0xf6, 0x00}, - {0x29, 0x01, 0xf6, 0x00}, {0x38, 0x01, 0xf6, 0x01} - ], - [ - {0x03, 0x01, 0xf7, 0x00}, {0x06, 0x01, 0xf7, 0x00}, - {0x0a, 0x01, 0xf7, 0x00}, {0x0f, 0x01, 0xf7, 0x00}, - {0x18, 0x01, 0xf7, 0x00}, {0x1f, 0x01, 0xf7, 0x00}, - {0x29, 0x01, 0xf7, 0x00}, {0x38, 0x01, 0xf7, 0x01}, - {0x03, 0x01, 0xf8, 0x00}, {0x06, 0x01, 0xf8, 0x00}, - {0x0a, 0x01, 0xf8, 0x00}, {0x0f, 0x01, 0xf8, 0x00}, - {0x18, 0x01, 0xf8, 0x00}, {0x1f, 0x01, 0xf8, 0x00}, - {0x29, 0x01, 0xf8, 0x00}, {0x38, 0x01, 0xf8, 0x01} - ], - /* 220 */ - [ - {0x02, 0x01, 0xfa, 0x00}, {0x09, 0x01, 0xfa, 0x00}, - {0x17, 0x01, 0xfa, 0x00}, {0x28, 0x01, 0xfa, 0x01}, - {0x02, 0x01, 0xfb, 0x00}, {0x09, 0x01, 0xfb, 0x00}, - {0x17, 0x01, 0xfb, 0x00}, {0x28, 0x01, 0xfb, 0x01}, - {0x02, 0x01, 0xfc, 0x00}, {0x09, 0x01, 0xfc, 0x00}, - {0x17, 0x01, 0xfc, 0x00}, {0x28, 0x01, 0xfc, 0x01}, - {0x02, 0x01, 0xfd, 0x00}, {0x09, 0x01, 0xfd, 0x00}, - {0x17, 0x01, 0xfd, 0x00}, {0x28, 0x01, 0xfd, 0x01} - ], - [ - {0x03, 0x01, 0xfa, 0x00}, {0x06, 0x01, 0xfa, 0x00}, - {0x0a, 0x01, 0xfa, 0x00}, {0x0f, 0x01, 0xfa, 0x00}, - {0x18, 0x01, 0xfa, 0x00}, {0x1f, 0x01, 0xfa, 0x00}, - {0x29, 0x01, 0xfa, 0x00}, {0x38, 0x01, 0xfa, 0x01}, - {0x03, 0x01, 0xfb, 0x00}, {0x06, 0x01, 0xfb, 0x00}, - {0x0a, 0x01, 0xfb, 0x00}, {0x0f, 0x01, 0xfb, 0x00}, - {0x18, 0x01, 0xfb, 0x00}, {0x1f, 0x01, 0xfb, 0x00}, - {0x29, 0x01, 0xfb, 0x00}, {0x38, 0x01, 0xfb, 0x01} - ], - [ - {0x03, 0x01, 0xfc, 0x00}, {0x06, 0x01, 0xfc, 0x00}, - {0x0a, 0x01, 0xfc, 0x00}, {0x0f, 0x01, 0xfc, 0x00}, - {0x18, 0x01, 0xfc, 0x00}, {0x1f, 0x01, 0xfc, 0x00}, - {0x29, 0x01, 0xfc, 0x00}, {0x38, 0x01, 0xfc, 0x01}, - {0x03, 0x01, 0xfd, 0x00}, {0x06, 0x01, 0xfd, 0x00}, - {0x0a, 0x01, 0xfd, 0x00}, {0x0f, 0x01, 0xfd, 0x00}, - {0x18, 0x01, 0xfd, 0x00}, {0x1f, 0x01, 0xfd, 0x00}, - {0x29, 0x01, 0xfd, 0x00}, {0x38, 0x01, 0xfd, 0x01} - ], - [ - {0x00, 0x01, 0xfe, 0x01}, {0xe3, 0x00, 0x00, 0x00}, - {0xe5, 0x00, 0x00, 0x00}, {0xe6, 0x00, 0x00, 0x00}, - {0xe9, 0x00, 0x00, 0x00}, {0xea, 0x00, 0x00, 0x00}, - {0xec, 0x00, 0x00, 0x00}, {0xed, 0x00, 0x00, 0x00}, - {0xf1, 0x00, 0x00, 0x00}, {0xf2, 0x00, 0x00, 0x00}, - {0xf4, 0x00, 0x00, 0x00}, {0xf5, 0x00, 0x00, 0x00}, - {0xf8, 0x00, 0x00, 0x00}, {0xf9, 0x00, 0x00, 0x00}, - {0xfb, 0x00, 0x00, 0x00}, {0xfc, 0x00, 0x00, 0x01} - ], - [ - {0x01, 0x01, 0xfe, 0x00}, {0x16, 0x01, 0xfe, 0x01}, - {0x00, 0x01, 0x02, 0x01}, {0x00, 0x01, 0x03, 0x01}, - {0x00, 0x01, 0x04, 0x01}, {0x00, 0x01, 0x05, 0x01}, - {0x00, 0x01, 0x06, 0x01}, {0x00, 0x01, 0x07, 0x01}, - {0x00, 0x01, 0x08, 0x01}, {0x00, 0x01, 0x0b, 0x01}, - {0x00, 0x01, 0x0c, 0x01}, {0x00, 0x01, 0x0e, 0x01}, - {0x00, 0x01, 0x0f, 0x01}, {0x00, 0x01, 0x10, 0x01}, - {0x00, 0x01, 0x11, 0x01}, {0x00, 0x01, 0x12, 0x01} - ], - /* 225 */ - [ - {0x02, 0x01, 0xfe, 0x00}, {0x09, 0x01, 0xfe, 0x00}, - {0x17, 0x01, 0xfe, 0x00}, {0x28, 0x01, 0xfe, 0x01}, - {0x01, 0x01, 0x02, 0x00}, {0x16, 0x01, 0x02, 0x01}, - {0x01, 0x01, 0x03, 0x00}, {0x16, 0x01, 0x03, 0x01}, - {0x01, 0x01, 0x04, 0x00}, {0x16, 0x01, 0x04, 0x01}, - {0x01, 0x01, 0x05, 0x00}, {0x16, 0x01, 0x05, 0x01}, - {0x01, 0x01, 0x06, 0x00}, {0x16, 0x01, 0x06, 0x01}, - {0x01, 0x01, 0x07, 0x00}, {0x16, 0x01, 0x07, 0x01} - ], - [ - {0x03, 0x01, 0xfe, 0x00}, {0x06, 0x01, 0xfe, 0x00}, - {0x0a, 0x01, 0xfe, 0x00}, {0x0f, 0x01, 0xfe, 0x00}, - {0x18, 0x01, 0xfe, 0x00}, {0x1f, 0x01, 0xfe, 0x00}, - {0x29, 0x01, 0xfe, 0x00}, {0x38, 0x01, 0xfe, 0x01}, - {0x02, 0x01, 0x02, 0x00}, {0x09, 0x01, 0x02, 0x00}, - {0x17, 0x01, 0x02, 0x00}, {0x28, 0x01, 0x02, 0x01}, - {0x02, 0x01, 0x03, 0x00}, {0x09, 0x01, 0x03, 0x00}, - {0x17, 0x01, 0x03, 0x00}, {0x28, 0x01, 0x03, 0x01} - ], - [ - {0x03, 0x01, 0x02, 0x00}, {0x06, 0x01, 0x02, 0x00}, - {0x0a, 0x01, 0x02, 0x00}, {0x0f, 0x01, 0x02, 0x00}, - {0x18, 0x01, 0x02, 0x00}, {0x1f, 0x01, 0x02, 0x00}, - {0x29, 0x01, 0x02, 0x00}, {0x38, 0x01, 0x02, 0x01}, - {0x03, 0x01, 0x03, 0x00}, {0x06, 0x01, 0x03, 0x00}, - {0x0a, 0x01, 0x03, 0x00}, {0x0f, 0x01, 0x03, 0x00}, - {0x18, 0x01, 0x03, 0x00}, {0x1f, 0x01, 0x03, 0x00}, - {0x29, 0x01, 0x03, 0x00}, {0x38, 0x01, 0x03, 0x01} - ], - [ - {0x02, 0x01, 0x04, 0x00}, {0x09, 0x01, 0x04, 0x00}, - {0x17, 0x01, 0x04, 0x00}, {0x28, 0x01, 0x04, 0x01}, - {0x02, 0x01, 0x05, 0x00}, {0x09, 0x01, 0x05, 0x00}, - {0x17, 0x01, 0x05, 0x00}, {0x28, 0x01, 0x05, 0x01}, - {0x02, 0x01, 0x06, 0x00}, {0x09, 0x01, 0x06, 0x00}, - {0x17, 0x01, 0x06, 0x00}, {0x28, 0x01, 0x06, 0x01}, - {0x02, 0x01, 0x07, 0x00}, {0x09, 0x01, 0x07, 0x00}, - {0x17, 0x01, 0x07, 0x00}, {0x28, 0x01, 0x07, 0x01} - ], - [ - {0x03, 0x01, 0x04, 0x00}, {0x06, 0x01, 0x04, 0x00}, - {0x0a, 0x01, 0x04, 0x00}, {0x0f, 0x01, 0x04, 0x00}, - {0x18, 0x01, 0x04, 0x00}, {0x1f, 0x01, 0x04, 0x00}, - {0x29, 0x01, 0x04, 0x00}, {0x38, 0x01, 0x04, 0x01}, - {0x03, 0x01, 0x05, 0x00}, {0x06, 0x01, 0x05, 0x00}, - {0x0a, 0x01, 0x05, 0x00}, {0x0f, 0x01, 0x05, 0x00}, - {0x18, 0x01, 0x05, 0x00}, {0x1f, 0x01, 0x05, 0x00}, - {0x29, 0x01, 0x05, 0x00}, {0x38, 0x01, 0x05, 0x01} - ], - /* 230 */ - [ - {0x03, 0x01, 0x06, 0x00}, {0x06, 0x01, 0x06, 0x00}, - {0x0a, 0x01, 0x06, 0x00}, {0x0f, 0x01, 0x06, 0x00}, - {0x18, 0x01, 0x06, 0x00}, {0x1f, 0x01, 0x06, 0x00}, - {0x29, 0x01, 0x06, 0x00}, {0x38, 0x01, 0x06, 0x01}, - {0x03, 0x01, 0x07, 0x00}, {0x06, 0x01, 0x07, 0x00}, - {0x0a, 0x01, 0x07, 0x00}, {0x0f, 0x01, 0x07, 0x00}, - {0x18, 0x01, 0x07, 0x00}, {0x1f, 0x01, 0x07, 0x00}, - {0x29, 0x01, 0x07, 0x00}, {0x38, 0x01, 0x07, 0x01} - ], - [ - {0x01, 0x01, 0x08, 0x00}, {0x16, 0x01, 0x08, 0x01}, - {0x01, 0x01, 0x0b, 0x00}, {0x16, 0x01, 0x0b, 0x01}, - {0x01, 0x01, 0x0c, 0x00}, {0x16, 0x01, 0x0c, 0x01}, - {0x01, 0x01, 0x0e, 0x00}, {0x16, 0x01, 0x0e, 0x01}, - {0x01, 0x01, 0x0f, 0x00}, {0x16, 0x01, 0x0f, 0x01}, - {0x01, 0x01, 0x10, 0x00}, {0x16, 0x01, 0x10, 0x01}, - {0x01, 0x01, 0x11, 0x00}, {0x16, 0x01, 0x11, 0x01}, - {0x01, 0x01, 0x12, 0x00}, {0x16, 0x01, 0x12, 0x01} - ], - [ - {0x02, 0x01, 0x08, 0x00}, {0x09, 0x01, 0x08, 0x00}, - {0x17, 0x01, 0x08, 0x00}, {0x28, 0x01, 0x08, 0x01}, - {0x02, 0x01, 0x0b, 0x00}, {0x09, 0x01, 0x0b, 0x00}, - {0x17, 0x01, 0x0b, 0x00}, {0x28, 0x01, 0x0b, 0x01}, - {0x02, 0x01, 0x0c, 0x00}, {0x09, 0x01, 0x0c, 0x00}, - {0x17, 0x01, 0x0c, 0x00}, {0x28, 0x01, 0x0c, 0x01}, - {0x02, 0x01, 0x0e, 0x00}, {0x09, 0x01, 0x0e, 0x00}, - {0x17, 0x01, 0x0e, 0x00}, {0x28, 0x01, 0x0e, 0x01} - ], - [ - {0x03, 0x01, 0x08, 0x00}, {0x06, 0x01, 0x08, 0x00}, - {0x0a, 0x01, 0x08, 0x00}, {0x0f, 0x01, 0x08, 0x00}, - {0x18, 0x01, 0x08, 0x00}, {0x1f, 0x01, 0x08, 0x00}, - {0x29, 0x01, 0x08, 0x00}, {0x38, 0x01, 0x08, 0x01}, - {0x03, 0x01, 0x0b, 0x00}, {0x06, 0x01, 0x0b, 0x00}, - {0x0a, 0x01, 0x0b, 0x00}, {0x0f, 0x01, 0x0b, 0x00}, - {0x18, 0x01, 0x0b, 0x00}, {0x1f, 0x01, 0x0b, 0x00}, - {0x29, 0x01, 0x0b, 0x00}, {0x38, 0x01, 0x0b, 0x01} - ], - [ - {0x03, 0x01, 0x0c, 0x00}, {0x06, 0x01, 0x0c, 0x00}, - {0x0a, 0x01, 0x0c, 0x00}, {0x0f, 0x01, 0x0c, 0x00}, - {0x18, 0x01, 0x0c, 0x00}, {0x1f, 0x01, 0x0c, 0x00}, - {0x29, 0x01, 0x0c, 0x00}, {0x38, 0x01, 0x0c, 0x01}, - {0x03, 0x01, 0x0e, 0x00}, {0x06, 0x01, 0x0e, 0x00}, - {0x0a, 0x01, 0x0e, 0x00}, {0x0f, 0x01, 0x0e, 0x00}, - {0x18, 0x01, 0x0e, 0x00}, {0x1f, 0x01, 0x0e, 0x00}, - {0x29, 0x01, 0x0e, 0x00}, {0x38, 0x01, 0x0e, 0x01} - ], - /* 235 */ - [ - {0x02, 0x01, 0x0f, 0x00}, {0x09, 0x01, 0x0f, 0x00}, - {0x17, 0x01, 0x0f, 0x00}, {0x28, 0x01, 0x0f, 0x01}, - {0x02, 0x01, 0x10, 0x00}, {0x09, 0x01, 0x10, 0x00}, - {0x17, 0x01, 0x10, 0x00}, {0x28, 0x01, 0x10, 0x01}, - {0x02, 0x01, 0x11, 0x00}, {0x09, 0x01, 0x11, 0x00}, - {0x17, 0x01, 0x11, 0x00}, {0x28, 0x01, 0x11, 0x01}, - {0x02, 0x01, 0x12, 0x00}, {0x09, 0x01, 0x12, 0x00}, - {0x17, 0x01, 0x12, 0x00}, {0x28, 0x01, 0x12, 0x01} - ], - [ - {0x03, 0x01, 0x0f, 0x00}, {0x06, 0x01, 0x0f, 0x00}, - {0x0a, 0x01, 0x0f, 0x00}, {0x0f, 0x01, 0x0f, 0x00}, - {0x18, 0x01, 0x0f, 0x00}, {0x1f, 0x01, 0x0f, 0x00}, - {0x29, 0x01, 0x0f, 0x00}, {0x38, 0x01, 0x0f, 0x01}, - {0x03, 0x01, 0x10, 0x00}, {0x06, 0x01, 0x10, 0x00}, - {0x0a, 0x01, 0x10, 0x00}, {0x0f, 0x01, 0x10, 0x00}, - {0x18, 0x01, 0x10, 0x00}, {0x1f, 0x01, 0x10, 0x00}, - {0x29, 0x01, 0x10, 0x00}, {0x38, 0x01, 0x10, 0x01} - ], - [ - {0x03, 0x01, 0x11, 0x00}, {0x06, 0x01, 0x11, 0x00}, - {0x0a, 0x01, 0x11, 0x00}, {0x0f, 0x01, 0x11, 0x00}, - {0x18, 0x01, 0x11, 0x00}, {0x1f, 0x01, 0x11, 0x00}, - {0x29, 0x01, 0x11, 0x00}, {0x38, 0x01, 0x11, 0x01}, - {0x03, 0x01, 0x12, 0x00}, {0x06, 0x01, 0x12, 0x00}, - {0x0a, 0x01, 0x12, 0x00}, {0x0f, 0x01, 0x12, 0x00}, - {0x18, 0x01, 0x12, 0x00}, {0x1f, 0x01, 0x12, 0x00}, - {0x29, 0x01, 0x12, 0x00}, {0x38, 0x01, 0x12, 0x01} - ], - [ - {0x00, 0x01, 0x13, 0x01}, {0x00, 0x01, 0x14, 0x01}, - {0x00, 0x01, 0x15, 0x01}, {0x00, 0x01, 0x17, 0x01}, - {0x00, 0x01, 0x18, 0x01}, {0x00, 0x01, 0x19, 0x01}, - {0x00, 0x01, 0x1a, 0x01}, {0x00, 0x01, 0x1b, 0x01}, - {0x00, 0x01, 0x1c, 0x01}, {0x00, 0x01, 0x1d, 0x01}, - {0x00, 0x01, 0x1e, 0x01}, {0x00, 0x01, 0x1f, 0x01}, - {0x00, 0x01, 0x7f, 0x01}, {0x00, 0x01, 0xdc, 0x01}, - {0x00, 0x01, 0xf9, 0x01}, {0xfd, 0x00, 0x00, 0x01} - ], - [ - {0x01, 0x01, 0x13, 0x00}, {0x16, 0x01, 0x13, 0x01}, - {0x01, 0x01, 0x14, 0x00}, {0x16, 0x01, 0x14, 0x01}, - {0x01, 0x01, 0x15, 0x00}, {0x16, 0x01, 0x15, 0x01}, - {0x01, 0x01, 0x17, 0x00}, {0x16, 0x01, 0x17, 0x01}, - {0x01, 0x01, 0x18, 0x00}, {0x16, 0x01, 0x18, 0x01}, - {0x01, 0x01, 0x19, 0x00}, {0x16, 0x01, 0x19, 0x01}, - {0x01, 0x01, 0x1a, 0x00}, {0x16, 0x01, 0x1a, 0x01}, - {0x01, 0x01, 0x1b, 0x00}, {0x16, 0x01, 0x1b, 0x01} - ], - /* 240 */ - [ - {0x02, 0x01, 0x13, 0x00}, {0x09, 0x01, 0x13, 0x00}, - {0x17, 0x01, 0x13, 0x00}, {0x28, 0x01, 0x13, 0x01}, - {0x02, 0x01, 0x14, 0x00}, {0x09, 0x01, 0x14, 0x00}, - {0x17, 0x01, 0x14, 0x00}, {0x28, 0x01, 0x14, 0x01}, - {0x02, 0x01, 0x15, 0x00}, {0x09, 0x01, 0x15, 0x00}, - {0x17, 0x01, 0x15, 0x00}, {0x28, 0x01, 0x15, 0x01}, - {0x02, 0x01, 0x17, 0x00}, {0x09, 0x01, 0x17, 0x00}, - {0x17, 0x01, 0x17, 0x00}, {0x28, 0x01, 0x17, 0x01} - ], - [ - {0x03, 0x01, 0x13, 0x00}, {0x06, 0x01, 0x13, 0x00}, - {0x0a, 0x01, 0x13, 0x00}, {0x0f, 0x01, 0x13, 0x00}, - {0x18, 0x01, 0x13, 0x00}, {0x1f, 0x01, 0x13, 0x00}, - {0x29, 0x01, 0x13, 0x00}, {0x38, 0x01, 0x13, 0x01}, - {0x03, 0x01, 0x14, 0x00}, {0x06, 0x01, 0x14, 0x00}, - {0x0a, 0x01, 0x14, 0x00}, {0x0f, 0x01, 0x14, 0x00}, - {0x18, 0x01, 0x14, 0x00}, {0x1f, 0x01, 0x14, 0x00}, - {0x29, 0x01, 0x14, 0x00}, {0x38, 0x01, 0x14, 0x01} - ], - [ - {0x03, 0x01, 0x15, 0x00}, {0x06, 0x01, 0x15, 0x00}, - {0x0a, 0x01, 0x15, 0x00}, {0x0f, 0x01, 0x15, 0x00}, - {0x18, 0x01, 0x15, 0x00}, {0x1f, 0x01, 0x15, 0x00}, - {0x29, 0x01, 0x15, 0x00}, {0x38, 0x01, 0x15, 0x01}, - {0x03, 0x01, 0x17, 0x00}, {0x06, 0x01, 0x17, 0x00}, - {0x0a, 0x01, 0x17, 0x00}, {0x0f, 0x01, 0x17, 0x00}, - {0x18, 0x01, 0x17, 0x00}, {0x1f, 0x01, 0x17, 0x00}, - {0x29, 0x01, 0x17, 0x00}, {0x38, 0x01, 0x17, 0x01} - ], - [ - {0x02, 0x01, 0x18, 0x00}, {0x09, 0x01, 0x18, 0x00}, - {0x17, 0x01, 0x18, 0x00}, {0x28, 0x01, 0x18, 0x01}, - {0x02, 0x01, 0x19, 0x00}, {0x09, 0x01, 0x19, 0x00}, - {0x17, 0x01, 0x19, 0x00}, {0x28, 0x01, 0x19, 0x01}, - {0x02, 0x01, 0x1a, 0x00}, {0x09, 0x01, 0x1a, 0x00}, - {0x17, 0x01, 0x1a, 0x00}, {0x28, 0x01, 0x1a, 0x01}, - {0x02, 0x01, 0x1b, 0x00}, {0x09, 0x01, 0x1b, 0x00}, - {0x17, 0x01, 0x1b, 0x00}, {0x28, 0x01, 0x1b, 0x01} - ], - [ - {0x03, 0x01, 0x18, 0x00}, {0x06, 0x01, 0x18, 0x00}, - {0x0a, 0x01, 0x18, 0x00}, {0x0f, 0x01, 0x18, 0x00}, - {0x18, 0x01, 0x18, 0x00}, {0x1f, 0x01, 0x18, 0x00}, - {0x29, 0x01, 0x18, 0x00}, {0x38, 0x01, 0x18, 0x01}, - {0x03, 0x01, 0x19, 0x00}, {0x06, 0x01, 0x19, 0x00}, - {0x0a, 0x01, 0x19, 0x00}, {0x0f, 0x01, 0x19, 0x00}, - {0x18, 0x01, 0x19, 0x00}, {0x1f, 0x01, 0x19, 0x00}, - {0x29, 0x01, 0x19, 0x00}, {0x38, 0x01, 0x19, 0x01} - ], - /* 245 */ - [ - {0x03, 0x01, 0x1a, 0x00}, {0x06, 0x01, 0x1a, 0x00}, - {0x0a, 0x01, 0x1a, 0x00}, {0x0f, 0x01, 0x1a, 0x00}, - {0x18, 0x01, 0x1a, 0x00}, {0x1f, 0x01, 0x1a, 0x00}, - {0x29, 0x01, 0x1a, 0x00}, {0x38, 0x01, 0x1a, 0x01}, - {0x03, 0x01, 0x1b, 0x00}, {0x06, 0x01, 0x1b, 0x00}, - {0x0a, 0x01, 0x1b, 0x00}, {0x0f, 0x01, 0x1b, 0x00}, - {0x18, 0x01, 0x1b, 0x00}, {0x1f, 0x01, 0x1b, 0x00}, - {0x29, 0x01, 0x1b, 0x00}, {0x38, 0x01, 0x1b, 0x01} - ], - [ - {0x01, 0x01, 0x1c, 0x00}, {0x16, 0x01, 0x1c, 0x01}, - {0x01, 0x01, 0x1d, 0x00}, {0x16, 0x01, 0x1d, 0x01}, - {0x01, 0x01, 0x1e, 0x00}, {0x16, 0x01, 0x1e, 0x01}, - {0x01, 0x01, 0x1f, 0x00}, {0x16, 0x01, 0x1f, 0x01}, - {0x01, 0x01, 0x7f, 0x00}, {0x16, 0x01, 0x7f, 0x01}, - {0x01, 0x01, 0xdc, 0x00}, {0x16, 0x01, 0xdc, 0x01}, - {0x01, 0x01, 0xf9, 0x00}, {0x16, 0x01, 0xf9, 0x01}, - {0xfe, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x01} - ], - [ - {0x02, 0x01, 0x1c, 0x00}, {0x09, 0x01, 0x1c, 0x00}, - {0x17, 0x01, 0x1c, 0x00}, {0x28, 0x01, 0x1c, 0x01}, - {0x02, 0x01, 0x1d, 0x00}, {0x09, 0x01, 0x1d, 0x00}, - {0x17, 0x01, 0x1d, 0x00}, {0x28, 0x01, 0x1d, 0x01}, - {0x02, 0x01, 0x1e, 0x00}, {0x09, 0x01, 0x1e, 0x00}, - {0x17, 0x01, 0x1e, 0x00}, {0x28, 0x01, 0x1e, 0x01}, - {0x02, 0x01, 0x1f, 0x00}, {0x09, 0x01, 0x1f, 0x00}, - {0x17, 0x01, 0x1f, 0x00}, {0x28, 0x01, 0x1f, 0x01} - ], - [ - {0x03, 0x01, 0x1c, 0x00}, {0x06, 0x01, 0x1c, 0x00}, - {0x0a, 0x01, 0x1c, 0x00}, {0x0f, 0x01, 0x1c, 0x00}, - {0x18, 0x01, 0x1c, 0x00}, {0x1f, 0x01, 0x1c, 0x00}, - {0x29, 0x01, 0x1c, 0x00}, {0x38, 0x01, 0x1c, 0x01}, - {0x03, 0x01, 0x1d, 0x00}, {0x06, 0x01, 0x1d, 0x00}, - {0x0a, 0x01, 0x1d, 0x00}, {0x0f, 0x01, 0x1d, 0x00}, - {0x18, 0x01, 0x1d, 0x00}, {0x1f, 0x01, 0x1d, 0x00}, - {0x29, 0x01, 0x1d, 0x00}, {0x38, 0x01, 0x1d, 0x01} - ], - [ - {0x03, 0x01, 0x1e, 0x00}, {0x06, 0x01, 0x1e, 0x00}, - {0x0a, 0x01, 0x1e, 0x00}, {0x0f, 0x01, 0x1e, 0x00}, - {0x18, 0x01, 0x1e, 0x00}, {0x1f, 0x01, 0x1e, 0x00}, - {0x29, 0x01, 0x1e, 0x00}, {0x38, 0x01, 0x1e, 0x01}, - {0x03, 0x01, 0x1f, 0x00}, {0x06, 0x01, 0x1f, 0x00}, - {0x0a, 0x01, 0x1f, 0x00}, {0x0f, 0x01, 0x1f, 0x00}, - {0x18, 0x01, 0x1f, 0x00}, {0x1f, 0x01, 0x1f, 0x00}, - {0x29, 0x01, 0x1f, 0x00}, {0x38, 0x01, 0x1f, 0x01} - ], - /* 250 */ - [ - {0x02, 0x01, 0x7f, 0x00}, {0x09, 0x01, 0x7f, 0x00}, - {0x17, 0x01, 0x7f, 0x00}, {0x28, 0x01, 0x7f, 0x01}, - {0x02, 0x01, 0xdc, 0x00}, {0x09, 0x01, 0xdc, 0x00}, - {0x17, 0x01, 0xdc, 0x00}, {0x28, 0x01, 0xdc, 0x01}, - {0x02, 0x01, 0xf9, 0x00}, {0x09, 0x01, 0xf9, 0x00}, - {0x17, 0x01, 0xf9, 0x00}, {0x28, 0x01, 0xf9, 0x01}, - {0x00, 0x01, 0x0a, 0x01}, {0x00, 0x01, 0x0d, 0x01}, - {0x00, 0x01, 0x16, 0x01}, {0xfa, 0x00, 0x00, 0x00} - ], - [ - {0x03, 0x01, 0x7f, 0x00}, {0x06, 0x01, 0x7f, 0x00}, - {0x0a, 0x01, 0x7f, 0x00}, {0x0f, 0x01, 0x7f, 0x00}, - {0x18, 0x01, 0x7f, 0x00}, {0x1f, 0x01, 0x7f, 0x00}, - {0x29, 0x01, 0x7f, 0x00}, {0x38, 0x01, 0x7f, 0x01}, - {0x03, 0x01, 0xdc, 0x00}, {0x06, 0x01, 0xdc, 0x00}, - {0x0a, 0x01, 0xdc, 0x00}, {0x0f, 0x01, 0xdc, 0x00}, - {0x18, 0x01, 0xdc, 0x00}, {0x1f, 0x01, 0xdc, 0x00}, - {0x29, 0x01, 0xdc, 0x00}, {0x38, 0x01, 0xdc, 0x01} - ], - [ - {0x03, 0x01, 0xf9, 0x00}, {0x06, 0x01, 0xf9, 0x00}, - {0x0a, 0x01, 0xf9, 0x00}, {0x0f, 0x01, 0xf9, 0x00}, - {0x18, 0x01, 0xf9, 0x00}, {0x1f, 0x01, 0xf9, 0x00}, - {0x29, 0x01, 0xf9, 0x00}, {0x38, 0x01, 0xf9, 0x01}, - {0x01, 0x01, 0x0a, 0x00}, {0x16, 0x01, 0x0a, 0x01}, - {0x01, 0x01, 0x0d, 0x00}, {0x16, 0x01, 0x0d, 0x01}, - {0x01, 0x01, 0x16, 0x00}, {0x16, 0x01, 0x16, 0x01}, - {0xfc, 0x00, 0x00, 0x00}, {0xfc, 0x00, 0x00, 0x00} - ], - [ - {0x02, 0x01, 0x0a, 0x00}, {0x09, 0x01, 0x0a, 0x00}, - {0x17, 0x01, 0x0a, 0x00}, {0x28, 0x01, 0x0a, 0x01}, - {0x02, 0x01, 0x0d, 0x00}, {0x09, 0x01, 0x0d, 0x00}, - {0x17, 0x01, 0x0d, 0x00}, {0x28, 0x01, 0x0d, 0x01}, - {0x02, 0x01, 0x16, 0x00}, {0x09, 0x01, 0x16, 0x00}, - {0x17, 0x01, 0x16, 0x00}, {0x28, 0x01, 0x16, 0x01}, - {0xfd, 0x00, 0x00, 0x00}, {0xfd, 0x00, 0x00, 0x00}, - {0xfd, 0x00, 0x00, 0x00}, {0xfd, 0x00, 0x00, 0x00} - ], - [ - {0x03, 0x01, 0x0a, 0x00}, {0x06, 0x01, 0x0a, 0x00}, - {0x0a, 0x01, 0x0a, 0x00}, {0x0f, 0x01, 0x0a, 0x00}, - {0x18, 0x01, 0x0a, 0x00}, {0x1f, 0x01, 0x0a, 0x00}, - {0x29, 0x01, 0x0a, 0x00}, {0x38, 0x01, 0x0a, 0x01}, - {0x03, 0x01, 0x0d, 0x00}, {0x06, 0x01, 0x0d, 0x00}, - {0x0a, 0x01, 0x0d, 0x00}, {0x0f, 0x01, 0x0d, 0x00}, - {0x18, 0x01, 0x0d, 0x00}, {0x1f, 0x01, 0x0d, 0x00}, - {0x29, 0x01, 0x0d, 0x00}, {0x38, 0x01, 0x0d, 0x01} - ], - /* 255 */ - [ - {0x03, 0x01, 0x16, 0x00}, {0x06, 0x01, 0x16, 0x00}, - {0x0a, 0x01, 0x16, 0x00}, {0x0f, 0x01, 0x16, 0x00}, - {0x18, 0x01, 0x16, 0x00}, {0x1f, 0x01, 0x16, 0x00}, - {0x29, 0x01, 0x16, 0x00}, {0x38, 0x01, 0x16, 0x01}, - {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, - {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, - {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, - {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00} - ] -]; diff --git a/source/vibe/http/internal/http2/hpack/tables.d b/source/vibe/http/internal/http2/hpack/tables.d deleted file mode 100644 index 0948c9a..0000000 --- a/source/vibe/http/internal/http2/hpack/tables.d +++ /dev/null @@ -1,410 +0,0 @@ -//module vibe.http.internal.hpack.tables; -module vibe.http.internal.http2.hpack.tables; - -import vibe.http.internal.http2.hpack.exception; - -import vibe.http.status; -import vibe.http.common; -import vibe.core.log; -import vibe.core.sync; -import vibe.internal.array : FixedRingBuffer; - -import std.variant; -import std.traits; -import std.meta; -import std.range; -import std.algorithm.iteration; -import std.math : log10; -import taggedalgebraic; - - -alias HTTP2SettingValue = uint; - -// 4096 octets -enum DEFAULT_DYNAMIC_TABLE_SIZE = 4096; - -/* - 2.3. Indexing Tables - HPACK uses two tables for associating header fields to indexes. The - static table (see Section 2.3.1) is predefined and contains common - header fields (most of them with an empty value). The dynamic table - (see Section 2.3.2) is dynamic and can be used by the encoder to - index header fields repeated in the encoded header lists. - These two tables are combined into a single address space for - defining index values (see Section 2.3.3). - 2.3.1. Static Table - The static table consists of a predefined static list of header - fields. Its entries are defined in Appendix A. - 2.3.2. Dynamic Table - The dynamic table consists of a list of header fields maintained in - first-in, first-out order. The first and newest entry in a dynamic - table is at the lowest index, and the oldest entry of a dynamic tabl - is at the highest index. - The dynamic table is initially empty. Entries are added as each - header block is decompressed. - The dynamic table is initially empty. Entries are added as each - header block is decompressed. - The dynamic table can contain duplicate entries (i.e., entries with - the same name and same value). Therefore, duplicate entries MUST NOT - be treated as an error by a decoder. - The encoder decides how to update the dynamic table and as such can - control how much memory is used by the dynamic table. To limit the - memory requirements of the decoder, the dynamic table size is - strictly bounded (see Section 4.2). - The decoder updates the dynamic table during the processing of a list - of header field representations (see Section 3.2). -*/ - -// wraps a header field = name:value -struct HTTP2HeaderTableField { - private union HeaderValue { - string str; - string[] strarr; - HTTPStatus status; - HTTPMethod method; - } - - string name; - TaggedAlgebraic!HeaderValue value; - bool index = true; - bool neverIndex = false; - - // initializers - static foreach(t; __traits(allMembers, HeaderValue)) { - mixin("this(string n, " ~ - typeof(__traits(getMember, HeaderValue, t)).stringof ~ - " v) @safe { name = n; value = v; }"); - } - - this(R)(R t) @safe - if(is(ElementType!R : string)) - { - assert(t.length == 2, "Invalid range for HTTP2HeaderTableField initializer"); - this(t[0], t[1]); - } -} - -// fixed as per HPACK RFC -immutable size_t STATIC_TABLE_SIZE = 61; - -/** static table to index most common headers - * fixed size, fixed order of entries (read only) - * cannot be updated while decoding a header block - */ -static immutable HTTP2HeaderTableField[STATIC_TABLE_SIZE+1] StaticTable; - -shared static this() { - StaticTable = [ - HTTP2HeaderTableField("",""), // 0 index is not allowed - HTTP2HeaderTableField(":authority", ""), - HTTP2HeaderTableField(":method", HTTPMethod.GET), - HTTP2HeaderTableField(":method", HTTPMethod.POST), - HTTP2HeaderTableField(":path", "/"), - HTTP2HeaderTableField(":path", "/index.html"), - HTTP2HeaderTableField(":scheme", "http"), - HTTP2HeaderTableField(":scheme", "https"), - HTTP2HeaderTableField(":status", HTTPStatus.ok), // 200 - HTTP2HeaderTableField(":status", HTTPStatus.noContent), // 204 - HTTP2HeaderTableField(":status", HTTPStatus.partialContent), // 206 - HTTP2HeaderTableField(":status", HTTPStatus.notModified), // 304 - HTTP2HeaderTableField(":status", HTTPStatus.badRequest), // 400 - HTTP2HeaderTableField(":status", HTTPStatus.notFound), // 404 - HTTP2HeaderTableField(":status", HTTPStatus.internalServerError), // 500 - HTTP2HeaderTableField("accept-charset", ""), - HTTP2HeaderTableField("accept-encoding", ["gzip", "deflate"]), - HTTP2HeaderTableField("accept-language", ""), - HTTP2HeaderTableField("accept-ranges", ""), - HTTP2HeaderTableField("accept", ""), - HTTP2HeaderTableField("access-control-allow-origin", ""), - HTTP2HeaderTableField("age", ""), - HTTP2HeaderTableField("allow", ""), - HTTP2HeaderTableField("authorization", ""), - HTTP2HeaderTableField("cache-control", ""), - HTTP2HeaderTableField("content-disposition", ""), - HTTP2HeaderTableField("content-encoding", ""), - HTTP2HeaderTableField("content-language", ""), - HTTP2HeaderTableField("content-length", ""), - HTTP2HeaderTableField("content-location", ""), - HTTP2HeaderTableField("content-range", ""), - HTTP2HeaderTableField("content-type", ""), - HTTP2HeaderTableField("cookie", ""), - HTTP2HeaderTableField("date", ""), - HTTP2HeaderTableField("etag", ""), - HTTP2HeaderTableField("expect", ""), - HTTP2HeaderTableField("expires", ""), - HTTP2HeaderTableField("from", ""), - HTTP2HeaderTableField("host", ""), - HTTP2HeaderTableField("if-match", ""), - HTTP2HeaderTableField("if-modified-since", ""), - HTTP2HeaderTableField("if-none-match", ""), - HTTP2HeaderTableField("if-range", ""), - HTTP2HeaderTableField("if-unmodified-since", ""), - HTTP2HeaderTableField("last-modified", ""), - HTTP2HeaderTableField("link", ""), - HTTP2HeaderTableField("location", ""), - HTTP2HeaderTableField("max-forwards", ""), - HTTP2HeaderTableField("proxy-authenticate", ""), - HTTP2HeaderTableField("proxy-authorization", ""), - HTTP2HeaderTableField("range", ""), - HTTP2HeaderTableField("referer", ""), - HTTP2HeaderTableField("refresh", ""), - HTTP2HeaderTableField("retry-after", ""), - HTTP2HeaderTableField("server", ""), - HTTP2HeaderTableField("set-cookie", ""), - HTTP2HeaderTableField("strict-transport-security", ""), - HTTP2HeaderTableField("transfer-encoding", ""), - HTTP2HeaderTableField("user-agent", ""), - HTTP2HeaderTableField("vary", ""), - HTTP2HeaderTableField("via", ""), - HTTP2HeaderTableField("www-authenticate", "") - ]; -} - -private ref immutable(HTTP2HeaderTableField) getStaticTableEntry(size_t key) @safe @nogc -{ - assert(key > 0 && key < StaticTable.length, "Invalid static table index"); - return StaticTable[key]; -} - -// compute size of an entry as per RFC -HTTP2SettingValue computeEntrySize(HTTP2HeaderTableField f) @safe -{ - alias k = HTTP2HeaderTableField.value.Kind; - HTTP2SettingValue ret = cast(HTTP2SettingValue)f.name.length + 32; - - final switch (f.value.kind) { - case k.str: ret += f.value.get!string.length; break; - case k.strarr: ret += f.value.get!(string[]).map!(s => s.length).sum(); break; - case k.status: ret += cast(size_t)log10(cast(int)f.value.get!HTTPStatus) + 1; break; - case k.method: ret += httpMethodString(f.value.get!HTTPMethod).length; break; - } - return ret; -} - -private struct DynamicTable { - private { - // default table is 4096 octs. / n. octets of an empty HTTP2HeaderTableField struct (32) - FixedRingBuffer!(HTTP2HeaderTableField, DEFAULT_DYNAMIC_TABLE_SIZE/HTTP2HeaderTableField.sizeof, false) m_table; - - // extra table is a circular buffer, initially empty, used when - // maxsize > DEFAULT_DYNAMIC_TABLE_SIZE - FixedRingBuffer!HTTP2HeaderTableField m_extraTable; - - // as defined in SETTINGS_HEADER_TABLE_SIZE - HTTP2SettingValue m_maxsize; - - // current size - size_t m_size = 0; - - // last index (table index starts from 1) - size_t m_index = 0; - - // extra table index (starts from 0) - size_t m_extraIndex = 0; - } - - this(HTTP2SettingValue ms) @trusted - { - m_maxsize = ms; - - if(ms > DEFAULT_DYNAMIC_TABLE_SIZE) { - m_extraTable.capacity = (ms - DEFAULT_DYNAMIC_TABLE_SIZE)/HTTP2HeaderTableField.sizeof; - } - } - - @property void dispose() { m_extraTable.dispose(); } - - // number of elements inside dynamic table - @property size_t size() @safe @nogc { return m_size; } - - @property size_t index() @safe @nogc { return m_index; } - - HTTP2HeaderTableField opIndex(size_t idx) @safe @nogc - { - size_t totIndex = m_index + m_extraIndex; - assert(idx > 0 && idx <= totIndex, "Invalid table index"); - if(idx > m_index && idx < totIndex) return m_extraTable[idx-m_index]; - else return m_table[idx-1]; - } - - // insert at the head - void insert(HTTP2HeaderTableField header) @safe - { - auto nsize = computeEntrySize(header); - // ensure that the new entry does not exceed table capacity - while(m_size + nsize > m_maxsize) { - //logDebug("Maximum header table size exceeded"); // requires gc - remove(); - } - - // insert - if(m_size + nsize > DEFAULT_DYNAMIC_TABLE_SIZE) { - m_extraTable.put(header); - m_extraIndex++; - } else { - m_table.put(header); - m_index++; - } - - m_size += nsize; - } - - // evict an entry - void remove() @safe - { - enforceHPACK(!m_table.empty, "Cannot remove element from empty table"); - - if(m_extraIndex > 0) { - m_size -= computeEntrySize(m_extraTable.back); - m_extraTable.popFront(); - m_extraIndex--; - } else { - m_size -= computeEntrySize(m_table.back); - m_table.popFront(); - m_index--; - } - } - - /** new size should be lower than the max set one - * after size is successfully changed, an ACK has to be sent - * multiple changes between two header fields are possible - * if multiple changes occour, only the smallest maximum size - * requested has to be acknowledged - */ - void updateSize(HTTP2SettingValue sz) @safe @nogc - { - m_maxsize = sz; - } -} - -unittest { - // static table - auto a = getStaticTableEntry(1); - static assert(is(typeof(a) == immutable(HTTP2HeaderTableField))); - assert(a.name == ":authority"); - assert(getStaticTableEntry(2).name == ":method" && getStaticTableEntry(2).value == HTTPMethod.GET); - - DynamicTable dt = DynamicTable(DEFAULT_DYNAMIC_TABLE_SIZE+2048); - assert(dt.size == 0); - assert(dt.index == 0); - - // dynamic table - import std.algorithm.comparison : equal; - - auto h = HTTP2HeaderTableField("test", "testval"); - dt.insert(h); - assert(dt.size > 0); - assert(dt.index == 1); - assert(dt[dt.index].name == "test"); - - dt.remove(); - assert(dt.size == 0); - assert(dt.index == 0); -} - -/** provides an unified address space through operator overloading - * this is the only interface that will be used for the two tables - */ -struct IndexingTable { - private { - DynamicTable m_dynamic; - RecursiveTaskMutex m_lock; - } - - // requires the maximum size for the dynamic table - this(HTTP2SettingValue ms) @trusted - { - m_dynamic = DynamicTable(ms); - m_lock = new RecursiveTaskMutex; - } - - ~this() - { - m_dynamic.dispose(); - } - - @property size_t size() @safe @nogc { return STATIC_TABLE_SIZE + m_dynamic.index + 1; } - - @property bool empty() @safe @nogc { return m_dynamic.size == 0; } - - @property HTTP2HeaderTableField front() @safe { return this[0]; } - - @property void popFront() @safe - { - assert(!empty, "Cannot call popFront on an empty dynamic table"); - m_lock.performLocked!({ - m_dynamic.remove(); - }); - } - - // element retrieval - HTTP2HeaderTableField opIndex(size_t idx) @safe - { - enforceHPACK(idx > 0 && idx < size(), "Invalid HPACK table index"); - - if (idx < STATIC_TABLE_SIZE+1) return getStaticTableEntry(idx); - else return m_dynamic[m_dynamic.index - (idx - STATIC_TABLE_SIZE) + 1]; - } - - // dollar == size - // +1 to mantain consistency with the dollar operator - size_t opDollar() @safe @nogc - { - return size(); - } - - // assignment can only be done on the dynamic table - void insert(HTTP2HeaderTableField hf) @safe - { - m_lock.performLocked!({ - m_dynamic.insert(hf); - }); - } - - // update max dynamic table size - void updateSize(HTTP2SettingValue sz) @safe - { - m_lock.performLocked!({ - m_dynamic.updateSize(sz); - }); - } -} - -unittest { - // indexing table - IndexingTable table = IndexingTable(DEFAULT_DYNAMIC_TABLE_SIZE); - assert(table[2].name == ":method" && table[2].value == HTTPMethod.GET); - - // assignment - auto h = HTTP2HeaderTableField("test", "testval"); - table.insert(h); - assert(table.size == STATIC_TABLE_SIZE + 2); - assert(table[STATIC_TABLE_SIZE+1].name == "test"); - - auto h2 = HTTP2HeaderTableField("test2", "testval2"); - table.insert(h2); - assert(table.size == STATIC_TABLE_SIZE + 3); - assert(table[STATIC_TABLE_SIZE+1].name == "test2"); - - // dollar - auto h3 = HTTP2HeaderTableField("test3", "testval3"); - table.insert(h3); - assert(table.size == STATIC_TABLE_SIZE + 4); - assert(table[$-1].name == "test"); - assert(table[$-2].name == "test2"); - assert(table[STATIC_TABLE_SIZE+1].name == "test3"); - - // test removal on full table - - HTTP2SettingValue hts = computeEntrySize(h); // only one header - IndexingTable t2 = IndexingTable(hts); - t2.insert(h); - t2.insert(h); - assert(t2.size == STATIC_TABLE_SIZE + 2); - assert(t2[STATIC_TABLE_SIZE + 1].name == "test"); - assert(t2[$ - 1].name == "test"); - - auto h4 = HTTP2HeaderTableField("",""); - hts = computeEntrySize(h4); // entry size of an empty field is 32 octets - assert(hts == 32); -} diff --git a/source/vibe/http/internal/http2/hpack/util.d b/source/vibe/http/internal/http2/hpack/util.d deleted file mode 100644 index 883d338..0000000 --- a/source/vibe/http/internal/http2/hpack/util.d +++ /dev/null @@ -1,14 +0,0 @@ -module vibe.http.internal.http2.hpack.util; - -import std.range; - -// decode ubyte as integer representation according to prefix -size_t toInteger(ubyte bbuf, uint prefix) @safe @nogc -{ - assert(prefix < 8, "Prefix must be at most an octet long"); - - bbuf = bbuf & ((1 << (8 - prefix)) - 1); - assert(bbuf >= 0, "Invalid decoded integer"); - - return bbuf; -} diff --git a/source/vibe/http/internal/http2/http2.d b/source/vibe/http/internal/http2/http2.d deleted file mode 100644 index b21b00d..0000000 --- a/source/vibe/http/internal/http2/http2.d +++ /dev/null @@ -1,963 +0,0 @@ -module vibe.http.internal.http2.http2; - -import vibe.http.internal.http2.error; -import vibe.http.internal.http2.multiplexing; -import vibe.http.internal.http2.frame; -import vibe.http.internal.http2.settings; -import vibe.http.internal.http2.exchange; -import vibe.http.internal.http2.hpack.tables; -import vibe.http.internal.http2.hpack.hpack; -import vibe.http.internal.http2.hpack.exception; -import vibe.http.server; - -import vibe.core.log; -import vibe.core.net; -import vibe.core.core; -import vibe.core.stream; -import vibe.stream.tls; -import vibe.internal.array; -import vibe.internal.allocator; -import vibe.internal.utilallocator : RegionListAllocator; -import vibe.internal.freelistref; -import vibe.internal.interfaceproxy; - -import std.range; -import std.base64; -import std.traits; -import std.bitmanip; // read from ubyte (decoding) -import std.typecons; -import std.conv : to; -import std.exception : enforce; -import std.algorithm : canFind; // alpn callback -import std.algorithm.iteration; -import std.variant : Algebraic; - -/* - 3.2. Starting HTTP/2 for "http" URIs - - A client that makes a request for an "http" URI without prior - knowledge about support for HTTP/2 on the next hop uses the HTTP - Upgrade mechanism (Section 6.7 of [RFC7230]). The client does so by - making an HTTP/1.1 request that includes an Upgrade header field with - the "h2c" token. Such an HTTP/1.1 request MUST include exactly one - HTTP2-Settings (Section 3.2.1) header field. - - For example: - - GET / HTTP/1.1 - Host: server.example.com - Connection: Upgrade, HTTP2-Settings - Upgrade: h2c - HTTP2-Settings:test\n
"); - assert(compile!":htmlescapetest\n
"); - assert(compile!":htmlescape !{\"test\n
"); + assert(compile!":htmlescapetest\n
"); + assert(compile!":htmlescape !{\"