quico 0.1.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/index.js ADDED
@@ -0,0 +1,2631 @@
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
+ var process = require('process');
20
+ var dgram = require('dgram');
21
+ var flat_ranges = require('flat-ranges');
22
+ var crypto = require('crypto');
23
+
24
+ var { sha256, sha384 } = require('@noble/hashes/sha2');
25
+
26
+ var {
27
+ concatUint8Arrays,
28
+ arraybufferEqual,
29
+ quic_acked_info_to_ranges,
30
+ build_ack_info_from_ranges,
31
+ readVarInt,
32
+ writeVarInt
33
+ } = require('./libs/utils');
34
+
35
+ var {
36
+ get_cipher_info,
37
+ build_certificate,
38
+ decrypt_quic_packet,
39
+ quic_derive_init_secrets,
40
+ quic_derive_from_tls_secrets,
41
+ parse_tls_message,
42
+ parse_tls_client_hello,
43
+ build_server_hello,
44
+ tls_derive_handshake_secrets,
45
+ build_quic_ext,
46
+ build_encrypted_extensions,
47
+ hkdf_expand_label,
48
+ hmac,
49
+ hash_transcript,
50
+ handle_client_hello,
51
+ build_certificate_verify,
52
+ encode_quic_frames,
53
+ encrypt_quic_packet,
54
+ parse_quic_datagram,
55
+ parse_quic_packet,
56
+ parse_quic_frames,
57
+ extract_tls_messages_from_chunks,
58
+ build_alpn_ext,
59
+ build_finished,
60
+ tls_derive_app_secrets,
61
+ parse_transport_parameters
62
+ } = require('./libs/crypto');
63
+
64
+ var {
65
+ build_h3_frames,
66
+ build_settings_frame,
67
+ parse_h3_settings_frame,
68
+ extract_qpack_encoder_instructions_from_chunks,
69
+ extract_h3_frames_from_chunks,
70
+ parse_qpack_header_block,
71
+ build_http3_literal_headers_frame,
72
+ parse_webtransport_datagram,
73
+ qpack_static_table_entries
74
+ } = require('./libs/h3');
75
+
76
+
77
+ var new_quic_connection = {
78
+ connection_status: 4,//0 - connecting... | 1 - connected | 2 - disconnected | ...
79
+
80
+ from_ip: null,
81
+ from_port: null,
82
+
83
+ version: 1,
84
+
85
+ my_cids: [], // SCIDים שאתה נתת (כנראה אחד ראשוני ועוד future)
86
+ their_cids: [], // DCIDים שהצד השני השתמש בהם (כלומר שלך כשרת)
87
+ original_dcid: null, // ל־Initial ול־Retry
88
+
89
+ //tls stuff...
90
+ sni: null,
91
+
92
+ tls_cipher_selected: null,
93
+ tls_alpn_selected: null,
94
+
95
+ tls_signature_algorithms: [],
96
+
97
+ tls_handshake_secret: null,
98
+ tls_shared_secret: null,
99
+ tls_early_secret: null,
100
+
101
+ tls_transcript: [],
102
+ tls_handshake_step: 0,
103
+ tls_finished_ok: false,
104
+
105
+ tls_server_public_key: null,
106
+ tls_server_private_key: null,
107
+
108
+ tls_client_handshake_traffic_secret: null,
109
+ tls_server_handshake_traffic_secret: null,
110
+
111
+ tls_client_app_traffic_secret: null,
112
+ tls_server_app_traffic_secret: null,
113
+
114
+
115
+ //....
116
+ init_read_key: null,
117
+ init_read_iv: null,
118
+ init_read_hp: null,
119
+
120
+ init_write_key: null,
121
+ init_write_iv: null,
122
+ init_write_hp: null,
123
+
124
+ handshake_read_key: null,
125
+ handshake_read_iv: null,
126
+ handshake_read_hp: null,
127
+
128
+ handshake_write_key: null,
129
+ handshake_write_iv: null,
130
+ handshake_write_hp: null,
131
+
132
+ app_prev_read_key: null,
133
+ app_prev_read_iv: null,
134
+ app_prev_read_hp: null,
135
+
136
+ app_read_key: null,
137
+ app_read_iv: null,
138
+ app_read_hp: null,
139
+
140
+ read_key_phase: false,
141
+
142
+ app_write_key: null,
143
+ app_write_iv: null,
144
+ app_write_hp: null,
145
+
146
+
147
+
148
+
149
+ //sending...
150
+
151
+ sending_init_pn_next: 1,
152
+ sending_init_chunks: [],
153
+ sending_init_offset_next: 0,
154
+ sending_init_pn_acked_ranges: [],
155
+
156
+ sending_handshake_pn_next: 1,
157
+ sending_handshake_chunks: [],
158
+ sending_handshake_offset_next: 0,
159
+ sending_handshake_pn_acked_ranges: [],
160
+
161
+
162
+ sending_streams: {},
163
+ sending_stream_id_next: 0,
164
+
165
+
166
+
167
+ max_sending_packets_per_sec: 1000,
168
+ max_sending_total_bytes_per_sec: 150000,
169
+ max_sending_packet_size: 1200,
170
+ min_sending_packet_size: 35,
171
+
172
+ max_sending_packets_in_flight: 20,
173
+ max_sending_bytes_in_flight: 150000,
174
+
175
+ sending_app_pn_base: 1,
176
+ sending_app_pn_history: [],
177
+ rtt_history: [],
178
+ sending_app_pn_in_flight: new Set(),
179
+
180
+ next_send_quic_packet_timer: null,
181
+ sending_quic_packet_now: false,
182
+
183
+
184
+ //received...
185
+
186
+ receiving_init_pn_largest: -1,
187
+ receiving_init_pn_ranges: [],
188
+ receiving_init_chunks: {},
189
+ receiving_init_from_offset: 0,
190
+ receiving_init_ranges: [],//מערך שטוח של מ עד
191
+
192
+ receiving_handshake_pn_largest: -1,
193
+ receiving_handshake_pn_ranges: [],
194
+ receiving_handshake_chunks: {},
195
+ receiving_handshake_from_offset: 0,
196
+ receiving_handshake_ranges: [],//מערך שטוח של מ עד
197
+
198
+ receiving_app_pn_largest: -1,
199
+ receiving_app_pn_ranges: [],
200
+ receiving_app_pn_history: [],
201
+
202
+ receiving_app_pn_pending_ack: [],
203
+
204
+
205
+ receiving_streams: {}, // stream_id → stream object
206
+ receiving_streams_next_check_timer: null,
207
+
208
+
209
+ remote_ack_delay_exponent: 3,
210
+ remote_max_udp_payload_size: 1000,
211
+
212
+ h3_remote_control_stream_id: null,
213
+ h3_remote_control_from_offset: 1,
214
+
215
+ h3_remote_qpack_encoder_stream_id: null,
216
+ h3_remote_qpack_encoder_from_offset: 1,
217
+
218
+ h3_remote_qpack_decoder_stream_id: null,
219
+ h3_remote_qpack_decoder_from_offset: 1,
220
+
221
+
222
+ h3_http_request_streams: {},
223
+
224
+
225
+ h3_remote_max_header_size: 0,//מתקבל ב settings - אחרי פיענוח
226
+ h3_remote_qpack_max_table_capacity: 0,//מתקבל ב settings - גודל הטבלה המקסימלי
227
+ h3_remote_datagram_support: null,
228
+
229
+ h3_remote_qpack_table_base_index: 0,
230
+ h3_remote_qpack_table_capacity: 0,
231
+ h3_remote_qpack_dynamic_table: [],
232
+
233
+
234
+ h3_wt_sessions: {}
235
+
236
+ // 🗺️ congestion control / flow control (אפשר להוסיף בהמשך)
237
+ };
238
+
239
+
240
+ function evict_qpack_remote_dynamic_table_if_needed(server, quic_connection_id){
241
+ if(quic_connection_id in server.connections==true){
242
+
243
+ var connection = server.connections[quic_connection_id];
244
+ var entries = connection.h3_remote_qpack_dynamic_table;
245
+ var capacity = connection.h3_remote_qpack_table_capacity;
246
+
247
+ // חישוב גודל כולל של כל הערכים בטבלה
248
+ var totalSize = 0;
249
+ for (var i = 0; i < entries.length; i++) {
250
+ var name = entries[i][0];
251
+ var value = entries[i][1];
252
+ totalSize += name.length + value.length + 32;
253
+ }
254
+
255
+ // הדחה של ערכים ישנים עד שהטבלה בגבולות המותר
256
+ while (totalSize > capacity && entries.length > 0) {
257
+ var removed = entries.pop(); // מסיר את הערך האחרון
258
+ var removedSize = removed[0].length + removed[1].length + 32;
259
+ totalSize -= removedSize;
260
+ }
261
+
262
+ }
263
+ }
264
+
265
+ function insert_into_qpack_remote_encoder_dynamic_table(server, quic_connection_id, name, value){
266
+ if(quic_connection_id in server.connections==true){
267
+ var entry_size = name.length + value.length + 32;
268
+
269
+ if (entry_size > server.connections[quic_connection_id].h3_remote_qpack_table_capacity) return false;
270
+
271
+ server.connections[quic_connection_id].h3_remote_qpack_dynamic_table.unshift([name, value]);
272
+ server.connections[quic_connection_id].h3_remote_qpack_table_base_index++;
273
+
274
+ evict_qpack_remote_dynamic_table_if_needed(server, quic_connection_id);
275
+
276
+ return true;
277
+
278
+ }
279
+ }
280
+
281
+ function create_wt_session_object(server, quic_connection_id, stream_id, headers) {
282
+ var wt = {
283
+ id: stream_id,
284
+ //quic_connection: conn_id,
285
+
286
+ headers: {},
287
+
288
+ send: function(data) {
289
+ send_quic_frames_packet(server,quic_connection_id,'1rtt',[{
290
+ type: 'datagram',
291
+ data: concatUint8Arrays([writeVarInt(Number(stream_id)),data])
292
+ }]);
293
+ },
294
+
295
+ close: function() {
296
+ wt._internal.isOpen = false;
297
+ // שלח CONTROL_FRAME של סוג close אם צריך
298
+ },
299
+
300
+ onmessage: null,
301
+ onclose: null,
302
+ onerror: null,
303
+ onstream: null,
304
+
305
+ _internal: {
306
+ incoming_uni_streams: {},
307
+ outgoing_uni_streams: {},
308
+ control_stream_id: stream_id,
309
+ isOpen: true
310
+ }
311
+ };
312
+
313
+ return wt;
314
+ }
315
+
316
+
317
+ function build_response_object(server, quic_connection_id, stream_id) {
318
+ return {
319
+
320
+ statusCode: null,
321
+ headersSent: false,
322
+ socket: null,
323
+
324
+ writeHead: function(statusCode, headers) {
325
+
326
+ for(var header_name in headers){
327
+ server.connections[quic_connection_id].h3_http_request_streams[stream_id].response_headers[header_name]=headers[header_name];
328
+ }
329
+
330
+ if(":status" in server.connections[quic_connection_id].h3_http_request_streams[stream_id].response_headers==false){
331
+ server.connections[quic_connection_id].h3_http_request_streams[stream_id].response_headers[":status"]=statusCode;
332
+
333
+ var headers_payload = build_http3_literal_headers_frame(server.connections[quic_connection_id].h3_http_request_streams[stream_id].response_headers);
334
+
335
+ var http3_response=build_h3_frames([
336
+ { frame_type: 1, payload: headers_payload }
337
+ ]);
338
+
339
+ quic_stream_write(server,quic_connection_id,Number(stream_id),http3_response,false);
340
+
341
+ }
342
+ },
343
+
344
+ writeEarlyHints: function (hints){
345
+
346
+ },
347
+
348
+ write: function(chunk) {
349
+ var http3_response=build_h3_frames([
350
+ { frame_type: 0, payload: chunk }
351
+ ]);
352
+
353
+ quic_stream_write(server,quic_connection_id,Number(stream_id),http3_response,false);
354
+ },
355
+
356
+ end: function(chunk) {
357
+
358
+ if(typeof chunk!=='undefined'){
359
+ var http3_response=build_h3_frames([
360
+ { frame_type: 0, payload: chunk }
361
+ ]);
362
+
363
+ quic_stream_write(server,quic_connection_id,Number(stream_id),http3_response,true);
364
+ }else{
365
+ quic_stream_write(server,quic_connection_id,Number(stream_id),new Uint8Array(0),true);
366
+ }
367
+
368
+
369
+
370
+ }
371
+ };
372
+ }
373
+
374
+ function process_quic_receiving_streams(server,quic_connection_id){
375
+ if(quic_connection_id in server.connections==true){
376
+
377
+ for(var stream_id in server.connections[quic_connection_id].receiving_streams){
378
+ if(server.connections[quic_connection_id].receiving_streams[stream_id].need_check==true){
379
+ server.connections[quic_connection_id].receiving_streams[stream_id].need_check=false;
380
+
381
+ var stream_type=null;
382
+
383
+ if(server.connections[quic_connection_id].h3_remote_control_stream_id==Number(stream_id)){
384
+ stream_type=0;
385
+ }else if(server.connections[quic_connection_id].h3_remote_qpack_encoder_stream_id==Number(stream_id)){
386
+ stream_type=2;
387
+ }else if(server.connections[quic_connection_id].h3_remote_qpack_decoder_stream_id==Number(stream_id)){
388
+ stream_type=3;
389
+ }else{
390
+
391
+ }
392
+
393
+ if(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_ranges.length>=2){
394
+
395
+ var is_unidirectional = (Number(stream_id) % 2 === 0) !== (Number(stream_id) % 4 === 0);
396
+ if (is_unidirectional) {
397
+
398
+ if(stream_type==null && '0' in server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks){
399
+
400
+ var first_byte=server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks[0][0];
401
+
402
+ switch (first_byte) {
403
+ case 0x00:
404
+ //console.log("✅ Control Stream");
405
+ server.connections[quic_connection_id].h3_remote_control_stream_id=Number(stream_id);
406
+ stream_type=0;
407
+ break;
408
+ case 0x01:
409
+ //console.log("✅ Push Stream");
410
+ //...
411
+ break;
412
+ case 0x02:
413
+ //console.log("✅ QPACK Encoder Stream");
414
+ server.connections[quic_connection_id].h3_remote_qpack_encoder_stream_id=Number(stream_id);
415
+ stream_type=2;
416
+ break;
417
+ case 0x03:
418
+ //console.log("✅ QPACK Decoder Stream");
419
+ server.connections[quic_connection_id].h3_remote_qpack_decoder_stream_id=Number(stream_id);
420
+ stream_type=3;
421
+ break;
422
+ default:
423
+ //console.log("❓ Unknown Unidirectional Stream");
424
+ }
425
+ }
426
+
427
+ } else {
428
+ stream_type=4;
429
+
430
+ //console.log("🔄 Bidirectional (HTTP Request/Response)");
431
+
432
+
433
+ /*
434
+ g_events.emit(['set_sending_quic_chunk',quic_connection_id,{
435
+ type: '1rtt',
436
+ stream_id: 0,
437
+ fin: true,
438
+ data: headersFrame
439
+ }]);
440
+ */
441
+ }
442
+
443
+ //console.log(server.connections[quic_connection_id]);
444
+
445
+ //console.log("--------------------------------------------");
446
+
447
+ }
448
+
449
+
450
+ if(stream_type!==null){
451
+
452
+ //console.log('h3_frames:::::::::::::::');
453
+
454
+ }
455
+
456
+ if(stream_type==0){
457
+
458
+ //console.log('control stream from chunks:');
459
+ //console.log(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks);
460
+
461
+ //console.dir(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks, { maxArrayLength: null });
462
+
463
+
464
+ //console.log('from offset: '+server.connections[quic_connection_id].h3_remote_control_from_offset);
465
+
466
+ var ext=extract_h3_frames_from_chunks(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks,server.connections[quic_connection_id].h3_remote_control_from_offset);
467
+ server.connections[quic_connection_id].h3_remote_control_from_offset=ext.new_from_offset;
468
+ var h3_frames=ext.frames;
469
+
470
+ if(h3_frames.length>0){
471
+ //console.log('frames: ');
472
+ //console.log(h3_frames);
473
+
474
+ for(var i in h3_frames){
475
+ if(h3_frames[i].frame_type==4){
476
+ //console.log('parse_h3_settings_frame:');
477
+ var control_settings=parse_h3_settings_frame(h3_frames[i].payload);
478
+ //console.log(control_settings);
479
+
480
+ if('SETTINGS_QPACK_MAX_TABLE_CAPACITY' in control_settings && control_settings['SETTINGS_QPACK_MAX_TABLE_CAPACITY']>0){
481
+ server.connections[quic_connection_id].h3_remote_qpack_max_table_capacity=control_settings['SETTINGS_QPACK_MAX_TABLE_CAPACITY'];
482
+
483
+ evict_qpack_remote_dynamic_table_if_needed(server, quic_connection_id);
484
+ }
485
+
486
+ if('SETTINGS_MAX_FIELD_SECTION_SIZE' in control_settings && control_settings['SETTINGS_MAX_FIELD_SECTION_SIZE']>0){
487
+ server.connections[quic_connection_id].h3_remote_max_header_size=control_settings['SETTINGS_MAX_FIELD_SECTION_SIZE'];
488
+ }
489
+
490
+ if('SETTINGS_H3_DATAGRAM' in control_settings && control_settings['SETTINGS_H3_DATAGRAM']>0){
491
+ server.connections[quic_connection_id].h3_remote_datagram_support=Boolean(control_settings['SETTINGS_H3_DATAGRAM']);
492
+ }
493
+
494
+
495
+
496
+ }
497
+ }
498
+
499
+ }
500
+
501
+ }else if(stream_type==2){//qpack encode stream...
502
+
503
+ //console.log('qpack encode stream from chunks:');
504
+ //console.log(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks);
505
+
506
+ //console.dir(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks, { maxArrayLength: null });
507
+
508
+
509
+
510
+ var ext=extract_qpack_encoder_instructions_from_chunks(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks,server.connections[quic_connection_id].h3_remote_qpack_encoder_from_offset);
511
+ server.connections[quic_connection_id].h3_remote_qpack_encoder_from_offset=ext.new_from_offset;
512
+
513
+ var arr_inserts=[];
514
+
515
+ for(var i in ext.instructions){
516
+ if(ext.instructions[i].type=='set_dynamic_table_capacity'){
517
+
518
+ server.connections[quic_connection_id].h3_remote_qpack_table_capacity=ext.instructions[i].capacity;
519
+
520
+ }else if(ext.instructions[i].type=='insert_with_name_ref' || ext.instructions[i].type=='insert_without_name_ref'){
521
+ var name=null;
522
+ var value=ext.instructions[i].value;
523
+
524
+ if(ext.instructions[i].type=='insert_with_name_ref'){
525
+ if(ext.instructions[i].from_static_table==true){
526
+ if(ext.instructions[i].name_index<qpack_static_table_entries.length){
527
+ name=qpack_static_table_entries[ext.instructions[i].name_index][0];
528
+ }else{
529
+ //error...
530
+ }
531
+ }else{
532
+ //from dynamic...
533
+ var base_index = server.connections[quic_connection_id].h3_remote_qpack_table_base_index;
534
+ var name_index = ext.instructions[i].name_index;
535
+ var dynamic_index = base_index - 1 - name_index;
536
+ var dynamic_table = server.connections[quic_connection_id].h3_remote_qpack_dynamic_table;
537
+
538
+ if (dynamic_index >= 0 && dynamic_index < dynamic_table.length) {
539
+ name = dynamic_table[dynamic_index][0];
540
+ } else {
541
+ // Error: missing reference
542
+ }
543
+ }
544
+ }else{
545
+ name=ext.instructions[i].name;
546
+ }
547
+
548
+
549
+ if(name!==null){
550
+ arr_inserts.push([name,value]);
551
+ }
552
+
553
+ }
554
+ }
555
+
556
+ if(arr_inserts.length>0){
557
+ for(var i in arr_inserts){
558
+ insert_into_qpack_remote_encoder_dynamic_table(server,quic_connection_id,arr_inserts[i][0],arr_inserts[i][1]);
559
+ }
560
+
561
+ console.log(server.connections[quic_connection_id].h3_remote_qpack_dynamic_table);
562
+ //then... build_qpack_known_received_count(arr_inserts.length);
563
+ }
564
+
565
+ }else if(stream_type==3){
566
+
567
+ }else if(stream_type==4){//http3 request...
568
+
569
+
570
+ if(stream_id in server.connections[quic_connection_id].h3_http_request_streams==false){
571
+ server.connections[quic_connection_id].h3_http_request_streams[stream_id]={
572
+ from_offset: 0,
573
+ response_headers: {},
574
+ header_sent: false,
575
+ response_body: null,
576
+
577
+ };
578
+ }
579
+
580
+ var ext=extract_h3_frames_from_chunks(server.connections[quic_connection_id].receiving_streams[stream_id].receiving_chunks,server.connections[quic_connection_id].h3_http_request_streams[stream_id].from_offset);
581
+
582
+ server.connections[quic_connection_id].h3_http_request_streams[stream_id].from_offset=ext.new_from_offset;
583
+
584
+
585
+ var h3_frames=ext.frames;
586
+
587
+ if(h3_frames.length>0){
588
+ //console.log('request frames: ');
589
+ //console.log(h3_frames);
590
+
591
+ for(var i in h3_frames){
592
+ if(h3_frames[i].frame_type==1){//header request
593
+
594
+ var headers={};
595
+
596
+ var dynamic_table = server.connections[quic_connection_id].h3_remote_qpack_dynamic_table;
597
+ var header_block = parse_qpack_header_block(h3_frames[i].payload);
598
+
599
+ if(header_block.insert_count<=dynamic_table.length){
600
+ var used_dynamic_ref=false;
601
+
602
+
603
+ for(var i2 in header_block.headers){
604
+
605
+ if(header_block.headers[i2].type=='indexed'){
606
+ if(header_block.headers[i2].from_static_table==true){
607
+ if(header_block.headers[i2].index<qpack_static_table_entries.length){
608
+
609
+ headers[qpack_static_table_entries[header_block.headers[i2].index][0]]=qpack_static_table_entries[header_block.headers[i2].index][1];
610
+
611
+ }else{
612
+ //error?
613
+ }
614
+ }else{
615
+ // from dynamic table
616
+ used_dynamic_ref=true;
617
+
618
+ var dynamic_index = header_block.base_index - 1 - header_block.headers[i2].index;
619
+ if (dynamic_index >= 0 && dynamic_index < dynamic_table.length) {
620
+ var [name, value] = dynamic_table[dynamic_index];
621
+ headers[name] = value;
622
+ }
623
+
624
+ }
625
+ }else if(header_block.headers[i2].type=='literal_with_name_ref'){
626
+ if(header_block.headers[i2].from_static_table==true){
627
+ if(header_block.headers[i2].name_index<qpack_static_table_entries.length){
628
+ headers[qpack_static_table_entries[header_block.headers[i2].name_index][0]]=header_block.headers[i2].value;
629
+ }
630
+ }else{
631
+ //from dynamic table...
632
+ used_dynamic_ref=true;
633
+
634
+ var dynamic_index = header_block.base_index - 1 - header_block.headers[i2].name_index;
635
+ if (dynamic_index >= 0 && dynamic_index < dynamic_table.length) {
636
+ var [name] = dynamic_table[dynamic_index];
637
+ headers[name] = header_block.headers[i2].value;
638
+ }
639
+ }
640
+ }else if(header_block.headers[i2].type=='literal_with_literal_name'){
641
+ headers[header_block.headers[i2].name]=header_block.headers[i2].value;
642
+ }
643
+ }
644
+
645
+ if(used_dynamic_ref==true){
646
+ //build and send the: build_qpack_block_header_ack(stream_id)
647
+ }
648
+ }
649
+
650
+ //console.log(headers);
651
+
652
+ if (headers[':protocol'] === 'webtransport') {
653
+ if (server._webtransport_handler) {
654
+ if(stream_id in server.connections[quic_connection_id].h3_wt_sessions==false){
655
+
656
+ var headers_payload = build_http3_literal_headers_frame([
657
+ { name: ":status", value: "200" },
658
+ ]);
659
+
660
+ var http3_response=build_h3_frames([
661
+ { frame_type: 1, payload: headers_payload }
662
+ ]);
663
+
664
+ set_sending_quic_chunk(server,quic_connection_id,{
665
+ type: '1rtt',
666
+ stream_id: Number(stream_id),
667
+ fin: false,
668
+ data: http3_response
669
+ });
670
+
671
+ var wt = create_wt_session_object(server, quic_connection_id, stream_id, headers);
672
+ server.connections[quic_connection_id].h3_wt_sessions[stream_id] = wt;
673
+ server._webtransport_handler(wt);
674
+ }
675
+ }
676
+ }else{
677
+
678
+ //...
679
+ if(server._handler){
680
+ var req = {
681
+ method: headers[':method'],
682
+ path: headers[':path'],
683
+ headers: headers,
684
+ connection_id: quic_connection_id,
685
+ stream_id: stream_id
686
+ };
687
+
688
+ var res = build_response_object(server, quic_connection_id, stream_id);
689
+
690
+ server._handler(req, res);
691
+ }
692
+
693
+ }
694
+
695
+ }else{//...
696
+
697
+ }
698
+ }
699
+
700
+ }
701
+
702
+ }
703
+
704
+
705
+
706
+
707
+
708
+
709
+ }
710
+ }
711
+
712
+ }
713
+ }
714
+
715
+ function receiving_udp_quic_packet(server,from_ip,from_port,udp_packet_data){
716
+
717
+ var quic_packets=parse_quic_datagram(udp_packet_data);
718
+
719
+ if(quic_packets.length>0){
720
+ for(var i in quic_packets){
721
+ if(quic_packets[i]!==null){
722
+
723
+ var quic_connection_id=null;
724
+
725
+ var dcid_str=null;
726
+ if('dcid' in quic_packets[i] && quic_packets[i].dcid && quic_packets[i].dcid.byteLength>0){
727
+ dcid_str = quic_packets[i].dcid.toString('hex');
728
+ }
729
+
730
+ if(dcid_str!==null){
731
+ if(dcid_str in server.connections==true){
732
+ quic_connection_id=dcid_str;
733
+ }
734
+ }else{
735
+ var address_str = from_ip + ':' + from_port;
736
+ if(address_str in server.address_binds==true){
737
+ if(server.address_binds[address_str] in server.connections==true){
738
+ quic_connection_id=server.address_binds[address_str];
739
+ }
740
+ }
741
+ }
742
+
743
+ if(quic_connection_id==null){
744
+ if(dcid_str!==null){
745
+ quic_connection_id=dcid_str;
746
+ }else{
747
+ quic_connection_id=Math.floor(Math.random() * 9007199254740991);
748
+ }
749
+ }
750
+
751
+
752
+ var build_params={};
753
+
754
+ build_params['from_ip']=from_ip;
755
+ build_params['from_port']=from_port;
756
+
757
+ if('dcid' in quic_packets[i] && quic_packets[i].dcid && quic_packets[i].dcid.byteLength>0){
758
+ build_params['dcid']=quic_packets[i].dcid;
759
+ }
760
+
761
+ if('scid' in quic_packets[i] && quic_packets[i].scid && quic_packets[i].scid.byteLength>0){
762
+ build_params['scid']=quic_packets[i].scid;
763
+ }
764
+
765
+ if('version' in quic_packets[i] && quic_packets[i].version){
766
+ build_params['version']=quic_packets[i].version;
767
+ }
768
+
769
+
770
+ if(quic_packets[i].type=='initial'){
771
+
772
+ build_params['incoming_packet']={
773
+ type: quic_packets[i].type,
774
+ data: quic_packets[i].raw
775
+ };
776
+
777
+ }else if(quic_packets[i].type=='handshake'){
778
+
779
+ build_params['incoming_packet']={
780
+ type: quic_packets[i].type,
781
+ data: quic_packets[i].raw
782
+ };
783
+
784
+ }else if(quic_packets[i].type=='1rtt'){
785
+
786
+
787
+ build_params['incoming_packet']={
788
+ type: quic_packets[i].type,
789
+ data: quic_packets[i].raw
790
+ };
791
+
792
+ }else{
793
+ //console.log(quic_packets[i]);
794
+ }
795
+
796
+ //console.log(build_params);
797
+
798
+ set_quic_connection(server,quic_connection_id,build_params);
799
+
800
+
801
+ }
802
+ }
803
+ }
804
+
805
+ }
806
+
807
+
808
+
809
+ function set_quic_connection(server,quic_connection_id,options){
810
+ var is_modified=false;
811
+
812
+ if(quic_connection_id in server.connections==false){
813
+ server.connections[quic_connection_id]=structuredClone(new_quic_connection);
814
+
815
+ is_modified=true;
816
+ }
817
+
818
+ var prev_params={
819
+ connection_status: server.connections[quic_connection_id].connection_status,
820
+ sni: server.connections[quic_connection_id].sni
821
+ };
822
+
823
+ if(typeof options=='object'){
824
+
825
+ if('from_ip' in options){
826
+ if(server.connections[quic_connection_id].from_ip!==options.from_ip){
827
+
828
+ server.connections[quic_connection_id].from_ip=options.from_ip;
829
+ is_modified=true;
830
+ }
831
+ }
832
+
833
+ if('from_port' in options){
834
+ if(server.connections[quic_connection_id].from_port!==options.from_port){
835
+
836
+ server.connections[quic_connection_id].from_port=options.from_port;
837
+ is_modified=true;
838
+ }
839
+ }
840
+
841
+ if('version' in options){
842
+ if(server.connections[quic_connection_id].version!==options.version){
843
+
844
+ server.connections[quic_connection_id].version=options.version;
845
+ is_modified=true;
846
+ }
847
+ }
848
+
849
+
850
+ if('dcid' in options && options.dcid && options.dcid.byteLength>0){
851
+ if(server.connections[quic_connection_id].original_dcid==null || server.connections[quic_connection_id].original_dcid.byteLength<=0 || arraybufferEqual(options.dcid.buffer,server.connections[quic_connection_id].original_dcid.buffer)==false){
852
+
853
+ server.connections[quic_connection_id].original_dcid=options.dcid;
854
+ is_modified=true;
855
+
856
+ }
857
+ }
858
+
859
+
860
+ if('scid' in options && options.scid && options.scid.byteLength>0){
861
+
862
+ var is_scid_exist=false;
863
+ for(var i in server.connections[quic_connection_id].their_cids){
864
+ if(arraybufferEqual(options.scid.buffer,server.connections[quic_connection_id].their_cids[i].buffer)==true){
865
+ is_scid_exist=true;
866
+ break;
867
+ }
868
+ }
869
+
870
+ if(is_scid_exist==false){
871
+ server.connections[quic_connection_id].their_cids.push(options.scid);
872
+ is_modified=true;
873
+ }
874
+ }
875
+
876
+
877
+ if('sni' in options){
878
+ if(server.connections[quic_connection_id].sni!==options.sni){
879
+
880
+ server.connections[quic_connection_id].sni=options.sni;
881
+ is_modified=true;
882
+
883
+ }
884
+ }
885
+
886
+ if('connection_status' in options){
887
+ if(server.connections[quic_connection_id].connection_status!==options.connection_status){
888
+
889
+ server.connections[quic_connection_id].connection_status=options.connection_status;
890
+ is_modified=true;
891
+
892
+ //clean up...
893
+ if(server.connections[quic_connection_id].connection_status==1){
894
+ server.connections[quic_connection_id].tls_transcript=[];
895
+ server.connections[quic_connection_id].receiving_init_chunks={};
896
+ server.connections[quic_connection_id].receiving_handshake_chunks={};
897
+ }
898
+
899
+
900
+ }
901
+ }
902
+
903
+
904
+ }
905
+
906
+
907
+ if(is_modified==true){
908
+
909
+ var address_str = server.connections[quic_connection_id].from_ip + ':' + server.connections[quic_connection_id].from_port;
910
+ if(address_str in server.address_binds==false || server.address_binds[address_str]!==quic_connection_id){
911
+
912
+ server.address_binds[address_str]=quic_connection_id;
913
+ }
914
+
915
+
916
+ quic_connection(server,quic_connection_id,{
917
+ connection_status: server.connections[quic_connection_id].connection_status,
918
+ sni: server.connections[quic_connection_id].sni
919
+ },prev_params);
920
+
921
+ }
922
+
923
+ if(typeof options=='object'){
924
+
925
+
926
+
927
+ if('cert' in options && 'key' in options){
928
+
929
+
930
+ var cipher_info = get_cipher_info(server.connections[quic_connection_id].tls_cipher_selected);
931
+ var hash_func = cipher_info.hash;
932
+
933
+
934
+
935
+
936
+
937
+ var cert = new crypto.X509Certificate(options.cert);
938
+ var cert_der = new Uint8Array(cert.raw);
939
+
940
+ var certificate = build_certificate([{ cert: cert_der, extensions: new Uint8Array(0) }]);
941
+
942
+ server.connections[quic_connection_id].tls_transcript.push(certificate);
943
+
944
+ set_sending_quic_chunk(server,quic_connection_id,{
945
+ type: 'handshake',
946
+ data: certificate
947
+ });
948
+
949
+ //////////////////////////////////
950
+
951
+
952
+
953
+ var privateKeyObj = crypto.createPrivateKey(options.key);
954
+
955
+
956
+ var label = new TextEncoder().encode("TLS 1.3, server CertificateVerify");
957
+ var separator = new Uint8Array([0x00]);
958
+ var handshake_hash = hash_transcript(server.connections[quic_connection_id].tls_transcript,hash_func); // SHA-256 over transcript
959
+
960
+ // padding של 64 תווי רווח
961
+ var padding = new Uint8Array(64).fill(0x20);
962
+
963
+ // בניית signed_data לפי הפורמט
964
+ var signed_data = new Uint8Array(
965
+ padding.length + label.length + separator.length + handshake_hash.length
966
+ );
967
+ signed_data.set(padding, 0);
968
+ signed_data.set(label, padding.length);
969
+ signed_data.set(separator, padding.length + label.length);
970
+ signed_data.set(handshake_hash, padding.length + label.length + separator.length);
971
+
972
+ // מיפוי סוגי מפתח לאלגוריתמים תקניים
973
+ var ALGO_BY_TYPE = {
974
+ 'rsa': 0x0804, // rsa_pss_rsae_sha256
975
+ 'ec': 0x0403, // ecdsa_secp256r1_sha256
976
+ 'ed25519': 0x0807 // ed25519
977
+ };
978
+
979
+ var keyType = privateKeyObj.asymmetricKeyType;
980
+ var algo_candidate = ALGO_BY_TYPE[keyType];
981
+
982
+ if (!algo_candidate) {
983
+ throw new Error("Unsupported private key type for TLS 1.3 CertificateVerify: " + keyType);
984
+ }
985
+
986
+ if (!server.connections[quic_connection_id].tls_signature_algorithms.includes(algo_candidate)) {
987
+ throw new Error(`Client did not offer compatible signature algorithm for key type ${keyType}`);
988
+ }
989
+
990
+ var signature=null;
991
+
992
+ if (keyType === 'rsa') {
993
+ signature = new Uint8Array(crypto.sign('sha256', Buffer.from(signed_data),
994
+ {
995
+ key: privateKeyObj,
996
+ padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
997
+ saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST // 32 bytes for SHA256
998
+ }
999
+ ));
1000
+ } else if (keyType === 'ec') {
1001
+ signature = new Uint8Array(crypto.sign('sha256', Buffer.from(signed_data), privateKeyObj));
1002
+ } else if (keyType === 'ed25519') {
1003
+ signature = new Uint8Array(crypto.sign(null, Buffer.from(signed_data), privateKeyObj));
1004
+ }
1005
+
1006
+ var cert_verify = build_certificate_verify(algo_candidate, signature);
1007
+
1008
+ server.connections[quic_connection_id].tls_transcript.push(cert_verify);
1009
+
1010
+ set_sending_quic_chunk(server,quic_connection_id,{
1011
+ type: 'handshake',
1012
+ data: cert_verify
1013
+ });
1014
+
1015
+ /////////////////////////////////
1016
+ var finished_key = hkdf_expand_label(server.connections[quic_connection_id].tls_server_handshake_traffic_secret, 'finished', new Uint8Array(), hash_func.outputLen,hash_func);
1017
+
1018
+ var verify_data = hmac(cipher_info.str, finished_key, hash_transcript(server.connections[quic_connection_id].tls_transcript,hash_func));
1019
+
1020
+ var finished = build_finished(verify_data);
1021
+ server.connections[quic_connection_id].tls_transcript.push(finished);
1022
+
1023
+ set_sending_quic_chunk(server,quic_connection_id,{
1024
+ type: 'handshake',
1025
+ data: finished
1026
+ });
1027
+ //////////////////////////////
1028
+
1029
+
1030
+ var c = tls_derive_app_secrets(server.connections[quic_connection_id].tls_handshake_secret, server.connections[quic_connection_id].tls_transcript, hash_func);
1031
+
1032
+ server.connections[quic_connection_id].tls_client_app_traffic_secret = c.client_application_traffic_secret;
1033
+
1034
+ server.connections[quic_connection_id].tls_server_app_traffic_secret = c.server_application_traffic_secret;
1035
+
1036
+ }
1037
+
1038
+
1039
+
1040
+ if('incoming_packet' in options){
1041
+
1042
+ if('type' in options['incoming_packet']){
1043
+
1044
+ var read_key=null;
1045
+ var read_iv=null;
1046
+ var read_hp=null;
1047
+
1048
+ var largest_pn=-1;
1049
+
1050
+ if(options['incoming_packet']['type']=='initial'){
1051
+
1052
+ if(server.connections[quic_connection_id].init_read_key!==null && server.connections[quic_connection_id].init_read_iv!==null && server.connections[quic_connection_id].init_read_hp!==null){
1053
+ read_key=server.connections[quic_connection_id].init_read_key;
1054
+ read_iv=server.connections[quic_connection_id].init_read_iv;
1055
+ read_hp=server.connections[quic_connection_id].init_read_hp;
1056
+
1057
+ }else{
1058
+ var d = quic_derive_init_secrets(server.connections[quic_connection_id].original_dcid,server.connections[quic_connection_id].version,'read');
1059
+
1060
+ read_key=d.key;
1061
+ read_iv=d.iv;
1062
+ read_hp=d.hp;
1063
+
1064
+ server.connections[quic_connection_id].init_read_key=d.key;
1065
+ server.connections[quic_connection_id].init_read_iv=d.iv;
1066
+ server.connections[quic_connection_id].init_read_hp=d.hp;
1067
+ }
1068
+
1069
+ largest_pn=Number(server.connections[quic_connection_id].receiving_init_pn_largest)+0;
1070
+
1071
+ }else if(options['incoming_packet']['type']=='handshake'){
1072
+
1073
+ if(server.connections[quic_connection_id].handshake_read_key!==null && server.connections[quic_connection_id].handshake_read_iv!==null && server.connections[quic_connection_id].handshake_read_hp!==null){
1074
+ read_key=server.connections[quic_connection_id].handshake_read_key;
1075
+ read_iv=server.connections[quic_connection_id].handshake_read_iv;
1076
+ read_hp=server.connections[quic_connection_id].handshake_read_hp;
1077
+
1078
+ }else if(server.connections[quic_connection_id].tls_client_handshake_traffic_secret!==null){
1079
+ var d = quic_derive_from_tls_secrets(server.connections[quic_connection_id].tls_client_handshake_traffic_secret,sha256);
1080
+
1081
+ read_key=d.key;
1082
+ read_iv=d.iv;
1083
+ read_hp=d.hp;
1084
+
1085
+ server.connections[quic_connection_id].handshake_read_key=d.key;
1086
+ server.connections[quic_connection_id].handshake_read_iv=d.iv;
1087
+ server.connections[quic_connection_id].handshake_read_hp=d.hp;
1088
+
1089
+ }
1090
+
1091
+ largest_pn=Number(server.connections[quic_connection_id].receiving_handshake_pn_largest)+0;
1092
+
1093
+ }else if(options['incoming_packet']['type']=='1rtt'){
1094
+
1095
+
1096
+ if(server.connections[quic_connection_id].app_read_key!==null && server.connections[quic_connection_id].app_read_iv!==null && server.connections[quic_connection_id].app_read_hp!==null){
1097
+ read_key=server.connections[quic_connection_id].app_read_key;
1098
+ read_iv=server.connections[quic_connection_id].app_read_iv;
1099
+ read_hp=server.connections[quic_connection_id].app_read_hp;
1100
+
1101
+ }else if(server.connections[quic_connection_id].tls_client_app_traffic_secret!==null){
1102
+
1103
+ var d = quic_derive_from_tls_secrets(server.connections[quic_connection_id].tls_client_app_traffic_secret,sha256);
1104
+
1105
+ read_key=d.key;
1106
+ read_iv=d.iv;
1107
+ read_hp=d.hp;
1108
+
1109
+ server.connections[quic_connection_id].app_read_key=d.key;
1110
+ server.connections[quic_connection_id].app_read_iv=d.iv;
1111
+ server.connections[quic_connection_id].app_read_hp=d.hp;
1112
+
1113
+
1114
+
1115
+
1116
+ }
1117
+
1118
+ largest_pn=Number(server.connections[quic_connection_id].receiving_app_pn_largest)+0;
1119
+
1120
+ }
1121
+
1122
+ if(read_key!==null && read_iv!==null){
1123
+
1124
+ var decrypted_packet = decrypt_quic_packet(options['incoming_packet']['data'], read_key, read_iv, read_hp,server.connections[quic_connection_id].original_dcid,largest_pn);
1125
+
1126
+ if(decrypted_packet && decrypted_packet.plaintext!==null && decrypted_packet.plaintext.byteLength>0){
1127
+
1128
+ /*
1129
+ if(server.connections[quic_connection_id].read_key_phase!==options['incoming_packet'].key_phase){
1130
+ console.log('changed key pashe!!!!!!!!!!!!!!!!!!! '+options['incoming_packet'].key_phase);
1131
+ server.connections[quic_connection_id].read_key_phase=options['incoming_packet'].key_phase;
1132
+ }
1133
+ */
1134
+
1135
+ //console.log('key phase: ',decrypted_packet.key_phase);
1136
+
1137
+
1138
+ var need_check_tls_chunks=false;
1139
+ var is_new_packet=false;
1140
+
1141
+ var need_check_receiving_streams=false;
1142
+
1143
+
1144
+ if(options['incoming_packet']['type']=='initial'){
1145
+
1146
+ is_new_packet=flat_ranges.add(server.connections[quic_connection_id].receiving_init_pn_ranges, [decrypted_packet.packet_number,decrypted_packet.packet_number]);
1147
+
1148
+ if(server.connections[quic_connection_id].receiving_init_pn_largest<decrypted_packet.packet_number){
1149
+ server.connections[quic_connection_id].receiving_init_pn_largest=decrypted_packet.packet_number;
1150
+ }
1151
+
1152
+ }else if(options['incoming_packet']['type']=='handshake'){
1153
+
1154
+ is_new_packet=flat_ranges.add(server.connections[quic_connection_id].receiving_handshake_pn_ranges, [decrypted_packet.packet_number,decrypted_packet.packet_number]);
1155
+
1156
+ if(server.connections[quic_connection_id].receiving_handshake_pn_largest<decrypted_packet.packet_number){
1157
+ server.connections[quic_connection_id].receiving_handshake_pn_largest=decrypted_packet.packet_number;
1158
+ }
1159
+
1160
+ }else if(options['incoming_packet']['type']=='1rtt'){
1161
+
1162
+ is_new_packet=flat_ranges.add(server.connections[quic_connection_id].receiving_app_pn_ranges, [decrypted_packet.packet_number,decrypted_packet.packet_number]);
1163
+
1164
+ if(server.connections[quic_connection_id].receiving_app_pn_largest<decrypted_packet.packet_number){
1165
+ server.connections[quic_connection_id].receiving_app_pn_largest=decrypted_packet.packet_number;
1166
+
1167
+ //console.log(server.connections[quic_connection_id].receiving_app_pn_ranges);
1168
+ }
1169
+
1170
+ if(server.connections[quic_connection_id].connection_status!==1){
1171
+
1172
+
1173
+ set_quic_connection(server,quic_connection_id,{
1174
+ connection_status: 1
1175
+ });
1176
+ }
1177
+
1178
+ }
1179
+
1180
+ if(is_new_packet==true){
1181
+
1182
+ var ack_eliciting=false;
1183
+
1184
+ var frames=parse_quic_frames(decrypted_packet.plaintext);
1185
+
1186
+ for(var i in frames){
1187
+
1188
+ if(ack_eliciting==false && (frames[i].type=='stream' || frames[i].type=='crypto' || frames[i].type=='new_connection_id' || frames[i].type=='handshake_done' || frames[i].type=='path_challenge' || frames[i].type=='path_response' || frames[i].type=='ping')){
1189
+ ack_eliciting=true;
1190
+ }
1191
+
1192
+
1193
+
1194
+ if(options['incoming_packet']['type']=='handshake'){
1195
+ //console.log('handshake get! ..@@@@@@@@@@@@.');
1196
+ //console.log(frames[i]);
1197
+ }else if(options['incoming_packet']['type']=='1rtt'){
1198
+ //console.log('1rtt get! ..@@@@@@@@@@@@.');
1199
+ //console.log(frames[i]);
1200
+ }
1201
+
1202
+
1203
+ if(frames[i].type=='crypto'){
1204
+ if(options['incoming_packet']['type']=='initial'){
1205
+
1206
+ if(flat_ranges.add(server.connections[quic_connection_id].receiving_init_ranges, [frames[i].offset, frames[i].offset + frames[i].data.length])==true){
1207
+
1208
+ if(frames[i].offset in server.connections[quic_connection_id].receiving_init_chunks==false || server.connections[quic_connection_id].receiving_init_chunks[frames[i].offset].byteLength<frames[i].data.byteLength){
1209
+ server.connections[quic_connection_id].receiving_init_chunks[frames[i].offset]=frames[i].data;
1210
+ }
1211
+
1212
+ need_check_tls_chunks=true;
1213
+
1214
+ }
1215
+
1216
+ }else if(options['incoming_packet']['type']=='handshake'){
1217
+
1218
+ if(flat_ranges.add(server.connections[quic_connection_id].receiving_handshake_ranges, [frames[i].offset, frames[i].offset + frames[i].data.length])==true){
1219
+
1220
+
1221
+
1222
+ if(frames[i].offset in server.connections[quic_connection_id].receiving_handshake_chunks==false || server.connections[quic_connection_id].receiving_handshake_chunks[frames[i].offset].byteLength<frames[i].data.byteLength){
1223
+ server.connections[quic_connection_id].receiving_handshake_chunks[frames[i].offset]=frames[i].data;
1224
+ }
1225
+
1226
+ need_check_tls_chunks=true;
1227
+
1228
+ }
1229
+
1230
+ }
1231
+ }else if(frames[i].type=='stream'){
1232
+
1233
+ if(frames[i].id in server.connections[quic_connection_id].receiving_streams==false){
1234
+ server.connections[quic_connection_id].receiving_streams[frames[i].id]={
1235
+ receiving_chunks: {},
1236
+ total_size: 0,
1237
+ receiving_ranges: [],
1238
+ need_check: false
1239
+ };
1240
+ }
1241
+
1242
+ if(flat_ranges.add(server.connections[quic_connection_id].receiving_streams[frames[i].id].receiving_ranges, [frames[i].offset, frames[i].offset + frames[i].data.length])==true){
1243
+
1244
+ if(frames[i].offset in server.connections[quic_connection_id].receiving_streams[frames[i].id].receiving_chunks==false || server.connections[quic_connection_id].receiving_streams[frames[i].id].receiving_chunks[frames[i].offset].byteLength<frames[i].data.byteLength){
1245
+ server.connections[quic_connection_id].receiving_streams[frames[i].id].receiving_chunks[frames[i].offset]=frames[i].data;
1246
+ }
1247
+
1248
+ if('fin' in frames[i] && frames[i].fin==true){
1249
+ server.connections[quic_connection_id].receiving_streams[frames[i].id].total_size=frames[i].data.byteLength+frames[i].offset;
1250
+ }
1251
+
1252
+ server.connections[quic_connection_id].receiving_streams[frames[i].id].need_check=true;
1253
+
1254
+ if(need_check_receiving_streams==false){
1255
+ need_check_receiving_streams=true;
1256
+ }
1257
+
1258
+ }
1259
+
1260
+ }else if(frames[i].type=='stop_sending'){
1261
+
1262
+ //console.log(frames[i]);
1263
+ //console.log('stop_sending!!!!!!!!!!!');
1264
+
1265
+ }else if(frames[i].type=='datagram'){
1266
+
1267
+ var wt_datagram=parse_webtransport_datagram(frames[i].data);
1268
+ if(wt_datagram.stream_id in server.connections[quic_connection_id].h3_wt_sessions){
1269
+ var session = server.connections[quic_connection_id].h3_wt_sessions[wt_datagram.stream_id];
1270
+ if (typeof session.ondatagram === 'function') {
1271
+ session.ondatagram(wt_datagram.data); // מעביר רק את התוכן
1272
+ }
1273
+ }
1274
+
1275
+ }else if(frames[i].type=='ack'){
1276
+
1277
+
1278
+ if(options['incoming_packet']['type']=='initial'){
1279
+
1280
+ var acked_ranges=quic_acked_info_to_ranges(frames[i]);
1281
+
1282
+ if(flat_ranges.add(server.connections[quic_connection_id].sending_init_pn_acked_ranges, acked_ranges)==true){
1283
+ //console.log(server.connections[quic_connection_id].sending_init_pn_acked_ranges);
1284
+ }
1285
+
1286
+ }else if(options['incoming_packet']['type']=='handshake'){
1287
+
1288
+ var acked_ranges=quic_acked_info_to_ranges(frames[i]);
1289
+
1290
+ if(flat_ranges.add(server.connections[quic_connection_id].sending_handshake_pn_acked_ranges, acked_ranges)==true){
1291
+ //console.log(server.connections[quic_connection_id].sending_handshake_pn_acked_ranges);
1292
+ }
1293
+
1294
+ }else if(options['incoming_packet']['type']=='1rtt'){
1295
+
1296
+ process_ack_frame(server,quic_connection_id,frames[i]);
1297
+
1298
+ }
1299
+
1300
+
1301
+ }else{
1302
+ //console.log(frames[i]);
1303
+ }
1304
+
1305
+
1306
+ }
1307
+
1308
+ //console.log('get frames:');
1309
+ //console.log(frames);
1310
+
1311
+
1312
+ if(options['incoming_packet']['type']=='1rtt'){
1313
+ //add to history
1314
+ var now=Math.floor(performance.timeOrigin + performance.now());
1315
+ server.connections[quic_connection_id].receiving_app_pn_history.push([decrypted_packet.packet_number,now,options['incoming_packet']['data'].byteLength]);
1316
+ }
1317
+
1318
+ if(ack_eliciting==true){
1319
+ var ack_frame_to_send = [];
1320
+
1321
+ if(options['incoming_packet']['type']=='initial'){
1322
+ ack_frame_to_send.push(build_ack_info_from_ranges(server.connections[quic_connection_id].receiving_init_pn_ranges, null, 0));
1323
+ }else if(options['incoming_packet']['type']=='handshake'){
1324
+ ack_frame_to_send.push(build_ack_info_from_ranges(server.connections[quic_connection_id].receiving_handshake_pn_ranges, null, 0));
1325
+ }else if(options['incoming_packet']['type']=='1rtt'){
1326
+
1327
+ flat_ranges.add(server.connections[quic_connection_id].receiving_app_pn_pending_ack, [decrypted_packet.packet_number,decrypted_packet.packet_number]);
1328
+
1329
+ prepare_and_send_quic_packet(server,quic_connection_id);
1330
+
1331
+ }
1332
+
1333
+
1334
+ if(ack_frame_to_send.length>0){
1335
+ send_quic_frames_packet(server,quic_connection_id,options['incoming_packet']['type'],ack_frame_to_send);
1336
+ }
1337
+ }
1338
+
1339
+
1340
+
1341
+
1342
+ }
1343
+
1344
+
1345
+ var tls_messages=[];
1346
+
1347
+ if(need_check_tls_chunks==true){
1348
+ if(options['incoming_packet']['type']=='initial'){
1349
+
1350
+ var ext=extract_tls_messages_from_chunks(server.connections[quic_connection_id].receiving_init_chunks, server.connections[quic_connection_id].receiving_init_from_offset);
1351
+
1352
+ tls_messages=ext.tls_messages;
1353
+
1354
+ server.connections[quic_connection_id].receiving_init_from_offset=ext.new_from_offset;
1355
+
1356
+ }else if(options['incoming_packet']['type']=='handshake'){
1357
+
1358
+ var ext=extract_tls_messages_from_chunks(server.connections[quic_connection_id].receiving_handshake_chunks, server.connections[quic_connection_id].receiving_handshake_from_offset);
1359
+
1360
+ tls_messages=ext.tls_messages;
1361
+
1362
+ server.connections[quic_connection_id].receiving_handshake_from_offset=ext.new_from_offset;
1363
+
1364
+ }
1365
+ }
1366
+
1367
+
1368
+ if(tls_messages.length>0){
1369
+ for(var i in tls_messages){
1370
+ process_quic_tls_message(server,quic_connection_id,tls_messages[i]);
1371
+ }
1372
+ }
1373
+
1374
+ if(need_check_receiving_streams==true){
1375
+
1376
+ if(server.connections[quic_connection_id].receiving_streams_next_check_timer==null){
1377
+
1378
+ //run timer...
1379
+ server.connections[quic_connection_id].receiving_streams_next_check_timer=setTimeout(function(){
1380
+ server.connections[quic_connection_id].receiving_streams_next_check_timer=null;
1381
+ process_quic_receiving_streams(server,quic_connection_id);
1382
+ },5);
1383
+
1384
+ }
1385
+
1386
+ }
1387
+
1388
+
1389
+
1390
+
1391
+ }else{
1392
+
1393
+ //console.log('decrtyped packet fail...');
1394
+
1395
+ }
1396
+ }
1397
+
1398
+
1399
+
1400
+
1401
+ }
1402
+
1403
+ }
1404
+ }
1405
+ }
1406
+
1407
+ function process_ack_frame(server,quic_connection_id,frame){
1408
+ if(quic_connection_id in server.connections){
1409
+
1410
+ var acked_ranges=quic_acked_info_to_ranges(frame);
1411
+
1412
+
1413
+ if('largest' in frame && 'delay' in frame){
1414
+ var largest_pn=frame.largest;
1415
+
1416
+ if(server.connections[quic_connection_id].sending_app_pn_in_flight.has(largest_pn)==true){
1417
+ var now = Math.floor(performance.timeOrigin + performance.now());
1418
+ var ack_delay_raw=frame.delay;
1419
+ var ack_delay_ms = Math.round((ack_delay_raw * Math.pow(2, 3)) / 1000);
1420
+
1421
+ var pn_index = largest_pn - (server.connections[quic_connection_id].sending_app_pn_base - server.connections[quic_connection_id].sending_app_pn_history.length);
1422
+
1423
+ if (pn_index >= 0 && pn_index < server.connections[quic_connection_id].sending_app_pn_history.length) {
1424
+ /*
1425
+ console.log('pn_index: ',pn_index);
1426
+ console.log('sending_app_pn_history.length: ',server.connections[quic_connection_id].sending_app_pn_history.length);
1427
+ console.log('largest_pn: ',largest_pn);
1428
+ console.log('sending_app_pn_base: ',server.connections[quic_connection_id].sending_app_pn_base);
1429
+ */
1430
+
1431
+ var start_time=server.connections[quic_connection_id].sending_app_pn_history[pn_index][0];
1432
+
1433
+
1434
+ var received_time_estimate = now - ack_delay_ms;
1435
+
1436
+ var measured_rtt = now - start_time - ack_delay_ms;
1437
+
1438
+ var sent_bytes_during = 0;
1439
+ var sent_packets_during = 0;
1440
+
1441
+ for (var i2 = pn_index; i2 < server.connections[quic_connection_id].sending_app_pn_history.length; i2++) {
1442
+ var [ts, size] = server.connections[quic_connection_id].sending_app_pn_history[i2];
1443
+ if (received_time_estimate >= ts) {
1444
+ sent_bytes_during += size;
1445
+ sent_packets_during++;
1446
+ }
1447
+ }
1448
+
1449
+ var received_bytes_during = 0;
1450
+ var received_packets_during = 0;
1451
+
1452
+ for (var i2 = 0; i2 < server.connections[quic_connection_id].receiving_app_pn_history.length; i2++) {
1453
+ var [pn_recv, ts_recv, size_recv] = server.connections[quic_connection_id].receiving_app_pn_history[i2];
1454
+ if (ts_recv > received_time_estimate){
1455
+ break;
1456
+
1457
+ }else if (ts_recv >= start_time) {
1458
+ received_bytes_during += size_recv;
1459
+ received_packets_during++;
1460
+ }
1461
+ }
1462
+
1463
+
1464
+ var last_rtt_record=null;
1465
+ if(server.connections[quic_connection_id].rtt_history.length>0){
1466
+ last_rtt_record=server.connections[quic_connection_id].rtt_history[server.connections[quic_connection_id].rtt_history.length-1];
1467
+ }
1468
+
1469
+ if(last_rtt_record==null || (last_rtt_record[0]!==start_time && last_rtt_record[1]!==received_time_estimate)){
1470
+ server.connections[quic_connection_id].rtt_history.push([
1471
+ start_time, // 0 - מתי נשלח
1472
+ received_time_estimate, // 1 - מתי התקבל ACK
1473
+ sent_bytes_during, // 2 - כמה נשלח בזמן הזה
1474
+ sent_packets_during, // 3 - כמה פאקטים נשלחו
1475
+ received_bytes_during, // 4 - כמה התקבל באותו זמן
1476
+ received_packets_during, // 5 - כמה פאקטים התקבלו
1477
+ measured_rtt, // 6 - RTT
1478
+ ]);
1479
+ }
1480
+
1481
+
1482
+ //console.log(server.connections[quic_connection_id]);
1483
+ }
1484
+
1485
+ }
1486
+ }
1487
+
1488
+
1489
+
1490
+ for (var pn of server.connections[quic_connection_id].sending_app_pn_in_flight) {
1491
+ var is_ack_in_ranges = false;
1492
+ for (var i2 = 0; i2 < acked_ranges.length; i2 += 2) {
1493
+ var from = acked_ranges[i2];
1494
+ var to = acked_ranges[i2 + 1];
1495
+ if (pn >= from && pn <= to) {
1496
+ is_ack_in_ranges = true;
1497
+ break;
1498
+ }
1499
+ }
1500
+
1501
+ if(is_ack_in_ranges==true){
1502
+ server.connections[quic_connection_id].sending_app_pn_in_flight.delete(pn);
1503
+
1504
+
1505
+ for(var stream_id in server.connections[quic_connection_id].sending_streams){
1506
+
1507
+ if('in_flight_ranges' in server.connections[quic_connection_id].sending_streams[stream_id] && pn in server.connections[quic_connection_id].sending_streams[stream_id].in_flight_ranges==true){
1508
+
1509
+ if(flat_ranges.add(server.connections[quic_connection_id].sending_streams[stream_id].acked_ranges, server.connections[quic_connection_id].sending_streams[stream_id].in_flight_ranges[pn])==true){
1510
+
1511
+ }
1512
+
1513
+ delete server.connections[quic_connection_id].sending_streams[stream_id].in_flight_ranges[pn];
1514
+
1515
+ if(server.connections[quic_connection_id].sending_streams[stream_id].acked_ranges.length==2 && server.connections[quic_connection_id].sending_streams[stream_id].total_size && server.connections[quic_connection_id].sending_streams[stream_id].total_size>0 && server.connections[quic_connection_id].sending_streams[stream_id].acked_ranges[0]==0 && server.connections[quic_connection_id].sending_streams[stream_id].acked_ranges[1]==server.connections[quic_connection_id].sending_streams[stream_id].total_size){
1516
+ //we can delete it...
1517
+ delete server.connections[quic_connection_id].sending_streams[stream_id];
1518
+ }
1519
+
1520
+ //console.log(server.connections[quic_connection_id].sending_streams[stream_id]);
1521
+ }
1522
+ }
1523
+
1524
+
1525
+
1526
+
1527
+
1528
+
1529
+
1530
+
1531
+ }
1532
+ }
1533
+
1534
+ }
1535
+ }
1536
+
1537
+ function send_quic_frames_packet(server,quic_connection_id,type,frames){
1538
+ if(quic_connection_id in server.connections){
1539
+
1540
+ var write_key=null;
1541
+ var write_iv=null;
1542
+ var write_hp=null;
1543
+
1544
+ var packet_number=1;
1545
+
1546
+ if(type=='initial'){
1547
+
1548
+ if(server.connections[quic_connection_id].init_write_key!==null && server.connections[quic_connection_id].init_write_iv!==null && server.connections[quic_connection_id].init_write_hp!==null){
1549
+ write_key=server.connections[quic_connection_id].init_write_key;
1550
+ write_iv=server.connections[quic_connection_id].init_write_iv;
1551
+ write_hp=server.connections[quic_connection_id].init_write_hp;
1552
+
1553
+ }else{
1554
+ var d = quic_derive_init_secrets(server.connections[quic_connection_id].original_dcid,server.connections[quic_connection_id].version,'write');
1555
+
1556
+ write_key=d.key;
1557
+ write_iv=d.iv;
1558
+ write_hp=d.hp;
1559
+
1560
+ server.connections[quic_connection_id].init_write_key=d.key;
1561
+ server.connections[quic_connection_id].init_write_iv=d.iv;
1562
+ server.connections[quic_connection_id].init_write_hp=d.hp;
1563
+ }
1564
+
1565
+
1566
+ packet_number=Number(server.connections[quic_connection_id].sending_init_pn_next)+0;
1567
+
1568
+ }else if(type=='handshake'){
1569
+
1570
+ if(server.connections[quic_connection_id].handshake_write_key!==null && server.connections[quic_connection_id].handshake_write_iv!==null && server.connections[quic_connection_id].handshake_write_hp!==null){
1571
+ write_key=server.connections[quic_connection_id].handshake_write_key;
1572
+ write_iv=server.connections[quic_connection_id].handshake_write_iv;
1573
+ write_hp=server.connections[quic_connection_id].handshake_write_hp;
1574
+
1575
+ }else if(server.connections[quic_connection_id].tls_server_handshake_traffic_secret!==null){
1576
+ var d = quic_derive_from_tls_secrets(server.connections[quic_connection_id].tls_server_handshake_traffic_secret,sha256);
1577
+
1578
+ write_key=d.key;
1579
+ write_iv=d.iv;
1580
+ write_hp=d.hp;
1581
+
1582
+ server.connections[quic_connection_id].handshake_write_key=d.key;
1583
+ server.connections[quic_connection_id].handshake_write_iv=d.iv;
1584
+ server.connections[quic_connection_id].handshake_write_hp=d.hp;
1585
+ }
1586
+
1587
+ packet_number=Number(server.connections[quic_connection_id].sending_handshake_pn_next)+0;
1588
+
1589
+ }else if(type=='1rtt'){
1590
+
1591
+ if(server.connections[quic_connection_id].app_write_key!==null && server.connections[quic_connection_id].app_write_iv!==null && server.connections[quic_connection_id].app_write_hp!==null){
1592
+ write_key=server.connections[quic_connection_id].app_write_key;
1593
+ write_iv=server.connections[quic_connection_id].app_write_iv;
1594
+ write_hp=server.connections[quic_connection_id].app_write_hp;
1595
+
1596
+ }else if(server.connections[quic_connection_id].tls_server_app_traffic_secret!==null){
1597
+ var d = quic_derive_from_tls_secrets(server.connections[quic_connection_id].tls_server_app_traffic_secret,sha256);
1598
+
1599
+ write_key=d.key;
1600
+ write_iv=d.iv;
1601
+ write_hp=d.hp;
1602
+
1603
+ server.connections[quic_connection_id].app_write_key=d.key;
1604
+ server.connections[quic_connection_id].app_write_iv=d.iv;
1605
+ server.connections[quic_connection_id].app_write_hp=d.hp;
1606
+ }
1607
+
1608
+ packet_number=Number(server.connections[quic_connection_id].sending_app_pn_base)+0;
1609
+
1610
+ }
1611
+
1612
+ //console.log('sending packet_number===');
1613
+ //console.log(packet_number);
1614
+
1615
+
1616
+ var dcid=new Uint8Array(0);
1617
+
1618
+ if(server.connections[quic_connection_id].their_cids.length>0){
1619
+ dcid=server.connections[quic_connection_id].their_cids[0];
1620
+ }
1621
+
1622
+ var encodedFrames = encode_quic_frames(frames);
1623
+ var encrypted_quic_packet=encrypt_quic_packet(type, encodedFrames, write_key, write_iv, write_hp, packet_number,dcid,server.connections[quic_connection_id].original_dcid, new Uint8Array(0));
1624
+
1625
+ if(type=='initial'){
1626
+ server.connections[quic_connection_id].sending_init_pn_next++;
1627
+ }else if(type=='handshake'){
1628
+ server.connections[quic_connection_id].sending_handshake_pn_next++;
1629
+ }else if(type=='1rtt'){
1630
+ var now = Math.floor(performance.timeOrigin + performance.now());
1631
+ server.connections[quic_connection_id].sending_app_pn_history.push([now, encodedFrames.length]);
1632
+ server.connections[quic_connection_id].sending_app_pn_base++;
1633
+ }
1634
+
1635
+ send_udp_packet(server,encrypted_quic_packet,server.connections[quic_connection_id].from_port,server.connections[quic_connection_id].from_ip,function(){
1636
+
1637
+
1638
+
1639
+ });
1640
+
1641
+
1642
+
1643
+ }
1644
+ }
1645
+
1646
+ function send_udp_packet(server,data,port,ip,callback){
1647
+ if(ip.indexOf(':')>=0){
1648
+ server._udp6.send(data, port, ip, function(error){
1649
+ if (error) {
1650
+ callback(false);
1651
+ } else {
1652
+ callback(true);
1653
+ }
1654
+ });
1655
+ }else{
1656
+ server._udp4.send(data, port, ip, function(error){
1657
+ if (error) {
1658
+ callback(false);
1659
+ } else {
1660
+ callback(true);
1661
+ }
1662
+ });
1663
+ }
1664
+ }
1665
+
1666
+
1667
+ function send_quic_packet(server,quic_connection_id,type,encoded_frames,callback){
1668
+ if(quic_connection_id in server.connections){
1669
+
1670
+ var write_key=null;
1671
+ var write_iv=null;
1672
+ var write_hp=null;
1673
+
1674
+ var packet_number=1;
1675
+
1676
+ if(type=='initial'){
1677
+
1678
+ if(server.connections[quic_connection_id].init_write_key!==null && server.connections[quic_connection_id].init_write_iv!==null && server.connections[quic_connection_id].init_write_hp!==null){
1679
+ write_key=server.connections[quic_connection_id].init_write_key;
1680
+ write_iv=server.connections[quic_connection_id].init_write_iv;
1681
+ write_hp=server.connections[quic_connection_id].init_write_hp;
1682
+
1683
+ }else{
1684
+ var d = quic_derive_init_secrets(server.connections[quic_connection_id].original_dcid,server.connections[quic_connection_id].version,'write');
1685
+
1686
+ write_key=d.key;
1687
+ write_iv=d.iv;
1688
+ write_hp=d.hp;
1689
+
1690
+ server.connections[quic_connection_id].init_write_key=d.key;
1691
+ server.connections[quic_connection_id].init_write_iv=d.iv;
1692
+ server.connections[quic_connection_id].init_write_hp=d.hp;
1693
+ }
1694
+
1695
+
1696
+ packet_number=Number(server.connections[quic_connection_id].sending_init_pn_next)+0;
1697
+
1698
+ }else if(type=='handshake'){
1699
+
1700
+ if(server.connections[quic_connection_id].handshake_write_key!==null && server.connections[quic_connection_id].handshake_write_iv!==null && server.connections[quic_connection_id].handshake_write_hp!==null){
1701
+ write_key=server.connections[quic_connection_id].handshake_write_key;
1702
+ write_iv=server.connections[quic_connection_id].handshake_write_iv;
1703
+ write_hp=server.connections[quic_connection_id].handshake_write_hp;
1704
+
1705
+ }else if(server.connections[quic_connection_id].tls_server_handshake_traffic_secret!==null){
1706
+ var d = quic_derive_from_tls_secrets(server.connections[quic_connection_id].tls_server_handshake_traffic_secret,sha256);
1707
+
1708
+ write_key=d.key;
1709
+ write_iv=d.iv;
1710
+ write_hp=d.hp;
1711
+
1712
+ server.connections[quic_connection_id].handshake_write_key=d.key;
1713
+ server.connections[quic_connection_id].handshake_write_iv=d.iv;
1714
+ server.connections[quic_connection_id].handshake_write_hp=d.hp;
1715
+ }
1716
+
1717
+ packet_number=Number(server.connections[quic_connection_id].sending_handshake_pn_next)+0;
1718
+
1719
+ }else if(type=='1rtt'){
1720
+
1721
+ if(server.connections[quic_connection_id].app_write_key!==null && server.connections[quic_connection_id].app_write_iv!==null && server.connections[quic_connection_id].app_write_hp!==null){
1722
+ write_key=server.connections[quic_connection_id].app_write_key;
1723
+ write_iv=server.connections[quic_connection_id].app_write_iv;
1724
+ write_hp=server.connections[quic_connection_id].app_write_hp;
1725
+
1726
+ }else if(server.connections[quic_connection_id].tls_server_app_traffic_secret!==null){
1727
+ var d = quic_derive_from_tls_secrets(server.connections[quic_connection_id].tls_server_app_traffic_secret,sha256);
1728
+
1729
+ write_key=d.key;
1730
+ write_iv=d.iv;
1731
+ write_hp=d.hp;
1732
+
1733
+ server.connections[quic_connection_id].app_write_key=d.key;
1734
+ server.connections[quic_connection_id].app_write_iv=d.iv;
1735
+ server.connections[quic_connection_id].app_write_hp=d.hp;
1736
+ }
1737
+
1738
+ packet_number=Number(server.connections[quic_connection_id].sending_app_pn_base)+0;
1739
+
1740
+ }
1741
+
1742
+ //console.log('sending packet_number===');
1743
+ //console.log(packet_number);
1744
+
1745
+
1746
+ var dcid=new Uint8Array(0);
1747
+
1748
+ if(server.connections[quic_connection_id].their_cids.length>0){
1749
+ dcid=server.connections[quic_connection_id].their_cids[0];
1750
+ }
1751
+
1752
+ var encrypted_quic_packet=encrypt_quic_packet(type, encoded_frames, write_key, write_iv, write_hp, packet_number,dcid,server.connections[quic_connection_id].original_dcid, new Uint8Array(0));
1753
+
1754
+ send_udp_packet(server,encrypted_quic_packet,server.connections[quic_connection_id].from_port,server.connections[quic_connection_id].from_ip,function(is_sent){
1755
+
1756
+ if(typeof callback=='function'){
1757
+ callback(is_sent);
1758
+ }
1759
+
1760
+ });
1761
+
1762
+ }
1763
+ }
1764
+
1765
+
1766
+
1767
+
1768
+
1769
+
1770
+
1771
+ function process_quic_tls_message(server,quic_connection_id,tls_message){
1772
+ if(quic_connection_id in server.connections==true){
1773
+
1774
+ var hs = parse_tls_message(tls_message);
1775
+ if (hs.type === 0x01) {
1776
+ var parsed = parse_tls_client_hello(hs.body);
1777
+
1778
+ server.connections[quic_connection_id].tls_signature_algorithms=parsed.signature_algorithms;
1779
+ server.connections[quic_connection_id].tls_transcript=[tls_message];
1780
+
1781
+ var a=handle_client_hello(parsed);
1782
+
1783
+ //console.log('handle_client_hello:');
1784
+ //console.log(parsed);
1785
+
1786
+ var quic_transport_parameters=parse_transport_parameters(parsed.quic_transport_parameters_raw);
1787
+ //console.log('quic_transport_parameters:');
1788
+ //console.dir(quic_transport_parameters, { depth: null });
1789
+
1790
+ if ('ack_delay_exponent' in quic_transport_parameters) {
1791
+ server.connections[quic_connection_id].remote_ack_delay_exponent=quic_transport_parameters['ack_delay_exponent'];
1792
+ }
1793
+
1794
+ if ('max_udp_payload_size' in quic_transport_parameters) {
1795
+ server.connections[quic_connection_id].remote_max_udp_payload_size=quic_transport_parameters['max_udp_payload_size'];
1796
+ }
1797
+
1798
+
1799
+
1800
+ server.connections[quic_connection_id].tls_cipher_selected=a.selected_cipher;
1801
+
1802
+ var server_random = crypto.randomBytes(32);
1803
+ var server_hello = build_server_hello(server_random, a.server_public_key, parsed.session_id, server.connections[quic_connection_id].tls_cipher_selected, a.selected_group);
1804
+
1805
+
1806
+ server.connections[quic_connection_id].tls_transcript.push(server_hello);
1807
+
1808
+ set_sending_quic_chunk(server,quic_connection_id,{
1809
+ type: 'initial',
1810
+ data: server_hello
1811
+ });
1812
+
1813
+
1814
+ var cipher_info = get_cipher_info(server.connections[quic_connection_id].tls_cipher_selected);
1815
+ var hash_func = cipher_info.hash;
1816
+
1817
+ var b = tls_derive_handshake_secrets(a.shared_secret, server.connections[quic_connection_id].tls_transcript, hash_func);
1818
+
1819
+ server.connections[quic_connection_id].tls_handshake_secret=b.handshake_secret;
1820
+
1821
+
1822
+ server.connections[quic_connection_id].tls_client_handshake_traffic_secret=b.client_handshake_traffic_secret;
1823
+
1824
+ server.connections[quic_connection_id].tls_server_handshake_traffic_secret=b.server_handshake_traffic_secret;
1825
+
1826
+ var quic_ext_data=build_quic_ext({
1827
+ original_destination_connection_id: server.connections[quic_connection_id].original_dcid,
1828
+ initial_source_connection_id: server.connections[quic_connection_id].original_dcid,
1829
+ max_udp_payload_size: 65527,
1830
+ max_idle_timeout: 30000,
1831
+ stateless_reset_token: new Uint8Array(16).fill(0xab),
1832
+ initial_max_data: 1048576,
1833
+ initial_max_stream_data_bidi_local: 262144,
1834
+ initial_max_stream_data_bidi_remote: 262144,
1835
+ initial_max_stream_data_uni: 131072,
1836
+ initial_max_streams_bidi: 100,
1837
+ initial_max_streams_uni: 3,
1838
+ ack_delay_exponent: 3,
1839
+ max_ack_delay: 25,
1840
+ disable_active_migration: true,
1841
+ active_connection_id_limit: 4,
1842
+ max_datagram_frame_size: 65527,
1843
+ web_accepted_origins: [
1844
+ "*" // או הדומיין שלך
1845
+ ]
1846
+ });
1847
+
1848
+
1849
+ var supported_alpn = ['h3'];
1850
+ var selected_alpn=null;
1851
+
1852
+ for(var i in supported_alpn){
1853
+ if(selected_alpn==null){
1854
+ for(var i2 in parsed.alpn){
1855
+ if(parsed.alpn[i2]==supported_alpn[i]){
1856
+ selected_alpn=parsed.alpn[i2];
1857
+ break;
1858
+ }
1859
+ }
1860
+ }
1861
+ }
1862
+
1863
+ server.connections[quic_connection_id].tls_alpn_selected=selected_alpn;
1864
+
1865
+
1866
+ var enc_ext = build_encrypted_extensions([
1867
+ { type: 0x10, data: build_alpn_ext(selected_alpn) },
1868
+ { type: 0x39, data: quic_ext_data}
1869
+ ]);
1870
+
1871
+ server.connections[quic_connection_id].tls_transcript.push(enc_ext);
1872
+
1873
+ set_sending_quic_chunk(server,quic_connection_id,{
1874
+ type: 'handshake',
1875
+ data: enc_ext
1876
+ });
1877
+
1878
+ set_quic_connection(server,quic_connection_id,{
1879
+ sni: parsed.sni
1880
+ });
1881
+
1882
+
1883
+ }else if (hs.type === 20) {
1884
+
1885
+
1886
+ //finished from client here...
1887
+ var cipher_info = get_cipher_info(server.connections[quic_connection_id].tls_cipher_selected);
1888
+ var hash_func = cipher_info.hash;
1889
+
1890
+
1891
+ var finished_key = hkdf_expand_label(server.connections[quic_connection_id].tls_client_handshake_traffic_secret, 'finished', new Uint8Array(), hash_func.outputLen,hash_func);
1892
+
1893
+ var expected_client_finished = hmac(cipher_info.str, finished_key, hash_transcript(server.connections[quic_connection_id].tls_transcript,hash_func));
1894
+
1895
+ if(arraybufferEqual(expected_client_finished.buffer,new Uint8Array(hs.body).buffer)==true){
1896
+ //finished ok!!!!!!
1897
+
1898
+ //console.log('finished ok!!!!!!!');
1899
+ server.connections[quic_connection_id].tls_finished_ok=true;
1900
+ }
1901
+
1902
+
1903
+ }else{
1904
+ //console.log('tls other:');
1905
+ //console.log(hs);
1906
+ }
1907
+ }
1908
+ }
1909
+
1910
+ function get_quic_stream_chunks_to_send(server, quic_connection_id, stream_id, allowed_bytes) {
1911
+ var conn = server.connections[quic_connection_id];
1912
+ if (!conn) return;
1913
+
1914
+ var stream = conn.sending_streams[stream_id];
1915
+ if (!stream || !stream.pending_data) {
1916
+ return {
1917
+ chunks: [],
1918
+ send_offset_next: stream ? stream.send_offset_next : 0
1919
+ };
1920
+ }
1921
+
1922
+ // הגודל הכולל של ה־stream
1923
+ var total_bytes = (typeof stream.total_size === 'number')
1924
+ ? stream.total_size
1925
+ : stream.write_offset_next;
1926
+
1927
+ var base_offset = stream.pending_offset_start;
1928
+ var send_offset_next = stream.send_offset_next;
1929
+
1930
+ // טווחים חסרים (יחסיים)
1931
+ var relative_missing = flat_ranges.invert(stream.acked_ranges, 0, total_bytes);
1932
+
1933
+ // המרה ל־offset מוחלט
1934
+ for (var i = 0; i < relative_missing.length; i++) {
1935
+ relative_missing[i] += base_offset;
1936
+ }
1937
+
1938
+ var chunks = [];
1939
+ var total_bytes_used = 0;
1940
+ var first_chunk_offset = null;
1941
+
1942
+ // שלב ראשון – קדימה מהמקום האחרון
1943
+ for (var i = 0; i < relative_missing.length; i += 2) {
1944
+ var f = relative_missing[i];
1945
+ var t = relative_missing[i + 1];
1946
+
1947
+ if (f <= send_offset_next && send_offset_next < t) {
1948
+ var offset = send_offset_next;
1949
+
1950
+ while (offset < t && total_bytes_used < allowed_bytes) {
1951
+ var space_left = allowed_bytes - total_bytes_used;
1952
+ var len = Math.min(space_left, t - offset);
1953
+ if (len <= 0) break;
1954
+
1955
+ if (first_chunk_offset === null) first_chunk_offset = offset;
1956
+
1957
+ var rel_start = offset - base_offset;
1958
+ var rel_end = rel_start + len;
1959
+ var chunk_data = stream.pending_data.slice(rel_start, rel_end);
1960
+
1961
+ chunks.push({
1962
+ offset: offset,
1963
+ data: chunk_data
1964
+ });
1965
+
1966
+ total_bytes_used += len;
1967
+ offset += len;
1968
+ }
1969
+
1970
+ break;
1971
+ }
1972
+ }
1973
+
1974
+ // שלב שני – התחלה עד first_chunk_offset
1975
+ if (total_bytes_used < allowed_bytes && first_chunk_offset !== null) {
1976
+ for (var i = 0; i < relative_missing.length; i += 2) {
1977
+ var f = relative_missing[i];
1978
+ var t = relative_missing[i + 1];
1979
+
1980
+ var offset = f;
1981
+ while (offset < t && offset < first_chunk_offset && total_bytes_used < allowed_bytes) {
1982
+ var space_left = allowed_bytes - total_bytes_used;
1983
+ var len = Math.min(space_left, t - offset, first_chunk_offset - offset);
1984
+ if (len <= 0) break;
1985
+
1986
+ var rel_start = offset - base_offset;
1987
+ var rel_end = rel_start + len;
1988
+ var chunk_data = stream.pending_data.slice(rel_start, rel_end);
1989
+
1990
+ chunks.push({
1991
+ offset: offset,
1992
+ data: chunk_data
1993
+ });
1994
+
1995
+ total_bytes_used += len;
1996
+ offset += len;
1997
+ }
1998
+ }
1999
+ }
2000
+
2001
+ // חישוב המצביע הבא אם נשלחו רצפים מהמצביע הנוכחי
2002
+ var new_send_offset = send_offset_next;
2003
+ for (var i = 0; i < chunks.length; i++) {
2004
+ var chunk = chunks[i];
2005
+ if (chunk.offset === new_send_offset) {
2006
+ new_send_offset = chunk.offset + chunk.data.length;
2007
+ } else {
2008
+ break;
2009
+ }
2010
+ }
2011
+
2012
+ return {
2013
+ chunks: chunks,
2014
+ send_offset_next: new_send_offset,
2015
+ };
2016
+ }
2017
+
2018
+
2019
+ function prepare_and_send_quic_packet(server, quic_connection_id) {
2020
+ var conn = server.connections[quic_connection_id];
2021
+ if (!conn) return;
2022
+
2023
+ //console.log('prepare_and_send_quic_packet...............');
2024
+
2025
+ if(conn.sending_quic_packet_now==false){
2026
+ conn.sending_quic_packet_now=true;
2027
+
2028
+ if(conn.next_send_quic_packet_timer!==null){
2029
+ clearTimeout(conn.next_send_quic_packet_timer);
2030
+ conn.next_send_quic_packet_timer=null;
2031
+ }
2032
+
2033
+ var now = Math.floor(performance.timeOrigin + performance.now());
2034
+
2035
+ var total_bytes_last_1s = 0;
2036
+ var packet_count_last_1s = 0;
2037
+
2038
+ var oldest_packet_time_bytes = null;
2039
+ var oldest_packet_time_packets = null;
2040
+
2041
+ // סריקת ההיסטוריה
2042
+ for (var i in conn.sending_app_pn_history) {
2043
+ var [ts, size] = conn.sending_app_pn_history[i];
2044
+
2045
+ if (ts > now - 1000) {
2046
+ total_bytes_last_1s += size;
2047
+ packet_count_last_1s++;
2048
+ } else {
2049
+ // שומרים מתי יפוג כל פאקט מההיסטוריה
2050
+ if (oldest_packet_time_bytes === null || ts < oldest_packet_time_bytes) {
2051
+ oldest_packet_time_bytes = ts;
2052
+ }
2053
+ if (oldest_packet_time_packets === null || ts < oldest_packet_time_packets) {
2054
+ oldest_packet_time_packets = ts;
2055
+ }
2056
+ }
2057
+ }
2058
+
2059
+ var bytes_left = conn.max_sending_total_bytes_per_sec - total_bytes_last_1s;
2060
+ var packets_left = conn.max_sending_packets_per_sec - packet_count_last_1s;
2061
+
2062
+
2063
+ var in_flight_packet_count = conn.sending_app_pn_in_flight.size;
2064
+ var in_flight_total_bytes = 0;
2065
+ for (var pn of conn.sending_app_pn_in_flight) {
2066
+ var pn_index = Number(pn) - (conn.sending_app_pn_base - conn.sending_app_pn_history.length);
2067
+ if (pn_index >= 0 && pn_index < conn.sending_app_pn_history.length) {
2068
+ var info = conn.sending_app_pn_history[pn_index];
2069
+ if (info){
2070
+ in_flight_total_bytes=in_flight_total_bytes+info[1];//size
2071
+ }
2072
+ }
2073
+ }
2074
+
2075
+
2076
+ var in_flight_room = conn.max_sending_bytes_in_flight - in_flight_total_bytes;
2077
+
2078
+
2079
+ var allowed_packet_size = Math.min(bytes_left, conn.max_sending_packet_size, in_flight_room);
2080
+
2081
+
2082
+ if (
2083
+ packets_left > 0 &&
2084
+ allowed_packet_size >= conn.min_sending_packet_size &&
2085
+ in_flight_packet_count < conn.max_sending_packets_in_flight &&
2086
+ in_flight_total_bytes + allowed_packet_size <= conn.max_sending_bytes_in_flight
2087
+ ) {
2088
+ // מותר לשלוח *******************************
2089
+
2090
+
2091
+ var encoded_frames=[];
2092
+ var update_streams={};
2093
+ var remove_pending_ack=[];
2094
+
2095
+
2096
+
2097
+
2098
+ if(conn.receiving_app_pn_pending_ack.length>0 && 1==1){
2099
+ var ack_delay_ms = 0;
2100
+ var largest_pn = conn.receiving_app_pn_pending_ack[conn.receiving_app_pn_pending_ack.length - 1];
2101
+ for (var i2 = 0; i2 < conn.receiving_app_pn_history.length; i2++) {
2102
+ var [pn_recv, ts_recv, size_recv] = conn.receiving_app_pn_history[i2];
2103
+ if(pn_recv==largest_pn){
2104
+ ack_delay_ms = now - ts_recv;
2105
+ break;
2106
+ }
2107
+ }
2108
+
2109
+ var delay_ns = ack_delay_ms * 1_000_000;
2110
+ var ack_delay_raw = Math.floor(delay_ns / (1 << conn.remote_ack_delay_exponent));
2111
+
2112
+ var ack_frame = build_ack_info_from_ranges(conn.receiving_app_pn_pending_ack, null, ack_delay_raw);
2113
+
2114
+ //var padding=new Uint8Array([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]);
2115
+ encoded_frames.push(encode_quic_frames([ack_frame]));
2116
+
2117
+ /*
2118
+
2119
+ console.log('ack frame sent:');
2120
+
2121
+ console.log(ack_frame);
2122
+
2123
+ console.log('ack for ranges:');
2124
+
2125
+ console.log(conn.receiving_app_pn_pending_ack);
2126
+
2127
+ console.log('raw:');
2128
+ console.log(encoded_frames);
2129
+ //allowed_packet_size=allowed_packet_size-encoded_frames[0].byteLength;
2130
+
2131
+ */
2132
+
2133
+ remove_pending_ack = conn.receiving_app_pn_pending_ack.slice();
2134
+ }
2135
+
2136
+
2137
+
2138
+ var active_stream_count=0;
2139
+ for(var stream_id in server.connections[quic_connection_id].sending_streams){
2140
+ //צריך שיהיה בדיקה אם זה סטרים שעדיין לא נשלח במלואו...
2141
+ active_stream_count++;
2142
+ }
2143
+ var per_stream_bytes = Math.floor(allowed_packet_size / active_stream_count);
2144
+
2145
+
2146
+ for(var stream_id in server.connections[quic_connection_id].sending_streams){
2147
+
2148
+ var chunks_ranges=[];
2149
+
2150
+ var {chunks,send_offset_next}=get_quic_stream_chunks_to_send(server,quic_connection_id,Number(stream_id),per_stream_bytes);
2151
+
2152
+ if(chunks.length>0){
2153
+
2154
+ for(var i in chunks){
2155
+
2156
+ var is_fin=false;
2157
+
2158
+ if(chunks[i].offset+chunks[i].data.byteLength>=server.connections[quic_connection_id].sending_streams[stream_id].total_size){
2159
+ is_fin=true;
2160
+ }
2161
+
2162
+ var stream_frame={
2163
+ type: 'stream',
2164
+ id: Number(stream_id),
2165
+ offset: chunks[i].offset,
2166
+ fin: is_fin,
2167
+ data: chunks[i].data
2168
+ };
2169
+
2170
+ encoded_frames.push(encode_quic_frames([stream_frame]));
2171
+
2172
+ chunks_ranges.push(chunks[i].offset, chunks[i].offset + chunks[i].data.length);
2173
+
2174
+ }
2175
+
2176
+ chunks_ranges.sort(function(a, b) {
2177
+ return a - b;
2178
+ });
2179
+
2180
+ update_streams[stream_id]={
2181
+ chunks_ranges: chunks_ranges,
2182
+ send_offset_next: send_offset_next
2183
+ };
2184
+
2185
+ }
2186
+ }
2187
+
2188
+
2189
+ if(encoded_frames.length>0){
2190
+
2191
+
2192
+ /*
2193
+ console.log('allowed_packet_size::::::::::::');
2194
+ console.log(allowed_packet_size);
2195
+
2196
+ console.log('update_streams::::::::::::');
2197
+ console.log(update_streams);
2198
+
2199
+ console.log('frames::::::::::::');
2200
+ console.log(frames);
2201
+
2202
+ console.log('encoded_frames::::::::::::');
2203
+ console.log(encoded_frames);
2204
+ */
2205
+
2206
+ if(encoded_frames.length==1){
2207
+ var all_encoded_frames = encoded_frames[0];
2208
+ }else if(encoded_frames.length>1){
2209
+ var all_encoded_frames = concatUint8Arrays(encoded_frames);
2210
+ }
2211
+
2212
+ send_quic_packet(server,quic_connection_id,'1rtt',all_encoded_frames,function(is_sent){
2213
+ if(is_sent==true){
2214
+ now = Math.floor(performance.timeOrigin + performance.now());
2215
+
2216
+ var packet_number=server.connections[quic_connection_id].sending_app_pn_base;
2217
+ conn.sending_app_pn_history.push([now, all_encoded_frames.length]);
2218
+ conn.sending_app_pn_in_flight.add(packet_number);
2219
+
2220
+ for(var stream_id in update_streams){
2221
+ server.connections[quic_connection_id].sending_streams[stream_id].in_flight_ranges[packet_number]=update_streams[stream_id].chunks_ranges;
2222
+ server.connections[quic_connection_id].sending_streams[stream_id].send_offset_next=update_streams[stream_id].send_offset_next;
2223
+ }
2224
+
2225
+ //console.log(server.connections[quic_connection_id].sending_streams);
2226
+
2227
+ if(remove_pending_ack.length>0){
2228
+ flat_ranges.remove(conn.receiving_app_pn_pending_ack,remove_pending_ack);
2229
+ }
2230
+
2231
+
2232
+ server.connections[quic_connection_id].sending_app_pn_base++;
2233
+ }
2234
+
2235
+ // אם שלחנו הרגע פאקט ואין עדיין מגבלות, נמתין את הזמן הזה כדי לפזר נכון
2236
+ //var interval_between_packets = Math.ceil(1000 / server.max_sending_packets_per_sec);
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+ //conn.next_send_quic_packet_timer=null;
2244
+ //prepare_and_send_quic_packet(server, quic_connection_id);
2245
+
2246
+
2247
+ conn.next_send_quic_packet_timer=setTimeout(function(){
2248
+ conn.sending_quic_packet_now=false;
2249
+ conn.next_send_quic_packet_timer=null;
2250
+ prepare_and_send_quic_packet(server, quic_connection_id);
2251
+ }, 0);
2252
+
2253
+
2254
+ });
2255
+
2256
+
2257
+ }else{
2258
+
2259
+ conn.next_send_quic_packet_timer=null;
2260
+ conn.sending_quic_packet_now=false;
2261
+
2262
+ }
2263
+
2264
+ }else{
2265
+
2266
+ // ✋ לא ניתן לשלוח כרגע — צריך לחשב מתי כן יהיה אפשר
2267
+ var wait_options = [];
2268
+
2269
+ // זמן עד שיימחק פאקט שמפחית מגבלת פאקטים
2270
+ if (packets_left <= 0 && oldest_packet_time_packets !== null) {
2271
+ var wait_packets = Math.max(0, (oldest_packet_time_packets + 1000) - now);
2272
+ wait_options.push(wait_packets);
2273
+ }
2274
+
2275
+ // זמן עד שיימחק מספיק בייטים
2276
+ if (bytes_left < conn.min_sending_packet_size && oldest_packet_time_bytes !== null) {
2277
+ var wait_bytes = Math.max(0, (oldest_packet_time_bytes + 1000) - now);
2278
+ wait_options.push(wait_bytes);
2279
+ }
2280
+
2281
+
2282
+
2283
+ if (wait_options.length > 0) {
2284
+ conn.next_send_quic_packet_timer = setTimeout(function(){
2285
+ conn.next_send_quic_packet_timer=null;
2286
+ conn.sending_quic_packet_now=false;
2287
+ prepare_and_send_quic_packet(server, quic_connection_id);
2288
+ }, Math.max(...wait_options));
2289
+
2290
+ //console.log('next_time: ',(Math.max(...wait_options)));
2291
+ }else{
2292
+ conn.sending_quic_packet_now=false;
2293
+ }
2294
+
2295
+ }
2296
+
2297
+ }
2298
+
2299
+ }
2300
+
2301
+
2302
+
2303
+ function quic_stream_write(server,quic_connection_id,stream_id,data,fin){
2304
+ if(quic_connection_id in server.connections==true){
2305
+
2306
+ if(stream_id in server.connections[quic_connection_id].sending_streams==false){
2307
+ server.connections[quic_connection_id].sending_streams[stream_id]={
2308
+ pending_data: null,
2309
+ write_offset_next: 0,
2310
+ pending_offset_start: 0,
2311
+ send_offset_next: 0,
2312
+ total_size: 0,
2313
+
2314
+ in_flight_ranges: {},
2315
+ acked_ranges: [],
2316
+ };
2317
+ }
2318
+
2319
+
2320
+ var stream = server.connections[quic_connection_id].sending_streams[stream_id];
2321
+
2322
+ var start_offset = stream.write_offset_next;
2323
+ var end_offset = start_offset + data.byteLength;
2324
+ stream.write_offset_next = end_offset;
2325
+ //stream.total_size = end_offset;
2326
+
2327
+ if (fin === true) {
2328
+ stream.total_size = end_offset; // הגודל הסופי של הזרם
2329
+ }
2330
+
2331
+ // קבע את התחלת ה־pending לפי acked_ranges
2332
+ var pending_offset_start = 0;
2333
+ if (stream.acked_ranges.length > 0 && stream.acked_ranges[0] === 0) {
2334
+ pending_offset_start = stream.acked_ranges[1];
2335
+ }
2336
+
2337
+ // גזור רק את החלק שטרם קיבל ACK
2338
+ var skip = Math.max(pending_offset_start - start_offset, 0);
2339
+ if (skip >= data.byteLength) return; // אין מה להוסיף
2340
+
2341
+ var trimmed_data = data.slice(skip);
2342
+
2343
+ if (stream.pending_data === null) {
2344
+ stream.pending_data = trimmed_data;
2345
+ stream.pending_offset_start = start_offset + skip;
2346
+ } else {
2347
+ // מיזוג ל־Uint8Array חדש
2348
+ var old = stream.pending_data;
2349
+ var old_offset = stream.pending_offset_start;
2350
+ var new_offset = start_offset + skip;
2351
+
2352
+ var new_start = Math.min(old_offset, new_offset);
2353
+ var new_end = Math.max(old_offset + old.length, new_offset + trimmed_data.length);
2354
+ var total_len = new_end - new_start;
2355
+
2356
+ var merged = new Uint8Array(total_len);
2357
+
2358
+ // העתק ישן
2359
+ merged.set(old, old_offset - new_start);
2360
+
2361
+ // העתק חדש
2362
+ merged.set(trimmed_data, new_offset - new_start);
2363
+
2364
+ stream.pending_data = merged;
2365
+ stream.pending_offset_start = new_start;
2366
+
2367
+ }
2368
+
2369
+ prepare_and_send_quic_packet(server, quic_connection_id);
2370
+ }
2371
+ }
2372
+
2373
+ function set_sending_quic_chunk(server,quic_connection_id,options){
2374
+ if(quic_connection_id in server.connections==true){
2375
+
2376
+ var type=null;
2377
+ var data=null;
2378
+ var stream_id=null;
2379
+ var fin=false;
2380
+
2381
+ if(typeof options=='object'){
2382
+ if('type' in options){
2383
+ type=options.type;
2384
+ }
2385
+
2386
+ if('data' in options){
2387
+ data=options.data;
2388
+ }
2389
+
2390
+ if('stream_id' in options){
2391
+ stream_id=options.stream_id;
2392
+ type='1rtt';
2393
+ }
2394
+
2395
+ if('fin' in options){
2396
+ fin=options.fin;
2397
+ }
2398
+ }
2399
+
2400
+
2401
+ if(type=='initial'){
2402
+
2403
+ //server.connections[quic_connection_id].sending_init_chunks.push(data);
2404
+
2405
+ send_quic_frames_packet(server,quic_connection_id,'initial',[{type: 'crypto', offset: server.connections[quic_connection_id].sending_init_offset_next, data: data}]);
2406
+
2407
+ server.connections[quic_connection_id].sending_init_offset_next=server.connections[quic_connection_id].sending_init_offset_next+data.byteLength;
2408
+
2409
+ }else if(type=='handshake'){
2410
+
2411
+ //server.connections[quic_connection_id].sending_handshake_chunks.push(data);
2412
+
2413
+ send_quic_frames_packet(server,quic_connection_id,'handshake',[{type: 'crypto', offset: server.connections[quic_connection_id].sending_handshake_offset_next, data: data}]);
2414
+
2415
+ server.connections[quic_connection_id].sending_handshake_offset_next=server.connections[quic_connection_id].sending_handshake_offset_next+data.byteLength;
2416
+
2417
+ }else if(type=='1rtt'){
2418
+
2419
+ if(stream_id!==null){
2420
+
2421
+
2422
+ if(stream_id in server.connections[quic_connection_id].sending_streams==false){
2423
+ server.connections[quic_connection_id].sending_streams[stream_id]={
2424
+ offset_next: 0,
2425
+ };
2426
+ }
2427
+
2428
+ send_quic_frames_packet(server,quic_connection_id,'1rtt',[{
2429
+ type: 'stream',
2430
+ id: Number(stream_id),
2431
+ offset: server.connections[quic_connection_id].sending_streams[stream_id].offset_next,
2432
+ fin: fin,
2433
+ data: data
2434
+ }]);
2435
+
2436
+ server.connections[quic_connection_id].sending_streams[stream_id].offset_next=server.connections[quic_connection_id].sending_streams[stream_id].offset_next+data.byteLength;
2437
+
2438
+
2439
+ }
2440
+
2441
+
2442
+
2443
+ }
2444
+
2445
+
2446
+
2447
+
2448
+
2449
+ }
2450
+ }
2451
+
2452
+
2453
+ function quic_connection(server,quic_connection_id,current_params,prev_params){
2454
+ if(current_params!==null){
2455
+
2456
+ if(current_params.connection_status!==prev_params.connection_status){
2457
+
2458
+ //console.log(server.connections[quic_connection_id]);
2459
+
2460
+ if(current_params.connection_status==1){
2461
+ //איתות שיש לנו בצלחה פעם ראשונה
2462
+
2463
+
2464
+ send_quic_frames_packet(server,quic_connection_id,'1rtt',[{
2465
+ type: 'handshake_done'
2466
+ }]);
2467
+
2468
+ }
2469
+
2470
+ if(current_params.connection_status==1){
2471
+
2472
+
2473
+ var settings_frame=build_settings_frame({
2474
+ SETTINGS_QPACK_MAX_TABLE_CAPACITY: 65536,
2475
+ SETTINGS_MAX_FIELD_SECTION_SIZE: 65536,
2476
+ SETTINGS_ENABLE_WEBTRANSPORT: 1,
2477
+ SETTINGS_H3_DATAGRAM: 1,
2478
+ SETTINGS_ENABLE_CONNECT_PROTOCOL: 1,
2479
+ SETTINGS_WT_MAX_SESSIONS: 1
2480
+ //SETTINGS_NO_RFC9114_LEGACY_CODEPOINT: 1
2481
+ });
2482
+
2483
+ var control_stream_frames=build_h3_frames([
2484
+ { frame_type: 0x04, payload: settings_frame },
2485
+ ]);
2486
+
2487
+ quic_stream_write(server,quic_connection_id,3,concatUint8Arrays([new Uint8Array([0x00]),control_stream_frames]),false);
2488
+
2489
+
2490
+ /*
2491
+ set_sending_quic_chunk(server,quic_connection_id,{
2492
+ type: '1rtt',
2493
+ stream_id: 3,
2494
+ data: concatUint8Arrays([new Uint8Array([0x00]),control_stream_frames])
2495
+ });
2496
+ */
2497
+
2498
+ quic_stream_write(server,quic_connection_id,7,new Uint8Array([0x02]),false);
2499
+
2500
+ /*
2501
+ set_sending_quic_chunk(server,quic_connection_id,{
2502
+ type: '1rtt',
2503
+ stream_id: 7,
2504
+ data: new Uint8Array([0x02])
2505
+ });
2506
+ */
2507
+
2508
+ quic_stream_write(server,quic_connection_id,11,new Uint8Array([0x03]),false);
2509
+
2510
+ /*
2511
+ set_sending_quic_chunk(server,quic_connection_id,{
2512
+ type: '1rtt',
2513
+ stream_id: 11,
2514
+ data: new Uint8Array([0x03])
2515
+ });
2516
+ */
2517
+
2518
+
2519
+
2520
+ }
2521
+
2522
+ }
2523
+
2524
+ if(current_params.sni!==prev_params.sni){
2525
+
2526
+ server.SNICallback(current_params.sni, function (err, creds) {
2527
+ if (!err && creds) {
2528
+ set_quic_connection(server, quic_connection_id, {
2529
+ cert: creds.cert,
2530
+ key: creds.key
2531
+ });
2532
+ } else {
2533
+ //console.log('No TLS credentials for', current_params.sni);
2534
+ }
2535
+ });
2536
+
2537
+ }
2538
+
2539
+ }
2540
+ }
2541
+
2542
+
2543
+
2544
+
2545
+ function createServer(options, handler) {
2546
+ var server = {
2547
+ _udp4: null,
2548
+ _udp6: null,
2549
+ _port: null,
2550
+ _handler: handler || null,
2551
+ SNICallback: options.SNICallback || null,
2552
+ connections: {},
2553
+ address_binds: {},
2554
+ _timeout: null,
2555
+
2556
+ listen: function(port, host, callback) {
2557
+ var self = this;
2558
+
2559
+ // אם המשתמש לא סיפק host אלא רק callback
2560
+ if (typeof host === 'function') {
2561
+ callback = host;
2562
+ host = null;
2563
+ }
2564
+
2565
+ self._port = port || 443;
2566
+ host = host || '::';
2567
+
2568
+ // יצירת סוקט UDP4
2569
+ self._udp4 = dgram.createSocket('udp4');
2570
+ self._udp4.on('message', function(msg, rinfo) {
2571
+ receiving_udp_quic_packet(self, rinfo.address, rinfo.port, new Uint8Array(msg));
2572
+ });
2573
+ self._udp4.on('error', function(err) {
2574
+ //console.error('UDP4 error:', err);
2575
+ });
2576
+
2577
+ if (host === '::' || host.indexOf('.') !== -1) {
2578
+ var host4 = host.indexOf('.') !== -1 ? host : '0.0.0.0';
2579
+ self._udp4.bind(self._port, host4);
2580
+ }
2581
+
2582
+ // יצירת סוקט UDP6
2583
+ self._udp6 = dgram.createSocket({ type: 'udp6', ipv6Only: true });
2584
+ self._udp6.on('message', function(msg, rinfo) {
2585
+ receiving_udp_quic_packet(self, rinfo.address, rinfo.port, new Uint8Array(msg));
2586
+ });
2587
+ self._udp6.on('error', function(err) {
2588
+ //console.error('UDP6 error:', err);
2589
+ });
2590
+
2591
+ var host6 = host.indexOf(':') !== -1 ? host : '::';
2592
+ self._udp6.bind(self._port, host6, function() {
2593
+ if (typeof callback === 'function') {
2594
+ callback();
2595
+ }
2596
+ });
2597
+ },
2598
+
2599
+
2600
+ on: function(event, cb) {
2601
+ if (event === 'request'){
2602
+ this._handler = cb;
2603
+ }else if(event === 'webtransport'){
2604
+ this._webtransport_handler = cb;
2605
+
2606
+ }else if(event === 'OCSPRequest'){
2607
+
2608
+ }else if(event === 'newSession'){
2609
+
2610
+ }else if(event === 'resumeSession'){
2611
+
2612
+ }
2613
+ },
2614
+
2615
+ close: function() {
2616
+ if (this._udp4) this._udp4.close();
2617
+ if (this._udp6) this._udp6.close();
2618
+ },
2619
+
2620
+ setTimeout: function(ms, cb) {
2621
+ this._timeout = setTimeout(cb, ms);
2622
+ }
2623
+ };
2624
+
2625
+ return server;
2626
+ }
2627
+
2628
+
2629
+ module.exports = {
2630
+ createServer
2631
+ };