├── .gitignore
├── .vscode
└── settings.json
├── Pipfile
├── Pipfile.lock
├── README.md
├── index.html
├── index.js
├── quic_connection_sequence.jpg
├── quic_transport_server.py
├── sequence.drawio
└── setup.cfg
/.gitignore:
--------------------------------------------------------------------------------
1 | .venv
2 | certificate.key
3 | certificate.pem
4 | *.secret
5 | .DS_Store
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.pythonPath": ".venv/bin/python",
3 | "editor.formatOnSave": true,
4 | "python.linting.pycodestyleEnabled": true,
5 | "python.linting.pylintEnabled": true,
6 | "python.formatting.provider": "black",
7 | "notebook.kernelProviderAssociations": []
8 | }
9 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | name = "pypi"
3 | url = "https://pypi.org/simple"
4 | verify_ssl = true
5 |
6 | [dev-packages]
7 | pycodestyle = "*"
8 | black = "*"
9 | flake8 = "*"
10 | cryptography = ">=3.2"
11 |
12 | [packages]
13 | aioquic = "*"
14 |
15 | [requires]
16 | python_version = "3.8"
17 |
18 | [pipenv]
19 | allow_prereleases = true
20 |
--------------------------------------------------------------------------------
/Pipfile.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "hash": {
4 | "sha256": "f01d3c613f9790b31c669c2399c59e1089e5b4f130a7cc199217da8a21c66b68"
5 | },
6 | "pipfile-spec": 6,
7 | "requires": {
8 | "python_version": "3.8"
9 | },
10 | "sources": [
11 | {
12 | "name": "pypi",
13 | "url": "https://pypi.org/simple",
14 | "verify_ssl": true
15 | }
16 | ]
17 | },
18 | "default": {
19 | "aioquic": {
20 | "hashes": [
21 | "sha256:0a59cb078596087175b05929401645d49b0e0a687bc79bac236d9a7a73874b65",
22 | "sha256:1cbdc4ff1160ff82b3b1722e62a138c0fff41557449320768476af14d5b1eac3",
23 | "sha256:2cf057ea1af7639754e006fb98911b81b5d059f41f112b84557ec9492b22fec3",
24 | "sha256:2d603eefc960d0dee531e0e8d63b7c376816fab4beb7931fec24667641903899",
25 | "sha256:2ed04fa08d2d843166c264a90096a4fc61a75e26cc4198a6e7e9956d068c20b0",
26 | "sha256:2f66d52fb56f7b82b645231a957484dde379d626266c82d59d6db97bb31dd53a",
27 | "sha256:33e7ab651b77f7961b5521627aaa50c950e7da902102121deaf343e19ff9c60b",
28 | "sha256:4d826a7f63eefd625f26c767dd2e369b74e25dc1cb7b03edb73f67c27ccd6ff6",
29 | "sha256:637a25b7fd56084de89ccf34c905de29cd285b6a6679dcca7f52a7fef54a839d",
30 | "sha256:65cac12342aee15e8bd56cc8fccf9fe6dd05745383b68f39c7de4c6884a73a53",
31 | "sha256:6e024ce011d7400525814ec31ee83c9b29e4b26c243d8f3ad002fe391730d87c",
32 | "sha256:71e8fcbc7e210a19fb690aa31563ed97fbb2f8050904938697f4cd66f82d94c2",
33 | "sha256:7701db87ec94e11c9fb62e109886963072e2316667543f1c65ae1bed7319b1eb",
34 | "sha256:81200673a5219df55b29a7a6df5a2b4a430ab88154af7536e434d3b495d257c5",
35 | "sha256:866fe2540684e0b9515fc6ca72dd0f8e8994a5bae9f1a08ad2ea0db59a6b3143",
36 | "sha256:8cb2c06f0b12a84db0a05269d9ae912cc9a1284021a893f71de37d06367597a4",
37 | "sha256:95474e05759aa08a0f9e10d094c2c9fffd3344e30b02ae70600ccc753c3ecce9",
38 | "sha256:9be8e5a0f3772e184d35ad9c2e86d9c1dbd2b05c9e9875e2e2baf4dd0fd1fe1e",
39 | "sha256:ad7a870d27af0ea8a1709ef57fe1a346d01681e17d7d357b614a9375224f33d7",
40 | "sha256:aff622def5208e1d0dc986e92e3f39ec7c9381c6e834bd42eef2d426f280d30b",
41 | "sha256:b5cbb0433dcd301947f2d2d87e1cd1875fa458fa0f187436ff3cf3bf01d9e656",
42 | "sha256:c55798a741947b18d2d77de77c54de8963f92cba561afb89b175274dd8758784",
43 | "sha256:c73131f3a7c26bc93d10b07fdc5cb1db3d6293ee9e000c0908c44b7c0e7e6026",
44 | "sha256:ddb95d79b53a442dca36db8e56bc89d0e4f6835175e8c1439b5fad32e61d1e3d",
45 | "sha256:ea83c04b5a4898a6fbc6d7616cd92fc276d3cef487fe987e7482e466175b0195",
46 | "sha256:ed24fa120282eb9698c42e6afea9bbf68d11dddcf034e1a653d0427b29d120d0",
47 | "sha256:f045efcfc669e3e02af42aac60e46c4ed3a054b2694ae3c23c123c052dc2490e"
48 | ],
49 | "index": "pypi",
50 | "version": "==0.9.7"
51 | },
52 | "certifi": {
53 | "hashes": [
54 | "sha256:1f422849db327d534e3d0c5f02a263458c3955ec0aae4ff09b95f195c59f4edd",
55 | "sha256:f05def092c44fbf25834a51509ef6e631dc19765ab8a57b4e7ab85531f0a9cf4"
56 | ],
57 | "version": "==2020.11.8"
58 | },
59 | "cffi": {
60 | "hashes": [
61 | "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e",
62 | "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d",
63 | "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a",
64 | "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec",
65 | "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362",
66 | "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668",
67 | "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c",
68 | "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b",
69 | "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06",
70 | "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698",
71 | "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2",
72 | "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c",
73 | "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7",
74 | "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009",
75 | "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03",
76 | "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b",
77 | "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909",
78 | "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53",
79 | "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
80 | "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
81 | "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
82 | "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
83 | "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
84 | "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
85 | "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
86 | "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
87 | "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
88 | "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
89 | "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
90 | "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
91 | "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375",
92 | "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b",
93 | "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b",
94 | "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"
95 | ],
96 | "version": "==1.14.4"
97 | },
98 | "cryptography": {
99 | "hashes": [
100 | "sha256:07ca431b788249af92764e3be9a488aa1d39a0bc3be313d826bbec690417e538",
101 | "sha256:13b88a0bd044b4eae1ef40e265d006e34dbcde0c2f1e15eb9896501b2d8f6c6f",
102 | "sha256:32434673d8505b42c0de4de86da8c1620651abd24afe91ae0335597683ed1b77",
103 | "sha256:3cd75a683b15576cfc822c7c5742b3276e50b21a06672dc3a800a2d5da4ecd1b",
104 | "sha256:4e7268a0ca14536fecfdf2b00297d4e407da904718658c1ff1961c713f90fd33",
105 | "sha256:545a8550782dda68f8cdc75a6e3bf252017aa8f75f19f5a9ca940772fc0cb56e",
106 | "sha256:55d0b896631412b6f0c7de56e12eb3e261ac347fbaa5d5e705291a9016e5f8cb",
107 | "sha256:5849d59358547bf789ee7e0d7a9036b2d29e9a4ddf1ce5e06bb45634f995c53e",
108 | "sha256:6dc59630ecce8c1f558277ceb212c751d6730bd12c80ea96b4ac65637c4f55e7",
109 | "sha256:7117319b44ed1842c617d0a452383a5a052ec6aa726dfbaffa8b94c910444297",
110 | "sha256:75e8e6684cf0034f6bf2a97095cb95f81537b12b36a8fedf06e73050bb171c2d",
111 | "sha256:7b8d9d8d3a9bd240f453342981f765346c87ade811519f98664519696f8e6ab7",
112 | "sha256:a035a10686532b0587d58a606004aa20ad895c60c4d029afa245802347fab57b",
113 | "sha256:a4e27ed0b2504195f855b52052eadcc9795c59909c9d84314c5408687f933fc7",
114 | "sha256:a733671100cd26d816eed39507e585c156e4498293a907029969234e5e634bc4",
115 | "sha256:a75f306a16d9f9afebfbedc41c8c2351d8e61e818ba6b4c40815e2b5740bb6b8",
116 | "sha256:bd717aa029217b8ef94a7d21632a3bb5a4e7218a4513d2521c2a2fd63011e98b",
117 | "sha256:d25cecbac20713a7c3bc544372d42d8eafa89799f492a43b79e1dfd650484851",
118 | "sha256:d26a2557d8f9122f9bf445fc7034242f4375bd4e95ecda007667540270965b13",
119 | "sha256:d3545829ab42a66b84a9aaabf216a4dce7f16dbc76eb69be5c302ed6b8f4a29b",
120 | "sha256:d3d5e10be0cf2a12214ddee45c6bd203dab435e3d83b4560c03066eda600bfe3",
121 | "sha256:efe15aca4f64f3a7ea0c09c87826490e50ed166ce67368a68f315ea0807a20df"
122 | ],
123 | "version": "==3.2.1"
124 | },
125 | "pycparser": {
126 | "hashes": [
127 | "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
128 | "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
129 | ],
130 | "version": "==2.20"
131 | },
132 | "pylsqpack": {
133 | "hashes": [
134 | "sha256:04336f883f310beed4f4f3bb4709879761a234d001fb21afcc6755a04043b842",
135 | "sha256:233138ba8b78827773422ebfb19ed53127e6d4f2dfbef23434bcc3a75b804b95",
136 | "sha256:25e323bf0cdc732b564648b2e22cef334b503c19848b6b10b0db3c1040178f48",
137 | "sha256:2e41aec759734f9e4941f712086a32bc03085802207ba45b30a43464b9a6eae5",
138 | "sha256:2fddda908f1e04797d004f099fa953bd446fdad8065139237003a627596880d9",
139 | "sha256:32a644315c61d5a73d5847481fe2507decc91500322c8ae5e6787b5a899786df",
140 | "sha256:363a8d6bbd64413962dae25f7353b3e3ba8a9dd9a30e0dd99e7a1e1846b4a779",
141 | "sha256:3902629861f974b6b88437bbd5cbf0e0f9e328f4c58069ac7626690435856e18",
142 | "sha256:3c84077a55a145170ec75ae5b3a869d460361761d798c59af864bedbe8d7b3de",
143 | "sha256:3eb576a1636bc37f93decbdf490d1b951518139efb8972f98d4601066e618d41",
144 | "sha256:42324c78e3bba95bb743f874e68b455965d3737de31affc2c253a6599577a5e5",
145 | "sha256:44f898f9f11d57c2f88a4f89177c402c093d91b004904273cc6a56f6efe0a764",
146 | "sha256:49feecf515875592081f96dcab42ddf1e50ee29f61c7ce79e1d0cb66c4591967",
147 | "sha256:4b0e4374431a9e846e5c43368026e6b4d77c55ef5775bd091ad36cced7a48f18",
148 | "sha256:4c59abe3d3ed691f422fcd86fb8c5aa34f6f852af131a8157fcdb46723ef50f8",
149 | "sha256:57b199d228160fb4d366a265935b2d9278012f5b0f05e227ca8b70f659a880c1",
150 | "sha256:614939a4e89885a47c8163695059ed667b8777b2f8943b42fd774b4c97b26698",
151 | "sha256:659363b95ecb29c69c3222f09a4694521b1dfaf453056bdea2d1fbf65985ba34",
152 | "sha256:660326112271bf5d0e5f44cc1f2e25d5e22987fb6aae3b1dd1922b3efe2ac1fd",
153 | "sha256:66074b1b1c9c761518b080fbd8593c73ef80f1444b1a1f792992badc6cd63430",
154 | "sha256:66e7efc810d7bd2dd03525c39789942c41cdabbf7fdd375b3c1a1aaf72b63b0f",
155 | "sha256:6bf2b6a5e3ae8eca38a9c003ab7c5fc4c3680e56380c2cbc84c08e61332d73b4",
156 | "sha256:6c1da92cc2fa225074355f564d794bf7d57005534b8984c680cc9a3b3ca1b217",
157 | "sha256:71e974b7005da6d416427e33b769e78a2ed5e5d41b3486714cd40c7cf9229f3c",
158 | "sha256:7cfd98932c7cb3a39d75e6ae4c8d4516128e4683591bc2adb54dddec52b34dc8",
159 | "sha256:7ea7bc40f94867a4da58c875d3cfdc13fe88a447e051d62087a7be6cbcee2d2f",
160 | "sha256:7ed46fc27c06d03564db2f11974f8ee58fb7026331fb79e2014f9a164f3ccda7",
161 | "sha256:87bcded74563457da4c321bbecf283b20d6dd00f5a2925828f41f6f85f7c0aa7",
162 | "sha256:89c067bd4be35d6055511f63f7d077053965dc41f35057baa3ddee1d972ae221",
163 | "sha256:8ff8a2749efd870e3a7893f4e4cca26d7660d4a3adf670fb08457f2feb0a7619",
164 | "sha256:9212e6f0cfe7e00ee13a5e60f863eaf123ca9f7ecbfaa3cbcc3be1864f280676",
165 | "sha256:9fd2ab3049529f3317fe88c3ab9041bd0af78421ac3a5f226f303a829b6a208b",
166 | "sha256:a440ca4b343947b605902d33607f292b2f4f76e466d631035e11fe372e6e456d",
167 | "sha256:a501b9f49ab864948c454469add9e63b909300c24503cf458f35019901dbcf76",
168 | "sha256:bbdc5e1523b31ee3da07adc39c1034eee26f84688bad5d75c86d1c5740e811d3",
169 | "sha256:c0654dac162a842610ffc5f0297b89aa3b63ef73d7ee6a9db944120e1a9a90f2",
170 | "sha256:ccb4181b30b9bc952b5e3adbf8c37b3fff8c80fae21f47a645e810717ed9f2c7",
171 | "sha256:db48081caf0818265fc3b94c1e7e6da81e33722017c75cf64f97bccdc2832b27",
172 | "sha256:de86c2c244fe7e0b19c876aa79e8c8edf956f5b019423e2002ea456afce0ef10",
173 | "sha256:e3b27f75c19f6cf453fef46a430fc632b0a627b055ed3d2b98233b0caca72467",
174 | "sha256:e64f758850d5f4dbe82c65c75f91832dd4eaacf5a884000fcd508490abb3b9a2",
175 | "sha256:ebab88ba7948ae8556dfbaccb92356dc75740da88c2742b3d17a4afa6ae280dd",
176 | "sha256:f6ed0e5975fee0701f0d2d7a01c2122da8e64130b7240de96bbc891449f91956",
177 | "sha256:fc497933814545f3c54e35a1b4ebd85a93c2a670832440a0469128c5f501c8fc"
178 | ],
179 | "version": "==0.3.11"
180 | },
181 | "six": {
182 | "hashes": [
183 | "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
184 | "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
185 | ],
186 | "version": "==1.15.0"
187 | }
188 | },
189 | "develop": {
190 | "appdirs": {
191 | "hashes": [
192 | "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
193 | "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
194 | ],
195 | "version": "==1.4.4"
196 | },
197 | "black": {
198 | "hashes": [
199 | "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"
200 | ],
201 | "index": "pypi",
202 | "version": "==20.8b1"
203 | },
204 | "cffi": {
205 | "hashes": [
206 | "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e",
207 | "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d",
208 | "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a",
209 | "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec",
210 | "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362",
211 | "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668",
212 | "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c",
213 | "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b",
214 | "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06",
215 | "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698",
216 | "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2",
217 | "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c",
218 | "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7",
219 | "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009",
220 | "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03",
221 | "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b",
222 | "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909",
223 | "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53",
224 | "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
225 | "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
226 | "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
227 | "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
228 | "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
229 | "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
230 | "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
231 | "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
232 | "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
233 | "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
234 | "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
235 | "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
236 | "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375",
237 | "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b",
238 | "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b",
239 | "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"
240 | ],
241 | "version": "==1.14.4"
242 | },
243 | "click": {
244 | "hashes": [
245 | "sha256:681c9380a24b22fec089c8e5ffe40aa16a0da79f248a26fe2481bfa8170bfcc1",
246 | "sha256:e4315a188403c0258bbc4a4e31863e48fc301c4e95b8007a8eeda0391158df13"
247 | ],
248 | "version": "==8.0.0a1"
249 | },
250 | "cryptography": {
251 | "hashes": [
252 | "sha256:07ca431b788249af92764e3be9a488aa1d39a0bc3be313d826bbec690417e538",
253 | "sha256:13b88a0bd044b4eae1ef40e265d006e34dbcde0c2f1e15eb9896501b2d8f6c6f",
254 | "sha256:32434673d8505b42c0de4de86da8c1620651abd24afe91ae0335597683ed1b77",
255 | "sha256:3cd75a683b15576cfc822c7c5742b3276e50b21a06672dc3a800a2d5da4ecd1b",
256 | "sha256:4e7268a0ca14536fecfdf2b00297d4e407da904718658c1ff1961c713f90fd33",
257 | "sha256:545a8550782dda68f8cdc75a6e3bf252017aa8f75f19f5a9ca940772fc0cb56e",
258 | "sha256:55d0b896631412b6f0c7de56e12eb3e261ac347fbaa5d5e705291a9016e5f8cb",
259 | "sha256:5849d59358547bf789ee7e0d7a9036b2d29e9a4ddf1ce5e06bb45634f995c53e",
260 | "sha256:6dc59630ecce8c1f558277ceb212c751d6730bd12c80ea96b4ac65637c4f55e7",
261 | "sha256:7117319b44ed1842c617d0a452383a5a052ec6aa726dfbaffa8b94c910444297",
262 | "sha256:75e8e6684cf0034f6bf2a97095cb95f81537b12b36a8fedf06e73050bb171c2d",
263 | "sha256:7b8d9d8d3a9bd240f453342981f765346c87ade811519f98664519696f8e6ab7",
264 | "sha256:a035a10686532b0587d58a606004aa20ad895c60c4d029afa245802347fab57b",
265 | "sha256:a4e27ed0b2504195f855b52052eadcc9795c59909c9d84314c5408687f933fc7",
266 | "sha256:a733671100cd26d816eed39507e585c156e4498293a907029969234e5e634bc4",
267 | "sha256:a75f306a16d9f9afebfbedc41c8c2351d8e61e818ba6b4c40815e2b5740bb6b8",
268 | "sha256:bd717aa029217b8ef94a7d21632a3bb5a4e7218a4513d2521c2a2fd63011e98b",
269 | "sha256:d25cecbac20713a7c3bc544372d42d8eafa89799f492a43b79e1dfd650484851",
270 | "sha256:d26a2557d8f9122f9bf445fc7034242f4375bd4e95ecda007667540270965b13",
271 | "sha256:d3545829ab42a66b84a9aaabf216a4dce7f16dbc76eb69be5c302ed6b8f4a29b",
272 | "sha256:d3d5e10be0cf2a12214ddee45c6bd203dab435e3d83b4560c03066eda600bfe3",
273 | "sha256:efe15aca4f64f3a7ea0c09c87826490e50ed166ce67368a68f315ea0807a20df"
274 | ],
275 | "version": "==3.2.1"
276 | },
277 | "flake8": {
278 | "hashes": [
279 | "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839",
280 | "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"
281 | ],
282 | "index": "pypi",
283 | "version": "==3.8.4"
284 | },
285 | "mccabe": {
286 | "hashes": [
287 | "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
288 | "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
289 | ],
290 | "version": "==0.6.1"
291 | },
292 | "mypy-extensions": {
293 | "hashes": [
294 | "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
295 | "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
296 | ],
297 | "version": "==0.4.3"
298 | },
299 | "pathspec": {
300 | "hashes": [
301 | "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd",
302 | "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"
303 | ],
304 | "version": "==0.8.1"
305 | },
306 | "pycodestyle": {
307 | "hashes": [
308 | "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367",
309 | "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"
310 | ],
311 | "index": "pypi",
312 | "version": "==2.6.0"
313 | },
314 | "pycparser": {
315 | "hashes": [
316 | "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
317 | "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
318 | ],
319 | "version": "==2.20"
320 | },
321 | "pyflakes": {
322 | "hashes": [
323 | "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
324 | "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"
325 | ],
326 | "version": "==2.2.0"
327 | },
328 | "regex": {
329 | "hashes": [
330 | "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538",
331 | "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4",
332 | "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc",
333 | "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa",
334 | "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444",
335 | "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1",
336 | "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af",
337 | "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8",
338 | "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9",
339 | "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88",
340 | "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba",
341 | "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364",
342 | "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e",
343 | "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7",
344 | "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0",
345 | "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31",
346 | "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683",
347 | "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee",
348 | "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b",
349 | "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884",
350 | "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c",
351 | "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e",
352 | "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562",
353 | "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85",
354 | "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c",
355 | "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6",
356 | "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d",
357 | "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b",
358 | "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70",
359 | "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b",
360 | "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b",
361 | "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f",
362 | "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0",
363 | "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5",
364 | "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5",
365 | "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f",
366 | "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e",
367 | "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512",
368 | "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d",
369 | "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917",
370 | "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"
371 | ],
372 | "version": "==2020.11.13"
373 | },
374 | "six": {
375 | "hashes": [
376 | "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
377 | "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
378 | ],
379 | "version": "==1.15.0"
380 | },
381 | "toml": {
382 | "hashes": [
383 | "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
384 | "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
385 | ],
386 | "version": "==0.10.2"
387 | },
388 | "typed-ast": {
389 | "hashes": [
390 | "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
391 | "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
392 | "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d",
393 | "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
394 | "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
395 | "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
396 | "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c",
397 | "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
398 | "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
399 | "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
400 | "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
401 | "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
402 | "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
403 | "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d",
404 | "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
405 | "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
406 | "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
407 | "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
408 | "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395",
409 | "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
410 | "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
411 | "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
412 | "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
413 | "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
414 | "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
415 | "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298",
416 | "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
417 | "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
418 | "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f",
419 | "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
420 | ],
421 | "version": "==1.4.1"
422 | },
423 | "typing-extensions": {
424 | "hashes": [
425 | "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
426 | "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
427 | "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
428 | ],
429 | "version": "==3.7.4.3"
430 | }
431 | }
432 | }
433 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # quicTransport_mouse_point_share
2 |
3 | ## prepare
4 |
5 | - DownloadGoogle Chrome(M85~)
6 | - Get origin trial key
7 | - Register QuicTransport Trials. [All Trials](https://developers.chrome.com/origintrials/#/trials/active)
8 | - Copy token.
9 | - Use Trials Token in `index.html`.
10 | - ```
11 |
15 | ```
16 | - Generate a certificate and a private key
17 | - ```
18 | openssl req -newkey rsa:2048 -nodes -keyout certificate.key \
19 | -x509 -out certificate.pem -subj '/CN=Test Certificate' \
20 | -addext "subjectAltName = DNS:localhost"
21 | ```
22 | - Compute the fingerprint of the certificate
23 | - ```
24 | openssl x509 -pubkey -noout -in certificate.pem |
25 | openssl rsa -pubin -outform der |
26 | openssl dgst -sha256 -binary | base64
27 | ```
28 | - Copy fingerprint.
29 | - Open Google Chrome
30 | - ```
31 | open -a "Google Chrome" --args --origin-to-force-quic-on=localhost:4433 --ignore-certificate-errors-spki-list=""
32 | ```
33 |
34 | ### install
35 |
36 | `pipenv install`
37 |
38 | ## run
39 |
40 | `pipenv shell`
41 | `python quic_transport_server.py certificate.pem certificate.key`
42 | `python -m http.server 8000`
43 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | QuicTransport client
4 |
5 |
6 |
10 |
11 |
12 |
13 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // "Connect" button handler.
2 | async function prepareConnection() {
3 | let url = document.getElementById("url").value;
4 | var transport = new WebTransport(url);
5 | console.log(`initializing WebTransport Instance`);
6 | transport.closed
7 | .then(() => {
8 | console.log(`The QUIC connection to ${url} closed gracefully`);
9 | })
10 | .catch((error) => {
11 | console.error(`the QUIC connection to ${url} closed due to ${error}`);
12 | });
13 | await transport.ready;
14 | console.log("startReceivingDatagram");
15 | startReceivingDatagram(transport);
16 | console.log("startReceivingStream");
17 | startReceivingStream(transport);
18 | globalThis.currentTransport = transport;
19 | globalThis.streamNumber = 1;
20 | }
21 | let prev_mouse_point_x = null;
22 | let prev_mouse_point_y = null;
23 |
24 | async function startReceivingDatagram(transport) {
25 | const reader = transport.datagramReadable.getReader();
26 | while (true) {
27 | const { value, done } = await reader.read();
28 | let result = new TextDecoder("ascii").decode(value);
29 | // result = "mouse_point=x,y"
30 | if (result.startsWith("mouse_point=")) {
31 | const index = result.indexOf("=");
32 | const [mouse_point_x, mouse_point_y] = result.slice(index + 1).split(",");
33 | const myPics = document.getElementById("myPics");
34 | const context = myPics.getContext("2d");
35 | if (prev_mouse_point_x && prev_mouse_point_y) {
36 | drawLine(
37 | context,
38 | prev_mouse_point_x,
39 | prev_mouse_point_y,
40 | mouse_point_x,
41 | mouse_point_y
42 | );
43 | }
44 | prev_mouse_point_x = mouse_point_x;
45 | prev_mouse_point_y = mouse_point_y;
46 | }
47 | if (done) {
48 | break;
49 | }
50 | }
51 | }
52 |
53 | async function startReceivingStream(transport) {
54 | let reader = transport.incomingUnidirectionalStreams.getReader();
55 | while (true) {
56 | let result = await reader.read();
57 | if (result.done) {
58 | console.log("Done accepting unidirectional streams!");
59 | return;
60 | }
61 | let stream = result.value;
62 | let number = globalThis.streamNumber++;
63 | readDataFromStream(stream, number);
64 | }
65 | }
66 |
67 | async function readDataFromStream(stream, number) {
68 | let decoder = new TextDecoderStream("utf-8");
69 | let reader = stream.readable.pipeThrough(decoder).getReader();
70 | while (true) {
71 | let result = await reader.read();
72 | if (result.done) {
73 | console.log("Stream #" + number + " closed");
74 | return;
75 | }
76 | if (result.value.startsWith("quic_transport_id=")) {
77 | const index = result.value.indexOf("=");
78 | document.getElementById("QuicTransportID").value = result.value.slice(
79 | index + 1
80 | );
81 | } else if (result.value.startsWith("joined")) {
82 | const index = result.value.indexOf("=");
83 | document.getElementById("OtherQuicTransportID").value +=
84 | result.value.slice(index + 1) + "\n";
85 | }
86 | }
87 | }
88 |
89 | async function sendMousePointDatagram() {
90 | let QuicTransportID = document.getElementById("QuicTransportID").value;
91 | QuicTransportID = new TextEncoder().encode(QuicTransportID);
92 | const transport = globalThis.currentTransport;
93 | mouse_point_share();
94 | }
95 | let isDrawing = false;
96 | function drawLine(context, x1, y1, x2, y2) {
97 | context.beginPath();
98 | context.strokeStyle = "black";
99 | context.lineWidth = 1;
100 | context.moveTo(x1, y1);
101 | context.lineTo(x2, y2);
102 | context.stroke();
103 | context.closePath();
104 | }
105 |
106 | var timeoutId;
107 | function mouse_point_share() {
108 | const myPics = document.getElementById("myPics");
109 | const context = myPics.getContext("2d");
110 | myPics.addEventListener("mousedown", (e) => {
111 | x = e.offsetX;
112 | y = e.offsetY;
113 | isDrawing = true;
114 | });
115 |
116 | myPics.addEventListener("mousemove", (e) => {
117 | if (timeoutId) return;
118 | // Prevent from very high frequency sending.
119 | timeoutId = setTimeout(function () {
120 | timeoutId = 0;
121 |
122 | if (isDrawing === true) {
123 | drawLine(context, x, y, e.offsetX, e.offsetY);
124 | x = e.offsetX;
125 | y = e.offsetY;
126 | const text = `mouse_point=${e.offsetX},${e.offsetY}`;
127 | const encoded_text = new TextEncoder().encode(text);
128 |
129 | if (globalThis.writer) {
130 | writer.write(encoded_text);
131 | } else {
132 | const ws = globalThis.currentTransport.datagramWritable;
133 | const writer = ws.getWriter();
134 | globalThis.writer = writer;
135 | writer.write(encoded_text);
136 | }
137 | }
138 | }, 10);
139 | });
140 |
141 | window.addEventListener("mouseup", (e) => {
142 | if (isDrawing === true) {
143 | drawLine(context, x, y, e.offsetX, e.offsetY);
144 | x = 0;
145 | y = 0;
146 | isDrawing = false;
147 | }
148 | });
149 | }
150 |
--------------------------------------------------------------------------------
/quic_connection_sequence.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuki-uchida/quicTransport_mouse_point_share/5b8106ed75a1ad76b0128950e16df57733978fab/quic_connection_sequence.jpg
--------------------------------------------------------------------------------
/quic_transport_server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # Copyright 2020 Google LLC
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | """
17 | An example QuicTransport server based on the aioquic library.
18 | Processes incoming streams and datagrams, and
19 | replies with the ASCII-encoded length of the data sent in bytes.
20 | Example use:
21 | python3 quic_transport_server.py certificate.pem certificate.key
22 | Example use from JavaScript:
23 | let transport = new QuicTransport("quic-transport://localhost:4433/counter");
24 | await transport.ready;
25 | let stream = await transport.createBidirectionalStream();
26 | let encoder = new TextEncoder();
27 | let writer = stream.writable.getWriter();
28 | await writer.write(encoder.encode("Hello, world!"))
29 | writer.close();
30 | console.log(await new Response(stream.readable).text());
31 | This will output "13" (the length of "Hello, world!") into the console.
32 | """
33 |
34 | # ---- Dependencies ----
35 | #
36 | # This server only depends on Python standard library and aioquic. See
37 | # https://github.com/aiortc/aioquic for instructions on how to install
38 | # aioquic.
39 | #
40 | # ---- Certificates ----
41 | #
42 | # QUIC always operates using TLS, meaning that running a QuicTransport server
43 | # requires a valid TLS certificate. The easiest way to do this is to get a
44 | # certificate from a real publicly trusted CA like .
45 | # https://developers.google.com/web/fundamentals/security/encrypt-in-transit/enable-https
46 | # contains a detailed explanation of how to achieve that.
47 | #
48 | # As an alternative, Chromium can be instructed to trust a self-signed
49 | # certificate using command-line flags. Here are step-by-step instructions on
50 | # how to do that:
51 | #
52 | # 1. Generate a certificate and a private key:
53 | # openssl req -newkey rsa:2048 -nodes -keyout certificate.key \
54 | # -x509 -out certificate.pem -subj '/CN=Test Certificate' \
55 | # -addext "subjectAltName = DNS:localhost"
56 | #
57 | # 2. Compute the fingerprint of the certificate:
58 | # openssl x509 -pubkey -noout -in certificate.pem |
59 | # openssl rsa -pubin -outform der |
60 | # openssl dgst -sha256 -binary | base64
61 | # The result should be a base64-encoded blob that looks like this:
62 | # "Gi/HIwdiMcPZo2KBjnstF5kQdLI5bPrYJ8i3Vi6Ybck="
63 | #
64 | # 3. Pass a flag to Chromium indicating what host and port should be allowed
65 | # to use the self-signed certificate. For instance, if the host is
66 | # localhost, and the port is 4433, the flag would be:
67 | # --origin-to-force-quic-on=localhost:4433
68 | #
69 | # 4. Pass a flag to Chromium indicating which certificate needs to be trusted.
70 | # For the example above, that flag would be:
71 | # --ignore-certificate-errors-spki-list=Gi/HIwdiMcPZo2KBjnstF5kQdLI5bPrYJ8i3Vi6Ybck=
72 | #
73 | # See https://www.chromium.org/developers/how-tos/run-chromium-with-flags for
74 | # details on how to run Chromium with flags.
75 |
76 | # open -a "Google Chrome" --args --origin-to-force-quic-on=localhost:4433 --ignore-certificate-errors-spki-list="ks9+B0hyVs6hwrZh3alG5XBKVGbAIrSnRWPSsdYXXFw="
77 |
78 |
79 | import uuid
80 | from aioquic.tls import SessionTicket
81 | from aioquic.quic.events import (
82 | StreamDataReceived,
83 | StreamReset,
84 | DatagramFrameReceived,
85 | QuicEvent,
86 | )
87 | from aioquic.quic.connection import QuicConnection, END_STATES
88 | from aioquic.quic.configuration import QuicConfiguration
89 | from aioquic.asyncio import QuicConnectionProtocol, serve
90 | from typing import Dict, Optional
91 | from collections import defaultdict
92 | import urllib.parse
93 | import struct
94 | import os
95 | import io
96 | import asyncio
97 | import argparse
98 | import sys
99 |
100 |
101 | # Additional
102 |
103 | BIND_ADDRESS = "::1"
104 | BIND_PORT = 4433
105 |
106 | connections_list = {}
107 |
108 |
109 | def addConnections(new_connection, new_protocol) -> None:
110 | print(f"quic_transport_server addConnections{connections_list}")
111 | new_quic_transport_id = str(uuid.uuid4())
112 | # 入室情報を他の人に教えてあげる(streamで)
113 | for quic_transport_id, connection_dict in connections_list.items():
114 | response_id = connection_dict["connection"].get_next_available_stream_id(
115 | is_unidirectional=True
116 | )
117 | payload = str(f"joined={new_quic_transport_id}").encode("ascii")
118 | connection_dict["connection"].send_stream_data(response_id, payload, True)
119 | # connection_dict["protocol"].transmit()
120 |
121 | connections_list[new_quic_transport_id] = {
122 | "connection": new_connection,
123 | "protocol": new_protocol,
124 | }
125 | # 自分のQuicTransportIDを教えてあげる(streamで)
126 | response_id = new_connection.get_next_available_stream_id(is_unidirectional=True)
127 | payload = str(f"quic_transport_id={new_quic_transport_id}").encode("ascii")
128 | new_connection.send_stream_data(response_id, payload, True)
129 | new_protocol.transmit()
130 | for quic_transport_id, connection_dict in connections_list.items():
131 | # if new_connection == connection_dict["connection"]:
132 | # continue
133 | if new_quic_transport_id == quic_transport_id:
134 | continue
135 | response_id = new_connection.get_next_available_stream_id(
136 | is_unidirectional=True
137 | )
138 | payload = str(f"joined={quic_transport_id}").encode("ascii")
139 | new_connection.send_stream_data(response_id, payload, True)
140 | new_protocol.transmit()
141 | return new_quic_transport_id
142 |
143 |
144 | def removeConnections(connection, protocol) -> None:
145 | connections_list.remove({"connection": connection, "protocol": protocol})
146 | print(
147 | f"quic_transport_server removeConnections removed :{connection},{protocol}, remain: {connections_list} "
148 | )
149 | # TODO:// 抜けたことを知らせる処理をかく
150 |
151 |
152 | # QUIC uses two lowest bits of the stream ID to indicate whether the stream is:
153 | # (a) unidirectional or bidirectional,
154 | # (b) initiated by the client or by the server.
155 | # See https://tools.ietf.org/html/draft-ietf-quic-transport-27#section-2.1 for
156 | # more details.
157 |
158 | # ストリームのIDをみると、タイプがわかる
159 | # 0x0: クライアント開始&双方向
160 | # 0x1: サーバー起動&双方向
161 | # 0x2: クライアント開始&単方向
162 | # 0x3: サーバー起動&単方向
163 |
164 |
165 | def is_client_bidi_stream(stream_id):
166 | return stream_id % 4 == 0
167 |
168 |
169 | # CounterHandler implements a really simple protocol:
170 | # - For every incoming bidirectional stream, it counts bytes it receives on
171 | # that stream until the stream is closed, and then replies with that byte
172 | # count on the same stream.
173 | # - For every incoming unidirectional stream, it counts bytes it receives on
174 | # that stream until the stream is closed, and then replies with that byte
175 | # count on a new unidirectional stream.
176 | # - For every incoming datagram, it sends a datagram with the length of
177 | # datagram that was just received.
178 |
179 |
180 | class sendDataHandler:
181 | def __init__(self, protocol, connection) -> None:
182 | self.protocol = protocol
183 | self.connection = connection
184 | self.counters = defaultdict(str)
185 | self.quic_transport_id = addConnections(self.connection, self.protocol)
186 |
187 | def removeFromConnections(self) -> None:
188 | removeConnections(self.connection, self.proto)
189 |
190 | def quic_event_received(self, event: QuicEvent) -> None:
191 | if isinstance(event, DatagramFrameReceived):
192 | payload = event.data
193 | # self.connection.send_datagram_frame(payload)
194 | for quic_transport_id, connection_dict in connections_list.items():
195 | if self.quic_transport_id == quic_transport_id:
196 | continue
197 | connection_dict["connection"].send_datagram_frame(payload)
198 | connection_dict["protocol"].transmit()
199 |
200 |
201 | # QuicTransportProtocol handles the beginning of a QuicTransport connection: it
202 | # parses the incoming URL, and routes the transport events to a relevant
203 | # handler (in this example, CounterHandler). It does that by waiting for a
204 | # client indication (a special stream with protocol headers), and buffering all
205 | # unrelated events until the client indication can be fully processed.
206 |
207 |
208 | class QuicTransportProtocol(QuicConnectionProtocol):
209 | def __init__(self, *args, **kwargs) -> None:
210 | super().__init__(*args, **kwargs)
211 | self.pending_events = []
212 | self.handler = None
213 | self.client_indication_data = b""
214 |
215 | # QuicConnectionProtocolクラスのtをオーバーライドしてる
216 | # quicを経由したデータ送信は全てここを通る?少なくともclient indicationはここを経由する
217 |
218 | def quic_event_received(self, event: QuicEvent) -> None:
219 | try:
220 | print(
221 | "quic_server_transport_server#QuicTransportProtocol#quic_event_received ============================================================================================================================================"
222 | )
223 | if self.is_closing_or_closed():
224 | self.handler.removeFromConnections()
225 | return
226 | # If the handler is available, that means the connection has been
227 | # established and the client has been processed.
228 | if self.handler is not None:
229 | print(
230 | "quic_server_transport_server#QuicTransportProtocol#quic_event_received handler is already available!!"
231 | )
232 | self.handler.quic_event_received(event)
233 | return
234 | # stream_id=2 => クライアントサイド開始&単方向
235 | if isinstance(event, StreamDataReceived) and event.stream_id == 2:
236 | # print(f'event.data : {event.data}')
237 | # print(f'event.end_stream : {event.end_stream}')
238 | self.client_indication_data += event.data
239 | # streamが終了している場合には開始する処理が走る。すでに開始している場合には何もせず?
240 | if event.end_stream:
241 | # client_indicationを処理して、アクセスしてきたpathによって処理を変える。
242 | # self.handlerにCounter handlerのようなものが入っていないといけない?
243 | self.process_client_indication()
244 | # print(self.is_closing_or_closed())
245 | if self.is_closing_or_closed():
246 | return
247 | # Pass all buffered events into the handler now that it's
248 | # available.
249 | # print(self.pending_events)
250 | for e in self.pending_events:
251 | self.handler.quic_event_received(e)
252 | self.pending_events.clear()
253 | else:
254 | # We have received some application data before we have the
255 | # request URL available, which is possible since there is no
256 | # ordering guarantee on data between different QUIC streams.
257 | # Buffer the data for now.
258 | self.pending_events.append(event)
259 |
260 | except Exception as e:
261 | print(e)
262 | self.handler = None
263 | self.close()
264 | # print('quic_event_received() ended')
265 |
266 | # Client indication follows a "key-length-value" format, where key and
267 | # length are 16-bit integers. See
268 | # https://tools.ietf.org/html/draft-vvv-webtransport-quic-01#section-3.2
269 |
270 | def parse_client_indication(self, bs):
271 | while True:
272 | prefix = bs.read(4)
273 | if len(prefix) == 0:
274 | return # End-of-stream reached.
275 | if len(prefix) != 4:
276 | raise Exception("Truncated key-length tag")
277 | # Cの構造体のデータとpython bytesオブジェクトの変換でstructは使用される
278 | key, length = struct.unpack("!HH", prefix)
279 | value = bs.read(length)
280 | if len(value) != length:
281 | raise Exception("Truncated value")
282 | yield (key, value)
283 |
284 | def process_client_indication(self) -> None:
285 | """
286 | ProtocolNegotiated/HandshakeCompletedのeventが送られてきた後に送られるClient_indicationを処理する。
287 | stream_idが2(クライアント開始・単方向)で、handlerがまだ渡されていない(開始していないstreamである)場合にこの関数が呼ばれる。
288 | (その時はend_stream=Trueで、self.is_closing_or_closed()がFalseになっているはず)
289 | new QuicTransport(url);の段階で、clientの情報が送られてくる。その情報はまず`quic_event_received()` で処理される
290 | """
291 | KEY_ORIGIN = 0
292 | KEY_PATH = 1
293 | indication = dict(
294 | self.parse_client_indication(io.BytesIO(self.client_indication_data))
295 | )
296 |
297 | origin = urllib.parse.urlparse(indication[KEY_ORIGIN].decode())
298 | path = urllib.parse.urlparse(indication[KEY_PATH]).decode()
299 | # Verify that the origin host is allowed to talk to this server. This
300 | # is similar to the CORS (Cross-Origin Resource Sharing) mechanism in
301 | # HTTP. See .
302 | if origin.hostname != "localhost":
303 | raise Exception("Wrong origin specified")
304 | # Dispatch the incoming connection based on the path specified in the
305 | # URL.
306 | if path.path == "/mouse_point_share":
307 | self.handler = sendDataHandler(self, self._quic)
308 | print("handler attached!!!!!!!")
309 | else:
310 | raise Exception("Unknown path")
311 |
312 | def is_closing_or_closed(self) -> bool:
313 | return self._quic._close_pending or self._quic._state in END_STATES
314 |
315 |
316 | if __name__ == "__main__":
317 | parser = argparse.ArgumentParser()
318 | parser.add_argument("certificate")
319 | parser.add_argument("key")
320 | args = parser.parse_args()
321 | # Quicのsetting
322 | configuration = QuicConfiguration(
323 | # Identifies the protocol used. The origin trial uses the protocol
324 | # described in draft-vvv-webtransport-quic-01, hence the ALPN value.
325 | # See https://tools.ietf.org/html/draft-vvv-webtransport-quic-01#section-3.1
326 | alpn_protocols=["wq-vvv-01"],
327 | is_client=False,
328 | idle_timeout=30000,
329 | # Note that this is just an upper limit; the real maximum datagram size
330 | # available depends on the MTU of the path. See
331 | # .
332 | max_datagram_frame_size=1500,
333 | )
334 | # Quicの鍵読み込み。
335 | configuration.load_cert_chain(args.certificate, args.key)
336 |
337 | loop = asyncio.get_event_loop()
338 | # 完了するまで続ける
339 | print("running quic server")
340 | loop.run_until_complete(
341 | serve(
342 | BIND_ADDRESS,
343 | BIND_PORT,
344 | configuration=configuration,
345 | create_protocol=QuicTransportProtocol,
346 | )
347 | )
348 | loop.run_forever()
349 |
--------------------------------------------------------------------------------
/sequence.drawio:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [pycodestyle]
2 | ignore = E501
3 |
4 | [pep8]
5 | ignore = E501
--------------------------------------------------------------------------------