quico 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +381 -216
- package/index.cjs +45 -0
- package/index.d.ts +158 -0
- package/index.js +46 -23
- package/package.json +83 -60
- package/src/agent.js +275 -0
- package/src/client.js +439 -0
- package/src/crypto.js +519 -0
- package/src/h3.js +911 -0
- package/src/h3_client.js +317 -0
- package/src/h3_server.js +523 -0
- package/src/quic_connection.js +1238 -0
- package/src/server.js +346 -0
- package/src/streams.js +471 -0
- package/src/tls_bridge.js +211 -0
- package/src/transport.js +651 -0
- package/src/utils.js +290 -0
- package/src/webtransport.js +708 -0
- package/CHANGELOG.md +0 -31
- package/examples/webtransport_datagram_echo_server/client.html +0 -58
- package/examples/webtransport_datagram_echo_server/server.js +0 -23
- package/h3_server.js +0 -416
- package/h3_socket.js +0 -473
- package/libs/crypto.js +0 -1841
- package/libs/h3.js +0 -1461
- package/libs/utils.js +0 -404
- package/quic_socket.js +0 -1550
- package/quico.svg +0 -1
package/libs/h3.js
DELETED
|
@@ -1,1461 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* quico: HTTP/3 and QUIC implementation for Node.js
|
|
3
|
-
* Copyright 2025 colocohen
|
|
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
|
-
* This file is part of the open-source project hosted at:
|
|
12
|
-
* https://github.com/colocohen/quico
|
|
13
|
-
*
|
|
14
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import {
|
|
20
|
-
concatUint8Arrays,
|
|
21
|
-
writeVarInt,
|
|
22
|
-
readVarInt
|
|
23
|
-
} from './utils.js';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var huffman_codes = new Uint32Array([
|
|
27
|
-
0x1ff8,//(0)
|
|
28
|
-
0x7fffd8,//(1)
|
|
29
|
-
0xfffffe2,//(2)
|
|
30
|
-
0xfffffe3,//(3)
|
|
31
|
-
0xfffffe4,//(4)
|
|
32
|
-
0xfffffe5,//(5)
|
|
33
|
-
0xfffffe6,//(6)
|
|
34
|
-
0xfffffe7,//(7)
|
|
35
|
-
0xfffffe8,//(8)
|
|
36
|
-
0xffffea,//(9)
|
|
37
|
-
0x3ffffffc,//(10)
|
|
38
|
-
0xfffffe9,//(11)
|
|
39
|
-
0xfffffea,//(12)
|
|
40
|
-
0x3ffffffd,//(13)
|
|
41
|
-
0xfffffeb,//(14)
|
|
42
|
-
0xfffffec,//(15)
|
|
43
|
-
0xfffffed,//(16)
|
|
44
|
-
0xfffffee,//(17)
|
|
45
|
-
0xfffffef,//(18)
|
|
46
|
-
0xffffff0,//(19)
|
|
47
|
-
0xffffff1,//(20)
|
|
48
|
-
0xffffff2,//(21)
|
|
49
|
-
0x3ffffffe,//(22)
|
|
50
|
-
0xffffff3,//(23)
|
|
51
|
-
0xffffff4,//(24)
|
|
52
|
-
0xffffff5,//(25)
|
|
53
|
-
0xffffff6,//(26)
|
|
54
|
-
0xffffff7,//(27)
|
|
55
|
-
0xffffff8,//(28)
|
|
56
|
-
0xffffff9,//(29)
|
|
57
|
-
0xffffffa,//(30)
|
|
58
|
-
0xffffffb,//(31)
|
|
59
|
-
0x14,//' ' (32)
|
|
60
|
-
0x3f8,//'!' (33)
|
|
61
|
-
0x3f9,//'"' (34)
|
|
62
|
-
0xffa,//'#' (35)
|
|
63
|
-
0x1ff9,//'$' (36)
|
|
64
|
-
0x15,//'%' (37)
|
|
65
|
-
0xf8,//'&' (38)
|
|
66
|
-
0x7fa,//''' (39)
|
|
67
|
-
0x3fa,//'(' (40)
|
|
68
|
-
0x3fb,//')' (41)
|
|
69
|
-
0xf9,//'*' (42)
|
|
70
|
-
0x7fb,//'+' (43)
|
|
71
|
-
0xfa,//',' (44)
|
|
72
|
-
0x16,//'-' (45)
|
|
73
|
-
0x17,//'.' (46)
|
|
74
|
-
0x18,//'/' (47)
|
|
75
|
-
0x0,//'0' (48)
|
|
76
|
-
0x1,//'1' (49)
|
|
77
|
-
0x2,//'2' (50)
|
|
78
|
-
0x19,//'3' (51)
|
|
79
|
-
0x1a,//'4' (52)
|
|
80
|
-
0x1b,//'5' (53)
|
|
81
|
-
0x1c,//'6' (54)
|
|
82
|
-
0x1d,//'7' (55)
|
|
83
|
-
0x1e,//'8' (56)
|
|
84
|
-
0x1f,//'9' (57)
|
|
85
|
-
0x5c,//':' (58)
|
|
86
|
-
0xfb,//';' (59)
|
|
87
|
-
0x7ffc,//'<' (60)
|
|
88
|
-
0x20,//'=' (61)
|
|
89
|
-
0xffb,//'>' (62)
|
|
90
|
-
0x3fc,//'?' (63)
|
|
91
|
-
0x1ffa,//'@' (64)
|
|
92
|
-
0x21,//'A' (65)
|
|
93
|
-
0x5d,//'B' (66)
|
|
94
|
-
0x5e,//'C' (67)
|
|
95
|
-
0x5f,//'D' (68)
|
|
96
|
-
0x60,//'E' (69)
|
|
97
|
-
0x61,//'F' (70)
|
|
98
|
-
0x62,//'G' (71)
|
|
99
|
-
0x63,//'H' (72)
|
|
100
|
-
0x64,//'I' (73)
|
|
101
|
-
0x65,//'J' (74)
|
|
102
|
-
0x66,//'K' (75)
|
|
103
|
-
0x67,//'L' (76)
|
|
104
|
-
0x68,//'M' (77)
|
|
105
|
-
0x69,//'N' (78)
|
|
106
|
-
0x6a,//'O' (79)
|
|
107
|
-
0x6b,//'P' (80)
|
|
108
|
-
0x6c,//'Q' (81)
|
|
109
|
-
0x6d,//'R' (82)
|
|
110
|
-
0x6e,//'S' (83)
|
|
111
|
-
0x6f,//'T' (84)
|
|
112
|
-
0x70,//'U' (85)
|
|
113
|
-
0x71,//'V' (86)
|
|
114
|
-
0x72,//'W' (87)
|
|
115
|
-
0xfc,//'X' (88)
|
|
116
|
-
0x73,//'Y' (89)
|
|
117
|
-
0xfd,//'Z' (90)
|
|
118
|
-
0x1ffb,//'[' (91)
|
|
119
|
-
0x7fff0,//'\' (92)
|
|
120
|
-
0x1ffc,//']' (93)
|
|
121
|
-
0x3ffc,//'^' (94)
|
|
122
|
-
0x22,//'_' (95)
|
|
123
|
-
0x7ffd,//'`' (96)
|
|
124
|
-
0x3,//'a' (97)
|
|
125
|
-
0x23,//'b' (98)
|
|
126
|
-
0x4,//'c' (99)
|
|
127
|
-
0x24,//'d' (100)
|
|
128
|
-
0x5,//'e' (101)
|
|
129
|
-
0x25,//'f' (102)
|
|
130
|
-
0x26,//'g' (103)
|
|
131
|
-
0x27,//'h' (104)
|
|
132
|
-
0x6,//'i' (105)
|
|
133
|
-
0x74,//'j' (106)
|
|
134
|
-
0x75,//'k' (107)
|
|
135
|
-
0x28,//'l' (108)
|
|
136
|
-
0x29,//'m' (109)
|
|
137
|
-
0x2a,//'n' (110)
|
|
138
|
-
0x7,//'o' (111)
|
|
139
|
-
0x2b,//'p' (112)
|
|
140
|
-
0x76,//'q' (113)
|
|
141
|
-
0x2c,//'r' (114)
|
|
142
|
-
0x8,//'s' (115)
|
|
143
|
-
0x9,//'t' (116)
|
|
144
|
-
0x2d,//'u' (117)
|
|
145
|
-
0x77,//'v' (118)
|
|
146
|
-
0x78,//'w' (119)
|
|
147
|
-
0x79,//'x' (120)
|
|
148
|
-
0x7a,//'y' (121)
|
|
149
|
-
0x7b,//'z' (122)
|
|
150
|
-
0x7ffe,//'{' (123)
|
|
151
|
-
0x7fc,//'|' (124)
|
|
152
|
-
0x3ffd,//'}' (125)
|
|
153
|
-
0x1ffd,//'~' (126)
|
|
154
|
-
0xffffffc,//(127)
|
|
155
|
-
0xfffe6,//(128)
|
|
156
|
-
0x3fffd2,//(129)
|
|
157
|
-
0xfffe7,//(130)
|
|
158
|
-
0xfffe8,//(131)
|
|
159
|
-
0x3fffd3,//(132)
|
|
160
|
-
0x3fffd4,//(133)
|
|
161
|
-
0x3fffd5,//(134)
|
|
162
|
-
0x7fffd9,//(135)
|
|
163
|
-
0x3fffd6,//(136)
|
|
164
|
-
0x7fffda,//(137)
|
|
165
|
-
0x7fffdb,//(138)
|
|
166
|
-
0x7fffdc,//(139)
|
|
167
|
-
0x7fffdd,//(140)
|
|
168
|
-
0x7fffde,//(141)
|
|
169
|
-
0xffffeb,//(142)
|
|
170
|
-
0x7fffdf,//(143)
|
|
171
|
-
0xffffec,//(144)
|
|
172
|
-
0xffffed,//(145)
|
|
173
|
-
0x3fffd7,//(146)
|
|
174
|
-
0x7fffe0,//(147)
|
|
175
|
-
0xffffee,//(148)
|
|
176
|
-
0x7fffe1,//(149)
|
|
177
|
-
0x7fffe2,//(150)
|
|
178
|
-
0x7fffe3,//(151)
|
|
179
|
-
0x7fffe4,//(152)
|
|
180
|
-
0x1fffdc,//(153)
|
|
181
|
-
0x3fffd8,//(154)
|
|
182
|
-
0x7fffe5,//(155)
|
|
183
|
-
0x3fffd9,//(156)
|
|
184
|
-
0x7fffe6,//(157)
|
|
185
|
-
0x7fffe7,//(158)
|
|
186
|
-
0xffffef,//(159)
|
|
187
|
-
0x3fffda,//(160)
|
|
188
|
-
0x1fffdd,//(161)
|
|
189
|
-
0xfffe9,//(162)
|
|
190
|
-
0x3fffdb,//(163)
|
|
191
|
-
0x3fffdc,//(164)
|
|
192
|
-
0x7fffe8,//(165)
|
|
193
|
-
0x7fffe9,//(166)
|
|
194
|
-
0x1fffde,//(167)
|
|
195
|
-
0x7fffea,//(168)
|
|
196
|
-
0x3fffdd,//(169)
|
|
197
|
-
0x3fffde,//(170)
|
|
198
|
-
0xfffff0,//(171)
|
|
199
|
-
0x1fffdf,//(172)
|
|
200
|
-
0x3fffdf,//(173)
|
|
201
|
-
0x7fffeb,//(174)
|
|
202
|
-
0x7fffec,//(175)
|
|
203
|
-
0x1fffe0,//(176)
|
|
204
|
-
0x1fffe1,//(177)
|
|
205
|
-
0x3fffe0,//(178)
|
|
206
|
-
0x1fffe2,//(179)
|
|
207
|
-
0x7fffed,//(180)
|
|
208
|
-
0x3fffe1,//(181)
|
|
209
|
-
0x7fffee,//(182)
|
|
210
|
-
0x7fffef,//(183)
|
|
211
|
-
0xfffea,//(184)
|
|
212
|
-
0x3fffe2,//(185)
|
|
213
|
-
0x3fffe3,//(186)
|
|
214
|
-
0x3fffe4,//(187)
|
|
215
|
-
0x7ffff0,//(188)
|
|
216
|
-
0x3fffe5,//(189)
|
|
217
|
-
0x3fffe6,//(190)
|
|
218
|
-
0x7ffff1,//(191)
|
|
219
|
-
0x3ffffe0,//(192)
|
|
220
|
-
0x3ffffe1,//(193)
|
|
221
|
-
0xfffeb,//(194)
|
|
222
|
-
0x7fff1,//(195)
|
|
223
|
-
0x3fffe7,//(196)
|
|
224
|
-
0x7ffff2,//(197)
|
|
225
|
-
0x3fffe8,//(198)
|
|
226
|
-
0x1ffffec,//(199)
|
|
227
|
-
0x3ffffe2,//(200)
|
|
228
|
-
0x3ffffe3,//(201)
|
|
229
|
-
0x3ffffe4,//(202)
|
|
230
|
-
0x7ffffde,//(203)
|
|
231
|
-
0x7ffffdf,//(204)
|
|
232
|
-
0x3ffffe5,//(205)
|
|
233
|
-
0xfffff1,//(206)
|
|
234
|
-
0x1ffffed,//(207)
|
|
235
|
-
0x7fff2,//(208)
|
|
236
|
-
0x1fffe3,//(209)
|
|
237
|
-
0x3ffffe6,//(210)
|
|
238
|
-
0x7ffffe0,//(211)
|
|
239
|
-
0x7ffffe1,//(212)
|
|
240
|
-
0x3ffffe7,//(213)
|
|
241
|
-
0x7ffffe2,//(214)
|
|
242
|
-
0xfffff2,//(215)
|
|
243
|
-
0x1fffe4,//(216)
|
|
244
|
-
0x1fffe5,//(217)
|
|
245
|
-
0x3ffffe8,//(218)
|
|
246
|
-
0x3ffffe9,//(219)
|
|
247
|
-
0xffffffd,//(220)
|
|
248
|
-
0x7ffffe3,//(221)
|
|
249
|
-
0x7ffffe4,//(222)
|
|
250
|
-
0x7ffffe5,//(223)
|
|
251
|
-
0xfffec,//(224)
|
|
252
|
-
0xfffff3,//(225)
|
|
253
|
-
0xfffed,//(226)
|
|
254
|
-
0x1fffe6,//(227)
|
|
255
|
-
0x3fffe9,//(228)
|
|
256
|
-
0x1fffe7,//(229)
|
|
257
|
-
0x1fffe8,//(230)
|
|
258
|
-
0x7ffff3,//(231)
|
|
259
|
-
0x3fffea,//(232)
|
|
260
|
-
0x3fffeb,//(233)
|
|
261
|
-
0x1ffffee,//(234)
|
|
262
|
-
0x1ffffef,//(235)
|
|
263
|
-
0xfffff4,//(236)
|
|
264
|
-
0xfffff5,//(237)
|
|
265
|
-
0x3ffffea,//(238)
|
|
266
|
-
0x7ffff4,//(239)
|
|
267
|
-
0x3ffffeb,//(240)
|
|
268
|
-
0x7ffffe6,//(241)
|
|
269
|
-
0x3ffffec,//(242)
|
|
270
|
-
0x3ffffed,//(243)
|
|
271
|
-
0x7ffffe7,//(244)
|
|
272
|
-
0x7ffffe8,//(245)
|
|
273
|
-
0x7ffffe9,//(246)
|
|
274
|
-
0x7ffffea,//(247)
|
|
275
|
-
0x7ffffeb,//(248)
|
|
276
|
-
0xffffffe,//(249)
|
|
277
|
-
0x7ffffec,//(250)
|
|
278
|
-
0x7ffffed,//(251)
|
|
279
|
-
0x7ffffee,//(252)
|
|
280
|
-
0x7ffffef,//(253)
|
|
281
|
-
0x7fffff0,//(254)
|
|
282
|
-
0x3ffffee,//(255)
|
|
283
|
-
0x3fffffff,//EOS (256)
|
|
284
|
-
]);
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
var huffman_bits = new Uint8Array([13,23,28,28,28,28,28,28,28,24,30,28,28,30,28,28,28,28,28,28,28,28,30,28,28,28,28,28,28,28,28,28,6,10,10,12,13,6,8,11,10,10,8,11,8,6,6,6,5,5,5,6,6,6,6,6,6,6,7,8,15,6,12,10,13,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,7,8,13,19,13,14,6,15,5,6,5,6,5,6,6,6,5,7,7,6,6,6,5,6,7,6,5,5,6,7,7,7,7,7,15,11,14,13,28,20,22,20,20,22,22,22,23,22,23,23,23,23,23,24,23,24,24,22,23,24,23,23,23,23,21,22,23,22,23,23,24,22,21,20,22,22,23,23,21,23,22,22,24,21,22,23,23,21,21,22,21,23,22,23,23,20,22,22,22,23,22,22,23,26,26,20,19,22,23,22,25,26,26,26,27,27,26,24,25,19,21,26,27,27,26,27,24,21,21,26,26,28,27,27,27,20,24,20,21,22,21,21,23,22,22,25,25,24,24,26,23,26,27,26,26,27,27,27,27,27,28,27,27,27,27,27,26,30]);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
function buildHuffmanDecodeTrie() {
|
|
293
|
-
var root = {};
|
|
294
|
-
for (var i = 0; i < huffman_codes.length; i++) {
|
|
295
|
-
var code = huffman_codes[i];
|
|
296
|
-
var length = huffman_bits[i];
|
|
297
|
-
var node = root;
|
|
298
|
-
for (var j = length - 1; j >= 0; j--) {
|
|
299
|
-
var bit = (code >> j) & 1;
|
|
300
|
-
if (!node[bit]) node[bit] = {};
|
|
301
|
-
node = node[bit];
|
|
302
|
-
}
|
|
303
|
-
node.symbol = i;
|
|
304
|
-
}
|
|
305
|
-
return root;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
var huffman_flat_decode_tables = buildHuffmanDecodeTrie();
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
var qpack_static_table_entries = [
|
|
313
|
-
[":authority", ""],
|
|
314
|
-
[":path", "/"],
|
|
315
|
-
["age", "0"],
|
|
316
|
-
["content-disposition", ""],
|
|
317
|
-
["content-length", "0"],
|
|
318
|
-
["cookie", ""],
|
|
319
|
-
["date", ""],
|
|
320
|
-
["etag", ""],
|
|
321
|
-
["if-modified-since", ""],
|
|
322
|
-
["if-none-match", ""],
|
|
323
|
-
["last-modified", ""],
|
|
324
|
-
["link", ""],
|
|
325
|
-
["location", ""],
|
|
326
|
-
["referer", ""],
|
|
327
|
-
["set-cookie", ""],
|
|
328
|
-
[":method", "CONNECT"],
|
|
329
|
-
[":method", "DELETE"],
|
|
330
|
-
[":method", "GET"],
|
|
331
|
-
[":method", "HEAD"],
|
|
332
|
-
[":method", "OPTIONS"],
|
|
333
|
-
[":method", "POST"],
|
|
334
|
-
[":method", "PUT"],
|
|
335
|
-
[":scheme", "http"],
|
|
336
|
-
[":scheme", "https"],
|
|
337
|
-
[":status", "103"],
|
|
338
|
-
[":status", "200"],
|
|
339
|
-
[":status", "304"],
|
|
340
|
-
[":status", "404"],
|
|
341
|
-
[":status", "503"],
|
|
342
|
-
["accept", "*/*"],
|
|
343
|
-
["accept", "application/dns-message"],
|
|
344
|
-
["accept-encoding", "gzip, deflate, br"],
|
|
345
|
-
["accept-ranges", "bytes"],
|
|
346
|
-
["access-control-allow-headers", "cache-control"],
|
|
347
|
-
["access-control-allow-headers", "content-type"],
|
|
348
|
-
["access-control-allow-origin", "*"],
|
|
349
|
-
["cache-control", "max-age=0"],
|
|
350
|
-
["cache-control", "max-age=2592000"],
|
|
351
|
-
["cache-control", "max-age=604800"],
|
|
352
|
-
["cache-control", "no-cache"],
|
|
353
|
-
["cache-control", "no-store"],
|
|
354
|
-
["cache-control", "public, max-age=31536000"],
|
|
355
|
-
["content-encoding", "br"],
|
|
356
|
-
["content-encoding", "gzip"],
|
|
357
|
-
["content-type", "application/dns-message"],
|
|
358
|
-
["content-type", "application/javascript"],
|
|
359
|
-
["content-type", "application/json"],
|
|
360
|
-
["content-type", "application/x-www-form-urlencoded"],
|
|
361
|
-
["content-type", "image/gif"],
|
|
362
|
-
["content-type", "image/jpeg"],
|
|
363
|
-
["content-type", "image/png"],
|
|
364
|
-
["content-type", "text/css"],
|
|
365
|
-
["content-type", "text/html; charset=utf-8"],
|
|
366
|
-
["content-type", "text/plain"],
|
|
367
|
-
["content-type", "text/plain;charset=utf-8"],
|
|
368
|
-
["range", "bytes=0-"],
|
|
369
|
-
["strict-transport-security", "max-age=31536000"],
|
|
370
|
-
["strict-transport-security", "max-age=31536000; includesubdomains"],
|
|
371
|
-
["strict-transport-security", "max-age=31536000; includesubdomains; preload"],
|
|
372
|
-
["vary", "accept-encoding"],
|
|
373
|
-
["vary", "origin"],
|
|
374
|
-
["x-content-type-options", "nosniff"],
|
|
375
|
-
["x-xss-protection", "1; mode=block"],
|
|
376
|
-
[":status", "100"],
|
|
377
|
-
[":status", "204"],
|
|
378
|
-
[":status", "206"],
|
|
379
|
-
[":status", "302"],
|
|
380
|
-
[":status", "400"],
|
|
381
|
-
[":status", "403"],
|
|
382
|
-
[":status", "421"],
|
|
383
|
-
[":status", "425"],
|
|
384
|
-
[":status", "500"],
|
|
385
|
-
["accept-language", ""],
|
|
386
|
-
["access-control-allow-credentials", "FALSE"],
|
|
387
|
-
["access-control-allow-credentials", "TRUE"],
|
|
388
|
-
["access-control-allow-headers", "*"],
|
|
389
|
-
["access-control-allow-methods", "get"],
|
|
390
|
-
["access-control-allow-methods", "get, post, options"],
|
|
391
|
-
["access-control-allow-methods", "options"],
|
|
392
|
-
["access-control-expose-headers", "content-length"],
|
|
393
|
-
["access-control-request-headers", "content-type"],
|
|
394
|
-
["access-control-request-method", "get"],
|
|
395
|
-
["access-control-request-method", "post"],
|
|
396
|
-
["alt-svc", "clear"],
|
|
397
|
-
["authorization", ""],
|
|
398
|
-
["content-security-policy", "script-src 'none'; object-src 'none'; base-uri 'none'"],
|
|
399
|
-
["early-data", "1"],
|
|
400
|
-
["expect-ct", ""],
|
|
401
|
-
["forwarded", ""],
|
|
402
|
-
["if-range", ""],
|
|
403
|
-
["origin", ""],
|
|
404
|
-
["purpose", "prefetch"],
|
|
405
|
-
["server", ""],
|
|
406
|
-
["timing-allow-origin", "*"],
|
|
407
|
-
["upgrade-insecure-requests", "1"],
|
|
408
|
-
["user-agent", ""],
|
|
409
|
-
["x-forwarded-for", ""],
|
|
410
|
-
["x-frame-options", "deny"],
|
|
411
|
-
["x-frame-options", "sameorigin"]
|
|
412
|
-
];
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
function decodeVarInt(buf, prefixBits, pos) {
|
|
418
|
-
var maxPrefix = (1 << prefixBits) - 1;
|
|
419
|
-
var byte = buf[pos];
|
|
420
|
-
var value = byte & maxPrefix;
|
|
421
|
-
pos++;
|
|
422
|
-
|
|
423
|
-
if (value < maxPrefix) // נגמר במרווח-הבייט הראשון
|
|
424
|
-
return { value, next: pos };
|
|
425
|
-
|
|
426
|
-
var m = 0;
|
|
427
|
-
while (true) {
|
|
428
|
-
byte = buf[pos++];
|
|
429
|
-
value += (byte & 0x7f) << m;
|
|
430
|
-
if ((byte & 0x80) === 0) break;
|
|
431
|
-
m += 7;
|
|
432
|
-
}
|
|
433
|
-
return { value, next: pos };
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
function huffmanEncode(text) {
|
|
438
|
-
var input = new TextEncoder().encode(text); // UTF-8 -> bytes
|
|
439
|
-
var bitBuffer = 0;
|
|
440
|
-
var bitLen = 0;
|
|
441
|
-
var output = [];
|
|
442
|
-
|
|
443
|
-
for (var i = 0; i < input.length; i++) {
|
|
444
|
-
var sym = input[i];
|
|
445
|
-
var code = huffman_codes[sym];
|
|
446
|
-
var nbits = huffman_bits[sym];
|
|
447
|
-
|
|
448
|
-
bitBuffer = (bitBuffer << nbits) | code;
|
|
449
|
-
bitLen += nbits;
|
|
450
|
-
|
|
451
|
-
while (bitLen >= 8) {
|
|
452
|
-
bitLen -= 8;
|
|
453
|
-
output.push((bitBuffer >> bitLen) & 0xff);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Padding: לפי התקן, ממלאים 1-ים עד סוף בייט
|
|
458
|
-
if (bitLen > 0) {
|
|
459
|
-
bitBuffer = (bitBuffer << (8 - bitLen)) | ((1 << (8 - bitLen)) - 1);
|
|
460
|
-
output.push(bitBuffer & 0xff);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
return new Uint8Array(output);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
// פונקציית פיענוח לפי עץ
|
|
469
|
-
function decodeHuffman(buf) {
|
|
470
|
-
var output = [];
|
|
471
|
-
var node = huffman_flat_decode_tables;
|
|
472
|
-
var current = 0;
|
|
473
|
-
var nbits = 0;
|
|
474
|
-
|
|
475
|
-
for (var i = 0; i < buf.length; i++) {
|
|
476
|
-
current = (current << 8) | buf[i];
|
|
477
|
-
nbits += 8;
|
|
478
|
-
|
|
479
|
-
while (nbits > 0) {
|
|
480
|
-
var bit = (current >> (nbits - 1)) & 1;
|
|
481
|
-
node = node[bit];
|
|
482
|
-
if (!node) throw new Error("Invalid Huffman encoding");
|
|
483
|
-
nbits--;
|
|
484
|
-
|
|
485
|
-
if (node.symbol !== undefined) {
|
|
486
|
-
output.push(node.symbol);
|
|
487
|
-
node = huffman_flat_decode_tables;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// בדיקה לסיומת padding חוקית (לפי התקן — רק 1s מותר בסוף)
|
|
493
|
-
var padding = (1 << nbits) - 1;
|
|
494
|
-
if ((current & padding) !== padding) {
|
|
495
|
-
throw new Error("Invalid Huffman padding");
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
return new TextDecoder().decode(Uint8Array.from(output));
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
function parse_qpack_header_block(buf) {
|
|
504
|
-
var pos = 0;
|
|
505
|
-
var headers = [];
|
|
506
|
-
|
|
507
|
-
// Required Insert Count (prefix-8)
|
|
508
|
-
var ric = decodeVarInt(buf, 8, pos);
|
|
509
|
-
pos = ric.next;
|
|
510
|
-
|
|
511
|
-
// Delta Base (prefix-7 + S-bit)
|
|
512
|
-
var firstDbByte = buf[pos];
|
|
513
|
-
var postBase = (firstDbByte & 0x80) !== 0; // S-bit
|
|
514
|
-
var db = decodeVarInt(buf, 7, pos);
|
|
515
|
-
pos = db.next;
|
|
516
|
-
|
|
517
|
-
// Base Index = RIC ± DB לפי S-bit
|
|
518
|
-
var baseIndex = postBase
|
|
519
|
-
? ric.value + db.value
|
|
520
|
-
: ric.value - db.value;
|
|
521
|
-
|
|
522
|
-
// Header Field Lines
|
|
523
|
-
while (pos < buf.length) {
|
|
524
|
-
var byte = buf[pos];
|
|
525
|
-
|
|
526
|
-
// A. Indexed Field Line – 1xxxxxxx
|
|
527
|
-
if ((byte & 0x80) === 0x80) {
|
|
528
|
-
var fromStatic = (byte & 0x40) !== 0; // T-bit
|
|
529
|
-
var idx = decodeVarInt(buf, 6, pos); // prefix-6
|
|
530
|
-
pos = idx.next;
|
|
531
|
-
headers.push({
|
|
532
|
-
type: "indexed",
|
|
533
|
-
from_static_table: fromStatic,
|
|
534
|
-
index: idx.value
|
|
535
|
-
});
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// B. Literal With Name Reference – 01xxxxxx
|
|
540
|
-
if ((byte & 0xC0) === 0x40) {
|
|
541
|
-
var neverIndexed = (byte & 0x20) !== 0; // N-bit
|
|
542
|
-
var fromStatic = (byte & 0x10) !== 0; // T-bit
|
|
543
|
-
var nameIdx = decodeVarInt(buf, 4, pos); // prefix-4
|
|
544
|
-
pos = nameIdx.next;
|
|
545
|
-
|
|
546
|
-
var valH = (buf[pos] & 0x80) !== 0;
|
|
547
|
-
var valLen = decodeVarInt(buf, 7, pos); // prefix-7
|
|
548
|
-
pos = valLen.next;
|
|
549
|
-
|
|
550
|
-
var valBytes = buf.slice(pos, pos + valLen.value);
|
|
551
|
-
pos += valLen.value;
|
|
552
|
-
var value = valH ? decodeHuffman(valBytes)
|
|
553
|
-
: new TextDecoder().decode(valBytes);
|
|
554
|
-
|
|
555
|
-
headers.push({
|
|
556
|
-
type: "literal_with_name_ref",
|
|
557
|
-
never_indexed: neverIndexed,
|
|
558
|
-
from_static_table: fromStatic,
|
|
559
|
-
name_index: nameIdx.value,
|
|
560
|
-
value
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
continue;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// C. Literal With Literal Name – 001xxxxx
|
|
567
|
-
if ((byte & 0xE0) === 0x20) {
|
|
568
|
-
var neverIndexed = (byte & 0x10) !== 0; // N-bit
|
|
569
|
-
var nameH = (byte & 0x08) !== 0; // H-bit
|
|
570
|
-
var nameLen = decodeVarInt(buf, 3, pos); // prefix-3
|
|
571
|
-
pos = nameLen.next;
|
|
572
|
-
|
|
573
|
-
var nameBytes = buf.slice(pos, pos + nameLen.value);
|
|
574
|
-
pos += nameLen.value;
|
|
575
|
-
var name = nameH ? decodeHuffman(nameBytes)
|
|
576
|
-
: new TextDecoder().decode(nameBytes);
|
|
577
|
-
|
|
578
|
-
var valH = (buf[pos] & 0x80) !== 0; // H-bit
|
|
579
|
-
var valLen = decodeVarInt(buf, 7, pos); // prefix-7
|
|
580
|
-
pos = valLen.next;
|
|
581
|
-
|
|
582
|
-
var valBytes = buf.slice(pos, pos + valLen.value);
|
|
583
|
-
pos += valLen.value;
|
|
584
|
-
var value = valH ? decodeHuffman(valBytes)
|
|
585
|
-
: new TextDecoder().decode(valBytes);
|
|
586
|
-
|
|
587
|
-
headers.push({
|
|
588
|
-
type: "literal_with_literal_name",
|
|
589
|
-
never_indexed: neverIndexed,
|
|
590
|
-
name,
|
|
591
|
-
value
|
|
592
|
-
});
|
|
593
|
-
continue;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// לא אמור להגיע לכאן – תקלה לפי התקן
|
|
597
|
-
throw new Error(
|
|
598
|
-
`Unknown header-block instruction at byte ${pos} (0x${byte.toString(16)})`
|
|
599
|
-
);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
return {
|
|
603
|
-
insert_count: ric.value,
|
|
604
|
-
delta_base: db.value,
|
|
605
|
-
post_base: postBase,
|
|
606
|
-
base_index: baseIndex,
|
|
607
|
-
headers
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
function parse_qpack_header_block_old(buf) {
|
|
613
|
-
var pos = 0;
|
|
614
|
-
var headers = [];
|
|
615
|
-
|
|
616
|
-
/* 1) Field-section prefix */
|
|
617
|
-
var ric = decodeVarInt(buf, 8, pos); // Required Insert Count (prefix-8)
|
|
618
|
-
pos = ric.next;
|
|
619
|
-
|
|
620
|
-
var db = decodeVarInt(buf, 7, pos); // Delta Base (prefix-7)
|
|
621
|
-
pos = db.next;
|
|
622
|
-
|
|
623
|
-
/* 2) Field-line representations */
|
|
624
|
-
while (pos < buf.length) {
|
|
625
|
-
var byte = buf[pos];
|
|
626
|
-
|
|
627
|
-
/* A. Indexed Field Line – 1xxxxxxx */
|
|
628
|
-
if ((byte & 0x80) === 0x80) {
|
|
629
|
-
var fromStatic = (byte & 0x40) !== 0; // T-bit
|
|
630
|
-
var idx = decodeVarInt(buf, 6, pos); // prefix-6
|
|
631
|
-
pos = idx.next;
|
|
632
|
-
headers.push({
|
|
633
|
-
type: "indexed",
|
|
634
|
-
from_static_table: fromStatic,
|
|
635
|
-
index: idx.value
|
|
636
|
-
});
|
|
637
|
-
continue;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/* B. Literal Field Line + Name Reference – 01xxxxxx */
|
|
641
|
-
if ((byte & 0xC0) === 0x40) {
|
|
642
|
-
var neverIndexed = (byte & 0x20) !== 0; // N-bit
|
|
643
|
-
var fromStatic = (byte & 0x10) !== 0; // T-bit
|
|
644
|
-
var nameIdx = decodeVarInt(buf, 4, pos); // prefix-4
|
|
645
|
-
pos = nameIdx.next;
|
|
646
|
-
|
|
647
|
-
var valH = (buf[pos] & 0x80) !== 0;
|
|
648
|
-
var valLen = decodeVarInt(buf, 7, pos); // prefix-7
|
|
649
|
-
pos = valLen.next;
|
|
650
|
-
|
|
651
|
-
var valBytes = buf.slice(pos, pos + valLen.value);
|
|
652
|
-
pos += valLen.value;
|
|
653
|
-
var value = valH ? decodeHuffman(valBytes)
|
|
654
|
-
: new TextDecoder().decode(valBytes);
|
|
655
|
-
|
|
656
|
-
headers.push({
|
|
657
|
-
type: "literal_with_name_ref",
|
|
658
|
-
never_indexed: neverIndexed,
|
|
659
|
-
from_static_table: fromStatic,
|
|
660
|
-
name_index: nameIdx.value,
|
|
661
|
-
value
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
continue;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/* C. Literal Field Line + Literal Name – 001xxxxx */
|
|
668
|
-
if ((byte & 0xE0) === 0x20) {
|
|
669
|
-
var neverIndexed = (byte & 0x10) !== 0; // N-bit
|
|
670
|
-
var nameH = (byte & 0x08) !== 0; // H-bit (שם) :contentReference[oaicite:0]{index=0}
|
|
671
|
-
var nameLen = decodeVarInt(buf, 3, pos); // prefix-3
|
|
672
|
-
pos = nameLen.next;
|
|
673
|
-
|
|
674
|
-
var nameBytes = buf.slice(pos, pos + nameLen.value);
|
|
675
|
-
pos += nameLen.value;
|
|
676
|
-
var name = nameH ? decodeHuffman(nameBytes)
|
|
677
|
-
: new TextDecoder().decode(nameBytes);
|
|
678
|
-
|
|
679
|
-
var valH = (buf[pos] & 0x80) !== 0; // H-bit (ערך)
|
|
680
|
-
var valLen = decodeVarInt(buf, 7, pos); // prefix-7
|
|
681
|
-
pos = valLen.next;
|
|
682
|
-
|
|
683
|
-
var valBytes = buf.slice(pos, pos + valLen.value);
|
|
684
|
-
pos += valLen.value;
|
|
685
|
-
var value = valH ? decodeHuffman(valBytes)
|
|
686
|
-
: new TextDecoder().decode(valBytes);
|
|
687
|
-
|
|
688
|
-
headers.push({
|
|
689
|
-
type: "literal_with_literal_name",
|
|
690
|
-
never_indexed: neverIndexed,
|
|
691
|
-
name,
|
|
692
|
-
value
|
|
693
|
-
});
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
/* לא אמור להגיע לכאן – פסילה לפי התקן */
|
|
698
|
-
throw new Error(
|
|
699
|
-
`Unknown header-block instruction at byte ${pos} (0x${byte.toString(16)})`
|
|
700
|
-
);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
return {
|
|
704
|
-
insert_count: ric.value,
|
|
705
|
-
delta_base: db.value,
|
|
706
|
-
headers: headers
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
// הנחות:
|
|
715
|
-
// - chunks: Array<Uint8Array>, לפי הסדר (head → tail)
|
|
716
|
-
// - from_offset: offset לוגי (למי שצריך; נעדכן אותו בסוף)
|
|
717
|
-
// - readVarInt(u8, off) => { value, byteLength }
|
|
718
|
-
// - concatUint8Arrays(arr) קיים אצלך
|
|
719
|
-
|
|
720
|
-
function extract_h3_frames_from_chunks(chunks, from_offset) {
|
|
721
|
-
// אם אין צ'אנקים – אין מה לפרסר
|
|
722
|
-
if (!chunks || chunks.length === 0) {
|
|
723
|
-
return { frames: [], new_from_offset: from_offset };
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
// בונים buffers החל מהמיקום הלוגי from_offset בלי לשנות את chunks
|
|
727
|
-
var buffers = [];
|
|
728
|
-
var acc = 0;
|
|
729
|
-
for (var i = 0; i < chunks.length; i++) {
|
|
730
|
-
var c = chunks[i];
|
|
731
|
-
var nextAcc = acc + c.length;
|
|
732
|
-
if (from_offset < nextAcc) {
|
|
733
|
-
// from_offset נופל לתוך הצ'אנק הזה
|
|
734
|
-
var start = from_offset - acc;
|
|
735
|
-
buffers.push(c.slice(start));
|
|
736
|
-
// כל שאר הצ'אנקים כמות שהם
|
|
737
|
-
for (var j = i + 1; j < chunks.length; j++) {
|
|
738
|
-
buffers.push(chunks[j]);
|
|
739
|
-
}
|
|
740
|
-
break;
|
|
741
|
-
}
|
|
742
|
-
acc = nextAcc;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
if (buffers.length === 0) {
|
|
746
|
-
// from_offset מעבר לסוף הנתונים שיש כרגע
|
|
747
|
-
return { frames: [], new_from_offset: from_offset };
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
var combined = concatUint8Arrays(buffers);
|
|
751
|
-
var offset = 0;
|
|
752
|
-
var frames = [];
|
|
753
|
-
|
|
754
|
-
// קריאת VarInt בטוחה מתוך 'combined' עם קידום offset מקומי
|
|
755
|
-
function safeReadVarInt() {
|
|
756
|
-
if (offset >= combined.length) return null;
|
|
757
|
-
var firstByte = combined[offset];
|
|
758
|
-
var lengthBits = firstByte >> 6; // 0..3 → 1,2,4,8 bytes
|
|
759
|
-
var neededLength = 1 << lengthBits;
|
|
760
|
-
if (offset + neededLength > combined.length) return null;
|
|
761
|
-
var res = readVarInt(combined, offset);
|
|
762
|
-
if (!res || typeof res.byteLength !== 'number') return null;
|
|
763
|
-
offset += res.byteLength;
|
|
764
|
-
return res;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
while (offset < combined.length) {
|
|
768
|
-
var startOffset = offset;
|
|
769
|
-
|
|
770
|
-
var frameType = safeReadVarInt();
|
|
771
|
-
if (!frameType) break;
|
|
772
|
-
|
|
773
|
-
var lengthInfo = safeReadVarInt();
|
|
774
|
-
if (!lengthInfo) {
|
|
775
|
-
// לא הצלחנו אפילו לקרוא את האורך – נחזור לנק' ההתחלה ונחכה לנתונים נוספים
|
|
776
|
-
offset = startOffset;
|
|
777
|
-
break;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
var payloadLength = lengthInfo.value >>> 0; // מניחים אורך עד 2^32-1
|
|
781
|
-
if (offset + payloadLength > combined.length) {
|
|
782
|
-
// פריים חלקי – rollback מלא
|
|
783
|
-
offset = startOffset;
|
|
784
|
-
break;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
var payload = combined.slice(offset, offset + payloadLength);
|
|
788
|
-
frames.push({ frame_type: frameType.value, payload: payload });
|
|
789
|
-
offset += payloadLength;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// לא משנים את chunks; רק מקדמים את from_offset לפי כמה באמת נקרא
|
|
793
|
-
return { frames: frames, new_from_offset: from_offset + offset };
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
function extract_h3_frames_from_chunks2(chunks, from_offset) {
|
|
798
|
-
var offsets = Object.keys(chunks).map(Number).sort((a, b) => a - b);
|
|
799
|
-
var buffers = [];
|
|
800
|
-
var totalLength = 0;
|
|
801
|
-
|
|
802
|
-
// מחברים את כל הצ’אנקים החל מ־from_offset
|
|
803
|
-
for (var i = 0; i < offsets.length; i++) {
|
|
804
|
-
var base = offsets[i];
|
|
805
|
-
var chunk = chunks[base];
|
|
806
|
-
if (from_offset >= base && from_offset < base + chunk.length) {
|
|
807
|
-
var start = from_offset - base;
|
|
808
|
-
var sliced = chunk.slice(start);
|
|
809
|
-
buffers.push(sliced);
|
|
810
|
-
totalLength += sliced.length;
|
|
811
|
-
|
|
812
|
-
for (var j = i + 1; j < offsets.length; j++) {
|
|
813
|
-
buffers.push(chunks[offsets[j]]);
|
|
814
|
-
totalLength += chunks[offsets[j]].length;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
if (buffers.length === 0) return { frames: [], new_from_offset: from_offset };
|
|
822
|
-
|
|
823
|
-
var combined = concatUint8Arrays(buffers);
|
|
824
|
-
var offset = 0;
|
|
825
|
-
var frames = [];
|
|
826
|
-
|
|
827
|
-
// פונקציית עזר בטוחה לקריאת VarInt
|
|
828
|
-
function safeReadVarInt() {
|
|
829
|
-
if (offset >= combined.length) return null;
|
|
830
|
-
var firstByte = combined[offset];
|
|
831
|
-
var lengthBits = firstByte >> 6;
|
|
832
|
-
var neededLength = 1 << lengthBits;
|
|
833
|
-
if (offset + neededLength > combined.length) return null;
|
|
834
|
-
var res = readVarInt(combined, offset);
|
|
835
|
-
if (!res || typeof res.byteLength !== 'number') return null;
|
|
836
|
-
offset += res.byteLength;
|
|
837
|
-
return res;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
while (offset < combined.length) {
|
|
841
|
-
var startOffset = offset;
|
|
842
|
-
|
|
843
|
-
var frameType = safeReadVarInt();
|
|
844
|
-
if (!frameType) break;
|
|
845
|
-
|
|
846
|
-
var lengthInfo = safeReadVarInt();
|
|
847
|
-
if (!lengthInfo) {
|
|
848
|
-
offset = startOffset; // rollback – אי אפשר אפילו לקרוא אורך
|
|
849
|
-
break;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
var payloadLength = lengthInfo.value;
|
|
853
|
-
if (offset + payloadLength > combined.length) {
|
|
854
|
-
offset = startOffset; // rollback
|
|
855
|
-
break;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
var payload = combined.slice(offset, offset + payloadLength);
|
|
859
|
-
frames.push({ frame_type: frameType.value, payload });
|
|
860
|
-
offset += payloadLength;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
// עדכון chunks כדי להסיר את מה שקראנו
|
|
864
|
-
if (offset > 0) {
|
|
865
|
-
var bytesToRemove = offset;
|
|
866
|
-
var newChunks = {};
|
|
867
|
-
var processed = 0;
|
|
868
|
-
var currentOffset = from_offset;
|
|
869
|
-
|
|
870
|
-
for (var k = 0; k < offsets.length; k++) {
|
|
871
|
-
var base = offsets[k];
|
|
872
|
-
var chunk = chunks[base];
|
|
873
|
-
|
|
874
|
-
if (currentOffset >= base + chunk.length) continue;
|
|
875
|
-
|
|
876
|
-
var relStart = Math.max(currentOffset - base, 0);
|
|
877
|
-
var relEnd = Math.min(chunk.length, currentOffset + bytesToRemove - base);
|
|
878
|
-
if (relEnd < chunk.length) {
|
|
879
|
-
var leftover = chunk.slice(relEnd);
|
|
880
|
-
var newBase = base + relEnd;
|
|
881
|
-
newChunks[newBase] = leftover;
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
bytesToRemove -= (relEnd - relStart);
|
|
885
|
-
if (bytesToRemove <= 0) break;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
for (var key in chunks) delete chunks[key];
|
|
889
|
-
for (var key in newChunks) chunks[key] = newChunks[key];
|
|
890
|
-
from_offset += offset;
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
return { frames, new_from_offset: from_offset };
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
function build_h3_frames(frames) {
|
|
900
|
-
var parts = [];
|
|
901
|
-
|
|
902
|
-
for (var i = 0; i < frames.length; i++) {
|
|
903
|
-
var frame = frames[i];
|
|
904
|
-
|
|
905
|
-
// כל חלק מהפריים כ־Uint8Array
|
|
906
|
-
var typeBytes = writeVarInt(frame.frame_type);
|
|
907
|
-
var lenBytes = writeVarInt(frame.payload.length);
|
|
908
|
-
var payload = frame.payload;
|
|
909
|
-
|
|
910
|
-
parts.push(typeBytes, lenBytes, payload);
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
return concatUint8Arrays(parts);
|
|
914
|
-
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
/* חישוב אורך varint לפי HPACK/QPACK (prefix-N) */
|
|
920
|
-
function computeVarIntLen(buf, pos, prefixBits) {
|
|
921
|
-
if (pos >= buf.length) return null;
|
|
922
|
-
var first = buf[pos];
|
|
923
|
-
var prefixMask = (1 << prefixBits) - 1;
|
|
924
|
-
var prefixVal = first & prefixMask;
|
|
925
|
-
|
|
926
|
-
// אם הערך קטן מהמקסימום – varint של בייט אחד
|
|
927
|
-
if (prefixVal < prefixMask) return 1;
|
|
928
|
-
|
|
929
|
-
// אחרת ממשיכים ב-Base128 עד שבייט בלי MSB=1
|
|
930
|
-
var len = 1;
|
|
931
|
-
var idx = pos + 1;
|
|
932
|
-
while (idx < buf.length) {
|
|
933
|
-
len++;
|
|
934
|
-
if ((buf[idx] & 0x80) === 0) return len; // הסתיים
|
|
935
|
-
idx++;
|
|
936
|
-
}
|
|
937
|
-
return null; // חסר נתונים
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
/* קריאה בטוחה של varint */
|
|
941
|
-
function safeDecodeVarInt(buf, posRef, prefixBits) {
|
|
942
|
-
var len = computeVarIntLen(buf, posRef.pos, prefixBits);
|
|
943
|
-
if (len === null) return null; // לא שלם
|
|
944
|
-
|
|
945
|
-
var res = decodeVarInt(buf, prefixBits, posRef.pos); // הפונקציה שלך
|
|
946
|
-
posRef.pos = res.next;
|
|
947
|
-
return res.value;
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
/* ---------- פונקציית החילוץ העיקרית ---------- */
|
|
951
|
-
|
|
952
|
-
// הנחות:
|
|
953
|
-
// - chunks: Array<Uint8Array>, לפי הסדר (head → tail)
|
|
954
|
-
// - from_offset: מספר מצטבר (רק להחזרה/מתן עקיבה)
|
|
955
|
-
// - concatUint8Arrays(arr) קיים אצלך
|
|
956
|
-
// - safeDecodeVarInt(buf, posRef, prefixBits) -> number|null (posRef.pos מתקדם בפנים)
|
|
957
|
-
// - decodeHuffman(u8) קיים אם אתה תומך בהאףמן; אחרת אפשר להחזיר שגיאה/לקרוא כ-raw
|
|
958
|
-
|
|
959
|
-
function extract_qpack_encoder_instructions_from_chunks(chunks, from_offset) {
|
|
960
|
-
// אם אין צ'אנקים – אין מה לפרסר
|
|
961
|
-
if (!chunks || chunks.length === 0) {
|
|
962
|
-
return { instructions: [], new_from_offset: from_offset };
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
// מחברים ל-buffer יחיד החל מ-from_offset, בלי לשנות את chunks
|
|
966
|
-
var buffers = [];
|
|
967
|
-
var acc = 0;
|
|
968
|
-
for (var i = 0; i < chunks.length; i++) {
|
|
969
|
-
var c = chunks[i];
|
|
970
|
-
var nextAcc = acc + c.length;
|
|
971
|
-
if (from_offset < nextAcc) {
|
|
972
|
-
// from_offset בתוך הצ'אנק הזה
|
|
973
|
-
var start = from_offset - acc;
|
|
974
|
-
buffers.push(c.slice(start));
|
|
975
|
-
// כל שאר הצ'אנקים כפי שהם
|
|
976
|
-
for (var j = i + 1; j < chunks.length; j++) {
|
|
977
|
-
buffers.push(chunks[j]);
|
|
978
|
-
}
|
|
979
|
-
break;
|
|
980
|
-
}
|
|
981
|
-
acc = nextAcc;
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
if (buffers.length === 0) {
|
|
985
|
-
// from_offset מעבר לנתונים שיש כרגע
|
|
986
|
-
return { instructions: [], new_from_offset: from_offset };
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
var combined = concatUint8Arrays(buffers);
|
|
990
|
-
var posRef = { pos: 0 };
|
|
991
|
-
var instructions = [];
|
|
992
|
-
|
|
993
|
-
// 2) לולאת פירוש הוראות QPACK-Encoder
|
|
994
|
-
while (posRef.pos < combined.length) {
|
|
995
|
-
var startPos = posRef.pos;
|
|
996
|
-
if (posRef.pos >= combined.length) break;
|
|
997
|
-
var byte = combined[posRef.pos];
|
|
998
|
-
|
|
999
|
-
// --- A. Insert With Name Reference (1xxxxxxx) ---
|
|
1000
|
-
if ((byte & 0x80) === 0x80) {
|
|
1001
|
-
var fromStatic = (byte & 0x40) !== 0;
|
|
1002
|
-
var nameIdx = safeDecodeVarInt(combined, posRef, 6);
|
|
1003
|
-
if (nameIdx === null) break; // חסר נתונים
|
|
1004
|
-
|
|
1005
|
-
// value length (Huffman flag בביט העליון של בייט האורך)
|
|
1006
|
-
if (posRef.pos >= combined.length) { posRef.pos = startPos; break; }
|
|
1007
|
-
var valHuffman = (combined[posRef.pos] & 0x80) !== 0;
|
|
1008
|
-
var valLen = safeDecodeVarInt(combined, posRef, 7);
|
|
1009
|
-
if (valLen === null || posRef.pos + valLen > combined.length) {
|
|
1010
|
-
posRef.pos = startPos; break;
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
var valBytes = combined.slice(posRef.pos, posRef.pos + valLen);
|
|
1014
|
-
posRef.pos += valLen;
|
|
1015
|
-
|
|
1016
|
-
var value = valHuffman ? decodeHuffman(valBytes)
|
|
1017
|
-
: new TextDecoder().decode(valBytes);
|
|
1018
|
-
|
|
1019
|
-
instructions.push({
|
|
1020
|
-
type: 'insert_with_name_ref',
|
|
1021
|
-
from_static_table: fromStatic,
|
|
1022
|
-
name_index: nameIdx,
|
|
1023
|
-
value: value
|
|
1024
|
-
});
|
|
1025
|
-
continue;
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
// --- B. Insert Without Name Reference (01xxxxxx) ---
|
|
1029
|
-
if ((byte & 0xC0) === 0x40) {
|
|
1030
|
-
// שים לב: בדפוס הזה ה־N-flag (שם בהאףמן) נמצא בביט 0x20 של הבייט הראשון
|
|
1031
|
-
var nameH = (byte & 0x20) !== 0;
|
|
1032
|
-
var nameLen = safeDecodeVarInt(combined, posRef, 5);
|
|
1033
|
-
if (nameLen === null || posRef.pos + nameLen > combined.length) {
|
|
1034
|
-
posRef.pos = startPos; break;
|
|
1035
|
-
}
|
|
1036
|
-
var nameBytes = combined.slice(posRef.pos, posRef.pos + nameLen);
|
|
1037
|
-
posRef.pos += nameLen;
|
|
1038
|
-
|
|
1039
|
-
// value length (Huffman flag בביט העליון של בייט האורך)
|
|
1040
|
-
if (posRef.pos >= combined.length) { posRef.pos = startPos; break; }
|
|
1041
|
-
var valH = (combined[posRef.pos] & 0x80) !== 0;
|
|
1042
|
-
var valLen2 = safeDecodeVarInt(combined, posRef, 7);
|
|
1043
|
-
if (valLen2 === null || posRef.pos + valLen2 > combined.length) {
|
|
1044
|
-
posRef.pos = startPos; break;
|
|
1045
|
-
}
|
|
1046
|
-
var valBytes2 = combined.slice(posRef.pos, posRef.pos + valLen2);
|
|
1047
|
-
posRef.pos += valLen2;
|
|
1048
|
-
|
|
1049
|
-
var nameStr = nameH ? decodeHuffman(nameBytes)
|
|
1050
|
-
: new TextDecoder().decode(nameBytes);
|
|
1051
|
-
var valueStr = valH ? decodeHuffman(valBytes2)
|
|
1052
|
-
: new TextDecoder().decode(valBytes2);
|
|
1053
|
-
|
|
1054
|
-
instructions.push({
|
|
1055
|
-
type: 'insert_without_name_ref',
|
|
1056
|
-
name: nameStr,
|
|
1057
|
-
value: valueStr
|
|
1058
|
-
});
|
|
1059
|
-
continue;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
// --- C. Set Dynamic Table Capacity (001xxxxx) ---
|
|
1063
|
-
if ((byte & 0xE0) === 0x20) {
|
|
1064
|
-
var capacity = safeDecodeVarInt(combined, posRef, 5);
|
|
1065
|
-
if (capacity === null) { posRef.pos = startPos; break; }
|
|
1066
|
-
|
|
1067
|
-
instructions.push({
|
|
1068
|
-
type: 'set_dynamic_table_capacity',
|
|
1069
|
-
capacity: capacity
|
|
1070
|
-
});
|
|
1071
|
-
continue;
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
// --- D. Duplicate (0000xxxx) ---
|
|
1075
|
-
if ((byte & 0xF0) === 0x00) {
|
|
1076
|
-
var dupIndex = safeDecodeVarInt(combined, posRef, 4);
|
|
1077
|
-
if (dupIndex === null) { posRef.pos = startPos; break; }
|
|
1078
|
-
|
|
1079
|
-
instructions.push({
|
|
1080
|
-
type: 'duplicate',
|
|
1081
|
-
index: dupIndex
|
|
1082
|
-
});
|
|
1083
|
-
continue;
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
// אופקוד לא מוכר או לא נתמך – נעצור עד שיגיע עוד מידע / נטפל חיצונית
|
|
1087
|
-
break;
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
// כמה בייטים פרשנו מתוך ה־view המאוחד
|
|
1091
|
-
var consumed = posRef.pos | 0;
|
|
1092
|
-
|
|
1093
|
-
// לא משנים את chunks; רק מקדמים offset לוגי
|
|
1094
|
-
return { instructions: instructions, new_from_offset: from_offset + consumed };
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
function extract_qpack_encoder_instructions_from_chunks2(chunks, from_offset) {
|
|
1099
|
-
/* 1) חיבור הצ’אנקים החל מ-from_offset */
|
|
1100
|
-
var offsets = Object.keys(chunks).map(Number).sort(function (a, b) { return a - b; });
|
|
1101
|
-
var buffers = [];
|
|
1102
|
-
var totalLen = 0;
|
|
1103
|
-
|
|
1104
|
-
for (var i = 0; i < offsets.length; i++) {
|
|
1105
|
-
var base = offsets[i];
|
|
1106
|
-
var chunk = chunks[base];
|
|
1107
|
-
if (from_offset >= base && from_offset < base + chunk.length) {
|
|
1108
|
-
var start = from_offset - base;
|
|
1109
|
-
var sliced = chunk.slice(start);
|
|
1110
|
-
buffers.push(sliced);
|
|
1111
|
-
totalLen += sliced.length;
|
|
1112
|
-
|
|
1113
|
-
for (var j = i + 1; j < offsets.length; j++) {
|
|
1114
|
-
buffers.push(chunks[offsets[j]]);
|
|
1115
|
-
totalLen += chunks[offsets[j]].length;
|
|
1116
|
-
}
|
|
1117
|
-
break;
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
if (buffers.length === 0) {
|
|
1122
|
-
return { instructions: [], new_from_offset: from_offset };
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
var combined = concatUint8Arrays(buffers);
|
|
1126
|
-
var posRef = { pos: 0 };
|
|
1127
|
-
var instructions = [];
|
|
1128
|
-
|
|
1129
|
-
/* 2) לולאת פיענוח ההוראות */
|
|
1130
|
-
while (posRef.pos < combined.length) {
|
|
1131
|
-
var startPos = posRef.pos;
|
|
1132
|
-
var byte = combined[posRef.pos];
|
|
1133
|
-
|
|
1134
|
-
/* --- A. Insert With Name Reference (1xxxxxxx) --- */
|
|
1135
|
-
if ((byte & 0x80) === 0x80) {
|
|
1136
|
-
var fromStatic = (byte & 0x40) !== 0;
|
|
1137
|
-
var nameIdx = safeDecodeVarInt(combined, posRef, 6);
|
|
1138
|
-
if (nameIdx === null) break; // לא שלם
|
|
1139
|
-
|
|
1140
|
-
// value length
|
|
1141
|
-
var valHuffman = (combined[posRef.pos] & 0x80) !== 0;
|
|
1142
|
-
var valLen = safeDecodeVarInt(combined, posRef, 7);
|
|
1143
|
-
if (valLen === null || posRef.pos + valLen > combined.length) {
|
|
1144
|
-
posRef.pos = startPos; break;
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
var valBytes = combined.slice(posRef.pos, posRef.pos + valLen);
|
|
1148
|
-
posRef.pos += valLen;
|
|
1149
|
-
|
|
1150
|
-
var value = valHuffman ? decodeHuffman(valBytes)
|
|
1151
|
-
: new TextDecoder().decode(valBytes);
|
|
1152
|
-
|
|
1153
|
-
instructions.push({
|
|
1154
|
-
type: 'insert_with_name_ref',
|
|
1155
|
-
from_static_table: fromStatic,
|
|
1156
|
-
name_index: nameIdx,
|
|
1157
|
-
value: value
|
|
1158
|
-
});
|
|
1159
|
-
continue;
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
/* --- B. Insert Without Name Reference (01xxxxxx) --- */
|
|
1163
|
-
if ((byte & 0xC0) === 0x40) {
|
|
1164
|
-
var nameH = (byte & 0x20) !== 0;
|
|
1165
|
-
var nameLen = safeDecodeVarInt(combined, posRef, 5);
|
|
1166
|
-
if (nameLen === null || posRef.pos + nameLen > combined.length) {
|
|
1167
|
-
posRef.pos = startPos; break;
|
|
1168
|
-
}
|
|
1169
|
-
var nameBytes = combined.slice(posRef.pos, posRef.pos + nameLen);
|
|
1170
|
-
posRef.pos += nameLen;
|
|
1171
|
-
|
|
1172
|
-
var valH = (combined[posRef.pos] & 0x80) !== 0;
|
|
1173
|
-
var valLen2 = safeDecodeVarInt(combined, posRef, 7);
|
|
1174
|
-
if (valLen2 === null || posRef.pos + valLen2 > combined.length) {
|
|
1175
|
-
posRef.pos = startPos; break;
|
|
1176
|
-
}
|
|
1177
|
-
var valBytes2 = combined.slice(posRef.pos, posRef.pos + valLen2);
|
|
1178
|
-
posRef.pos += valLen2;
|
|
1179
|
-
|
|
1180
|
-
var nameStr = nameH ? decodeHuffman(nameBytes)
|
|
1181
|
-
: new TextDecoder().decode(nameBytes);
|
|
1182
|
-
var valueStr = valH ? decodeHuffman(valBytes2)
|
|
1183
|
-
: new TextDecoder().decode(valBytes2);
|
|
1184
|
-
|
|
1185
|
-
instructions.push({
|
|
1186
|
-
type: 'insert_without_name_ref',
|
|
1187
|
-
name: nameStr,
|
|
1188
|
-
value: valueStr
|
|
1189
|
-
});
|
|
1190
|
-
continue;
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
/* --- C. Set Dynamic Table Capacity (001xxxxx) --- */
|
|
1194
|
-
if ((byte & 0xE0) === 0x20) {
|
|
1195
|
-
var capacity = safeDecodeVarInt(combined, posRef, 5);
|
|
1196
|
-
if (capacity === null) { posRef.pos = startPos; break; }
|
|
1197
|
-
|
|
1198
|
-
instructions.push({
|
|
1199
|
-
type: 'set_dynamic_table_capacity',
|
|
1200
|
-
capacity: capacity
|
|
1201
|
-
});
|
|
1202
|
-
continue;
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
/* --- D. Duplicate (0000xxxx) --- */
|
|
1206
|
-
if ((byte & 0xF0) === 0x00) {
|
|
1207
|
-
var dupIndex = safeDecodeVarInt(combined, posRef, 4);
|
|
1208
|
-
if (dupIndex === null) { posRef.pos = startPos; break; }
|
|
1209
|
-
|
|
1210
|
-
instructions.push({
|
|
1211
|
-
type: 'duplicate',
|
|
1212
|
-
index: dupIndex
|
|
1213
|
-
});
|
|
1214
|
-
continue;
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
/* לא מוכר - נעצור */
|
|
1218
|
-
break;
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
var consumed = posRef.pos; // כמה בייטים הצלחנו לפרש
|
|
1222
|
-
|
|
1223
|
-
/* 3) ניקוי הצ’אנקים והתקדמות from_offset */
|
|
1224
|
-
if (consumed > 0) {
|
|
1225
|
-
var bytesLeft = consumed;
|
|
1226
|
-
var newChunks = {};
|
|
1227
|
-
var currOff = from_offset;
|
|
1228
|
-
|
|
1229
|
-
for (var k = 0; k < offsets.length; k++) {
|
|
1230
|
-
var base = offsets[k];
|
|
1231
|
-
var chunk = chunks[base];
|
|
1232
|
-
|
|
1233
|
-
if (currOff >= base + chunk.length) continue;
|
|
1234
|
-
|
|
1235
|
-
var relStart = Math.max(currOff - base, 0);
|
|
1236
|
-
var relEnd = Math.min(chunk.length, currOff + bytesLeft - base);
|
|
1237
|
-
|
|
1238
|
-
if (relEnd < chunk.length) {
|
|
1239
|
-
var leftover = chunk.slice(relEnd);
|
|
1240
|
-
newChunks[base + relEnd] = leftover;
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
bytesLeft -= (relEnd - relStart);
|
|
1244
|
-
if (bytesLeft <= 0) break;
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
for (var key in chunks) delete chunks[key];
|
|
1248
|
-
for (var nk in newChunks) chunks[nk] = newChunks[nk];
|
|
1249
|
-
|
|
1250
|
-
from_offset += consumed;
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
return { instructions: instructions, new_from_offset: from_offset };
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
var h3_settings_frame_params = [
|
|
1259
|
-
[0x01, "SETTINGS_QPACK_MAX_TABLE_CAPACITY"],
|
|
1260
|
-
[0x06, "SETTINGS_MAX_FIELD_SECTION_SIZE"],
|
|
1261
|
-
[0x07, "SETTINGS_QPACK_BLOCKED_STREAMS"],
|
|
1262
|
-
[0x08, "SETTINGS_ENABLE_CONNECT_PROTOCOL"],
|
|
1263
|
-
[0x33, "SETTINGS_H3_DATAGRAM"],
|
|
1264
|
-
[0x2b603742, "SETTINGS_ENABLE_WEBTRANSPORT"], // תקני לפי draft
|
|
1265
|
-
[0x0d, "SETTINGS_NO_RFC9114_LEGACY_CODEPOINT"],
|
|
1266
|
-
[0x14E9CD29, "SETTINGS_WT_MAX_SESSIONS"],
|
|
1267
|
-
[0x4d44, "SETTINGS_ENABLE_METADATA"] // provisional
|
|
1268
|
-
];
|
|
1269
|
-
|
|
1270
|
-
var h3_name_to_id = {};
|
|
1271
|
-
var h3_id_to_name = {};
|
|
1272
|
-
|
|
1273
|
-
for (var i = 0; i < h3_settings_frame_params.length; i++) {
|
|
1274
|
-
var [id, name] = h3_settings_frame_params[i];
|
|
1275
|
-
h3_name_to_id[name] = id;
|
|
1276
|
-
h3_id_to_name[id] = name;
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
function parse_h3_settings_frame(buf) {
|
|
1282
|
-
var settings = {};
|
|
1283
|
-
var offset = 0;
|
|
1284
|
-
|
|
1285
|
-
while (offset < buf.length) {
|
|
1286
|
-
var idRes = readVarInt(buf, offset);
|
|
1287
|
-
if (!idRes) break;
|
|
1288
|
-
offset += idRes.byteLength;
|
|
1289
|
-
|
|
1290
|
-
var valRes = readVarInt(buf, offset);
|
|
1291
|
-
if (!valRes) break;
|
|
1292
|
-
offset += valRes.byteLength;
|
|
1293
|
-
|
|
1294
|
-
var id = idRes.value;
|
|
1295
|
-
var value = valRes.value;
|
|
1296
|
-
|
|
1297
|
-
var name = h3_id_to_name[id] || `UNKNOWN_0x${id.toString(16)}`;
|
|
1298
|
-
settings[name] = value;
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
return settings;
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
function build_settings_frame(settings_named) {
|
|
1306
|
-
var frame_payload = [];
|
|
1307
|
-
|
|
1308
|
-
for (var name in settings_named) {
|
|
1309
|
-
var id = h3_name_to_id[name];
|
|
1310
|
-
if (id === undefined) {
|
|
1311
|
-
throw new Error("Unknown setting name: " + name);
|
|
1312
|
-
}
|
|
1313
|
-
var value = settings_named[name];
|
|
1314
|
-
|
|
1315
|
-
frame_payload.push(...writeVarInt(id));
|
|
1316
|
-
frame_payload.push(...writeVarInt(value));
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
return new Uint8Array(frame_payload);
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
function build_control_stream_old(settings_named) {
|
|
1325
|
-
var setting_ids = {
|
|
1326
|
-
SETTINGS_QPACK_MAX_TABLE_CAPACITY: 0x01,
|
|
1327
|
-
SETTINGS_MAX_FIELD_SECTION_SIZE: 0x06,
|
|
1328
|
-
SETTINGS_ENABLE_WEBTRANSPORT: 0x2b603742, // תקני לפי draft
|
|
1329
|
-
SETTINGS_H3_DATAGRAM: 0x33, // תקני לפי RFC 9297
|
|
1330
|
-
SETTINGS_NO_RFC9114_LEGACY_CODEPOINT: 0x0d,
|
|
1331
|
-
SETTINGS_ENABLE_CONNECT_PROTOCOL: 0x08, // תקני לפי RFC 9220
|
|
1332
|
-
SETTINGS_WT_MAX_SESSIONS: 0x14E9CD29
|
|
1333
|
-
};
|
|
1334
|
-
|
|
1335
|
-
var frame_payload = [];
|
|
1336
|
-
|
|
1337
|
-
for (var name in settings_named) {
|
|
1338
|
-
var id = setting_ids[name];
|
|
1339
|
-
if (id === undefined) {
|
|
1340
|
-
throw new Error("Unknown setting name: " + name);
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
var value = settings_named[name];
|
|
1344
|
-
frame_payload.push(...writeVarInt(id));
|
|
1345
|
-
frame_payload.push(...writeVarInt(value));
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
var frame_header = [
|
|
1349
|
-
...writeVarInt(0x04), // SETTINGS frame type
|
|
1350
|
-
...writeVarInt(frame_payload.length)
|
|
1351
|
-
];
|
|
1352
|
-
|
|
1353
|
-
return new Uint8Array([
|
|
1354
|
-
0x00, // Stream Type: Control Stream
|
|
1355
|
-
...frame_header,
|
|
1356
|
-
...frame_payload
|
|
1357
|
-
]);
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
function encodeInt(value, prefixBits) {
|
|
1362
|
-
var max = (1 << prefixBits) - 1;
|
|
1363
|
-
if (value < max) return [value]; // נכנס כולו בפריפיקס
|
|
1364
|
-
var bytes = [max];
|
|
1365
|
-
value -= max;
|
|
1366
|
-
while (value >= 128) { // המשך varint (7-bit groups)
|
|
1367
|
-
bytes.push((value & 0x7F) | 0x80);
|
|
1368
|
-
value >>= 7;
|
|
1369
|
-
}
|
|
1370
|
-
bytes.push(value);
|
|
1371
|
-
return bytes;
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
function encodeStringLiteral(bytes, hFlag /* 0/1 */) {
|
|
1375
|
-
var lenBytes = encodeInt(bytes.length, 7); // prefix-7
|
|
1376
|
-
lenBytes[0] |= (hFlag << 7); // מוסיפים H
|
|
1377
|
-
return lenBytes.concat(Array.from(bytes));
|
|
1378
|
-
}
|
|
1379
|
-
|
|
1380
|
-
/* ---------- בניית HEADERS (Literal) ---------- */
|
|
1381
|
-
function build_http3_literal_headers_frame(headers) {
|
|
1382
|
-
var out = [];
|
|
1383
|
-
out.push(0x00, 0x00); // QPACK prefix
|
|
1384
|
-
|
|
1385
|
-
for (var header_name in headers) {
|
|
1386
|
-
var nameBytes = new TextEncoder().encode(header_name.toLowerCase());
|
|
1387
|
-
var valueBytes = new TextEncoder().encode(String(headers[header_name]));
|
|
1388
|
-
|
|
1389
|
-
/* בייט ראשון: 001 | N=0 | H=0 | NameLen(3+) */
|
|
1390
|
-
var nameLenEnc = encodeInt(nameBytes.length, 3); // prefix-3
|
|
1391
|
-
var firstByte = 0x20 | nameLenEnc[0]; // 0b0010_0000
|
|
1392
|
-
out.push(firstByte, ...nameLenEnc.slice(1), ...nameBytes);
|
|
1393
|
-
|
|
1394
|
-
/* value: H=0 + prefix-7 */
|
|
1395
|
-
out.push(...encodeStringLiteral(valueBytes, 0));
|
|
1396
|
-
}
|
|
1397
|
-
return new Uint8Array(out);
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
function build_qpack_block_header_ack(stream_id) {
|
|
1402
|
-
return concatUint8Arrays([
|
|
1403
|
-
Uint8Array.from([0x81]), // instruction type
|
|
1404
|
-
writeVarInt(stream_id) // full VarInt
|
|
1405
|
-
]);
|
|
1406
|
-
}
|
|
1407
|
-
function build_qpack_known_received_count(count) {
|
|
1408
|
-
if (count <= 0) return null; // אין מה לשלוח
|
|
1409
|
-
var buf = writeVarInt(count); // VarInt עם prefix-6
|
|
1410
|
-
buf[0] &= 0x3F; // מוודא ששני הביטים העליונים 00
|
|
1411
|
-
return buf;
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
function parse_webtransport_datagram(payload) {
|
|
1416
|
-
var result = readVarInt(payload, 0);
|
|
1417
|
-
if (!result) {
|
|
1418
|
-
throw new Error("Invalid VarInt at beginning of payload");
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
var stream_id = result.value;
|
|
1422
|
-
var data = payload.slice(result.byteLength); // שאר ה־payload זה הנתונים
|
|
1423
|
-
|
|
1424
|
-
return {
|
|
1425
|
-
stream_id: stream_id,
|
|
1426
|
-
data: data
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
function build_close_webtransport(errorCode, reason) {
|
|
1432
|
-
var reasonBytes = reason ? new TextEncoder().encode(reason) : new Uint8Array();
|
|
1433
|
-
var payload = [
|
|
1434
|
-
...writeVarInt(errorCode),
|
|
1435
|
-
...writeVarInt(reasonBytes.length),
|
|
1436
|
-
...reasonBytes
|
|
1437
|
-
];
|
|
1438
|
-
|
|
1439
|
-
var frame = [
|
|
1440
|
-
...writeVarInt(0x2843), // type
|
|
1441
|
-
...writeVarInt(payload.length), // length
|
|
1442
|
-
...payload
|
|
1443
|
-
];
|
|
1444
|
-
|
|
1445
|
-
return new Uint8Array(frame);
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
export {
|
|
1449
|
-
build_h3_frames,
|
|
1450
|
-
build_settings_frame,
|
|
1451
|
-
parse_h3_settings_frame,
|
|
1452
|
-
extract_qpack_encoder_instructions_from_chunks,
|
|
1453
|
-
extract_h3_frames_from_chunks,
|
|
1454
|
-
parse_qpack_header_block,
|
|
1455
|
-
build_http3_literal_headers_frame,
|
|
1456
|
-
parse_webtransport_datagram,
|
|
1457
|
-
build_close_webtransport,
|
|
1458
|
-
build_qpack_block_header_ack,
|
|
1459
|
-
build_qpack_known_received_count,
|
|
1460
|
-
qpack_static_table_entries
|
|
1461
|
-
};
|