@fails-components/webtransport 0.0.6 → 0.0.7
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/CMakeLists.txt +11 -6
- package/package.json +1 -1
- package/platform/quiche_platform_impl/quic_udp_socket_winsock.cc +605 -523
- package/src/http3client.cc +86 -72
- package/src/http3client.h +6 -0
- package/src/http3dispatcher.cc +5 -3
- package/src/http3dispatcher.h +2 -1
- package/src/http3server.cc +47 -10
- package/src/http3server.h +2 -1
- package/test/testsuite.js +8 -8
package/src/http3client.cc
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
#include "absl/strings/match.h"
|
|
21
21
|
#include "absl/strings/string_view.h"
|
|
22
|
+
#include "absl/cleanup/cleanup.h"
|
|
22
23
|
#include "openssl/x509.h"
|
|
23
24
|
#include "quiche/quic/core/crypto/proof_verifier.h"
|
|
24
25
|
#include "quiche/quic/core/http/quic_spdy_client_stream.h"
|
|
@@ -44,41 +45,41 @@ using spdy::Http2HeaderBlock;
|
|
|
44
45
|
namespace quic
|
|
45
46
|
{
|
|
46
47
|
|
|
47
|
-
// taken from libquiche
|
|
48
|
-
namespace
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
// For level-triggered I/O, we need to manually rearm the kSocketEventWritable
|
|
52
|
-
// listener whenever the socket gets blocked.
|
|
53
|
-
class LevelTriggeredPacketWriter : public QuicDefaultPacketWriter
|
|
48
|
+
// taken from libquiche
|
|
49
|
+
namespace
|
|
54
50
|
{
|
|
55
|
-
public:
|
|
56
|
-
explicit LevelTriggeredPacketWriter(int fd, QuicEventLoop *event_loop)
|
|
57
|
-
: QuicDefaultPacketWriter(fd), event_loop_(event_loop)
|
|
58
|
-
{
|
|
59
|
-
QUICHE_DCHECK(!event_loop->SupportsEdgeTriggered());
|
|
60
|
-
}
|
|
61
51
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
PerPacketOptions *options) override
|
|
52
|
+
// For level-triggered I/O, we need to manually rearm the kSocketEventWritable
|
|
53
|
+
// listener whenever the socket gets blocked.
|
|
54
|
+
class LevelTriggeredPacketWriter : public QuicDefaultPacketWriter
|
|
66
55
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
public:
|
|
57
|
+
explicit LevelTriggeredPacketWriter(int fd, QuicEventLoop *event_loop)
|
|
58
|
+
: QuicDefaultPacketWriter(fd), event_loop_(event_loop)
|
|
70
59
|
{
|
|
71
|
-
|
|
72
|
-
QUICHE_DCHECK(success);
|
|
60
|
+
QUICHE_DCHECK(!event_loop->SupportsEdgeTriggered());
|
|
73
61
|
}
|
|
74
|
-
return result;
|
|
75
|
-
}
|
|
76
62
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
63
|
+
WriteResult WritePacket(const char *buffer, size_t buf_len,
|
|
64
|
+
const QuicIpAddress &self_address,
|
|
65
|
+
const QuicSocketAddress &peer_address,
|
|
66
|
+
PerPacketOptions *options) override
|
|
67
|
+
{
|
|
68
|
+
WriteResult result = QuicDefaultPacketWriter::WritePacket(
|
|
69
|
+
buffer, buf_len, self_address, peer_address, options);
|
|
70
|
+
if (IsWriteBlockedStatus(result.status))
|
|
71
|
+
{
|
|
72
|
+
bool success = event_loop_->RearmSocket(fd(), kSocketEventWritable);
|
|
73
|
+
QUICHE_DCHECK(success);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private:
|
|
79
|
+
QuicEventLoop *event_loop_;
|
|
80
|
+
};
|
|
80
81
|
|
|
81
|
-
} // namespace
|
|
82
|
+
} // namespace
|
|
82
83
|
|
|
83
84
|
// taken from chromium to behave like the browser
|
|
84
85
|
// A version of WebTransportFingerprintProofVerifier that enforces
|
|
@@ -480,6 +481,9 @@ namespace
|
|
|
480
481
|
overflow_supported_ = api.EnableDroppedPacketCount(fd);
|
|
481
482
|
api.EnableReceiveTimestamp(fd);
|
|
482
483
|
|
|
484
|
+
auto closer = absl::MakeCleanup([fd]
|
|
485
|
+
{ QuicUdpSocketApi api;api.Destroy(fd); });
|
|
486
|
+
|
|
483
487
|
QuicSocketAddress client_address;
|
|
484
488
|
if (bind_to_address.IsInitialized())
|
|
485
489
|
{
|
|
@@ -528,10 +532,13 @@ namespace
|
|
|
528
532
|
}
|
|
529
533
|
const int kEpollFlags = kSocketEventReadable | kSocketEventWritable; // there is no analogue to EPOLLET in libuv hopefully not a problem
|
|
530
534
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
+
if (eventloop_->getQuicEventLoop()->RegisterSocket(fd, kEpollFlags, this))
|
|
536
|
+
{
|
|
537
|
+
fd_address_map_[fd] = client_address;
|
|
538
|
+
std::move(closer).Cancel();
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
return false;
|
|
535
542
|
}
|
|
536
543
|
|
|
537
544
|
void Http3Client::CleanUpUDPSocket(int fd)
|
|
@@ -687,8 +694,8 @@ namespace
|
|
|
687
694
|
Http3WTSession *wtsessionobj =
|
|
688
695
|
new Http3WTSession();
|
|
689
696
|
wtsessionobj->init(
|
|
690
|
-
|
|
691
|
-
|
|
697
|
+
static_cast<WebTransportSession *>(wtsession),
|
|
698
|
+
eventloop_);
|
|
692
699
|
eventloop_->informNewClientSession(this, wtsessionobj);
|
|
693
700
|
auto visitor = std::make_unique<Http3WTSession::Visitor>(wtsessionobj);
|
|
694
701
|
wtsession->SetVisitor(std::move(visitor));
|
|
@@ -753,7 +760,7 @@ namespace
|
|
|
753
760
|
|
|
754
761
|
session_ = std::make_unique<Http3ClientSession>(
|
|
755
762
|
config_, client_supported_versions, new QuicConnection(newconnid, QuicSocketAddress(), server_address_, helper_.get(), alarm_factory_.get(), writer,
|
|
756
|
-
/* owns_writer= */ false, Perspective::IS_CLIENT, client_supported_versions),
|
|
763
|
+
/* owns_writer= */ false, Perspective::IS_CLIENT, client_supported_versions, connection_id_generator_),
|
|
757
764
|
server_id_, &crypto_config_,
|
|
758
765
|
&push_promise_index_, false /*drop_response_body_*/, true /* enable_web_transport */);
|
|
759
766
|
|
|
@@ -924,7 +931,7 @@ namespace
|
|
|
924
931
|
bool success =
|
|
925
932
|
event_loop->ArtificiallyNotifyEvent(fd, kSocketEventReadable);
|
|
926
933
|
QUICHE_DCHECK(success);
|
|
927
|
-
}
|
|
934
|
+
}
|
|
928
935
|
if (!event_loop->SupportsEdgeTriggered())
|
|
929
936
|
{
|
|
930
937
|
bool success = event_loop->RearmSocket(fd, kSocketEventReadable);
|
|
@@ -1292,8 +1299,7 @@ namespace
|
|
|
1292
1299
|
latest_created_stream_ = nullptr;
|
|
1293
1300
|
}
|
|
1294
1301
|
|
|
1295
|
-
Http3ClientJS::Http3ClientJS(const Napi::CallbackInfo &info) :
|
|
1296
|
-
Napi::ObjectWrap<Http3ClientJS>(info)
|
|
1302
|
+
Http3ClientJS::Http3ClientJS(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Http3ClientJS>(info)
|
|
1297
1303
|
{
|
|
1298
1304
|
|
|
1299
1305
|
std::string port = "443";
|
|
@@ -1310,39 +1316,41 @@ namespace
|
|
|
1310
1316
|
if (!lobj.IsEmpty())
|
|
1311
1317
|
{
|
|
1312
1318
|
|
|
1313
|
-
if (lobj.Has(
|
|
1319
|
+
if (lobj.Has("allowPooling") && !(lobj).Get("allowPooling").IsEmpty())
|
|
1314
1320
|
{
|
|
1315
1321
|
Napi::Value poolValue = (lobj).Get("allowPooling");
|
|
1316
1322
|
allowPooling = poolValue.As<Napi::Boolean>().Value();
|
|
1317
1323
|
}
|
|
1318
1324
|
|
|
1319
|
-
if (lobj.Has(
|
|
1325
|
+
if (lobj.Has("forceIpv6") && !(lobj).Get("forceIpv6").IsEmpty())
|
|
1320
1326
|
{
|
|
1321
1327
|
Napi::Value ipv6Value = (lobj).Get("forceIpv6");
|
|
1322
1328
|
forceipv6 = ipv6Value.As<Napi::Boolean>().Value();
|
|
1323
1329
|
}
|
|
1324
1330
|
|
|
1325
|
-
if (lobj.Has(
|
|
1331
|
+
if (lobj.Has("port") && !(lobj).Get("port").IsEmpty())
|
|
1326
1332
|
{
|
|
1327
1333
|
Napi::Value portValue = (lobj).Get("port");
|
|
1328
1334
|
port = portValue.ToString().Utf8Value();
|
|
1329
1335
|
}
|
|
1330
|
-
else
|
|
1336
|
+
else
|
|
1337
|
+
{
|
|
1331
1338
|
Napi::Error::New(env, "no port specified").ThrowAsJavaScriptException();
|
|
1332
|
-
return
|
|
1339
|
+
return;
|
|
1333
1340
|
}
|
|
1334
1341
|
|
|
1335
|
-
if (lobj.Has(
|
|
1342
|
+
if (lobj.Has("hostname") && !(lobj).Get("hostname").IsEmpty())
|
|
1336
1343
|
{
|
|
1337
1344
|
Napi::Value hostnameValue = (lobj).Get("hostname");
|
|
1338
1345
|
hostname = hostnameValue.ToString().Utf8Value();
|
|
1339
1346
|
}
|
|
1340
|
-
else
|
|
1347
|
+
else
|
|
1348
|
+
{
|
|
1341
1349
|
Napi::Error::New(env, "no hostname specified").ThrowAsJavaScriptException();
|
|
1342
|
-
return
|
|
1350
|
+
return;
|
|
1343
1351
|
}
|
|
1344
1352
|
|
|
1345
|
-
if (lobj.Has(
|
|
1353
|
+
if (lobj.Has("serverCertificateHashes") && !(lobj).Get("serverCertificateHashes").IsEmpty())
|
|
1346
1354
|
{
|
|
1347
1355
|
Napi::Value hashValue = (lobj).Get("serverCertificateHashes");
|
|
1348
1356
|
if (hashValue.IsArray())
|
|
@@ -1362,40 +1370,45 @@ namespace
|
|
|
1362
1370
|
size_t len = bufferlocal.As<Napi::Buffer<char>>().Length();
|
|
1363
1371
|
curhash.value = std::string(buffer, len);
|
|
1364
1372
|
}
|
|
1365
|
-
else
|
|
1373
|
+
else
|
|
1374
|
+
{
|
|
1366
1375
|
Napi::Error::New(env, "serverCertificateHashes wrong format").ThrowAsJavaScriptException();
|
|
1367
|
-
return
|
|
1376
|
+
return;
|
|
1368
1377
|
}
|
|
1369
1378
|
if (hashobj.Has("algorithm") && !(hashobj).Get("algorithm").IsEmpty())
|
|
1370
1379
|
{
|
|
1371
1380
|
Napi::Value algorithmValue = (hashobj).Get("algorithm");
|
|
1372
1381
|
curhash.algorithm = algorithmValue.ToString().Utf8Value();
|
|
1373
1382
|
}
|
|
1374
|
-
else
|
|
1383
|
+
else
|
|
1384
|
+
{
|
|
1375
1385
|
Napi::Error::New(env, "serverCertificateHashes wrong format").ThrowAsJavaScriptException();
|
|
1376
|
-
return
|
|
1386
|
+
return;
|
|
1377
1387
|
}
|
|
1378
|
-
if (curhash.algorithm.compare(WebTransportHash::kSha256) != 0)
|
|
1388
|
+
if (curhash.algorithm.compare(WebTransportHash::kSha256) != 0)
|
|
1389
|
+
{
|
|
1379
1390
|
Napi::Error::New(env, "serverCertificateHashes unknown algorithm").ThrowAsJavaScriptException();
|
|
1380
|
-
return
|
|
1391
|
+
return;
|
|
1381
1392
|
}
|
|
1382
1393
|
serverCertificateHashes.push_back(curhash);
|
|
1383
1394
|
}
|
|
1384
1395
|
}
|
|
1385
|
-
else
|
|
1396
|
+
else
|
|
1397
|
+
{
|
|
1386
1398
|
Napi::Error::New(env, "serverCertificateHashes is not an array").ThrowAsJavaScriptException();
|
|
1387
|
-
return
|
|
1399
|
+
return;
|
|
1388
1400
|
}
|
|
1389
1401
|
}
|
|
1390
1402
|
|
|
1391
|
-
if (lobj.Has(
|
|
1403
|
+
if (lobj.Has("localPort") && !(lobj).Get("localPort").IsEmpty())
|
|
1392
1404
|
{
|
|
1393
1405
|
Napi::Value localPortValue = (lobj).Get("localPort");
|
|
1394
1406
|
if (localPortValue.IsNumber())
|
|
1395
1407
|
local_port = localPortValue.As<Napi::Number>().Int32Value();
|
|
1396
|
-
else
|
|
1408
|
+
else
|
|
1409
|
+
{
|
|
1397
1410
|
Napi::Error::New(env, "localPort is not a number").ThrowAsJavaScriptException();
|
|
1398
|
-
return
|
|
1411
|
+
return;
|
|
1399
1412
|
}
|
|
1400
1413
|
}
|
|
1401
1414
|
}
|
|
@@ -1412,7 +1425,7 @@ namespace
|
|
|
1412
1425
|
else
|
|
1413
1426
|
{
|
|
1414
1427
|
Napi::Error::New(env, "No eventloop arguments passed to Http3Client").ThrowAsJavaScriptException();
|
|
1415
|
-
return
|
|
1428
|
+
return;
|
|
1416
1429
|
}
|
|
1417
1430
|
|
|
1418
1431
|
std::unique_ptr<QuicConnectionHelperInterface> helper =
|
|
@@ -1430,13 +1443,14 @@ namespace
|
|
|
1430
1443
|
if (!verifier->AddFingerprint(*cur))
|
|
1431
1444
|
{
|
|
1432
1445
|
Napi::Error::New(env, "serverCertificateHashes is not valid fingerprint").ThrowAsJavaScriptException();
|
|
1433
|
-
return
|
|
1446
|
+
return;
|
|
1434
1447
|
}
|
|
1435
1448
|
}
|
|
1436
1449
|
}
|
|
1437
|
-
else
|
|
1450
|
+
else
|
|
1451
|
+
{
|
|
1438
1452
|
Napi::Error::New(env, "No supported verification method included").ThrowAsJavaScriptException();
|
|
1439
|
-
return
|
|
1453
|
+
return;
|
|
1440
1454
|
}
|
|
1441
1455
|
|
|
1442
1456
|
std::unique_ptr<Http3SessionCache> cache;
|
|
@@ -1463,7 +1477,7 @@ namespace
|
|
|
1463
1477
|
<< gai_strerror(result);
|
|
1464
1478
|
info_list = nullptr;
|
|
1465
1479
|
Napi::Error::New(env, "URL host lookup failed").ThrowAsJavaScriptException();
|
|
1466
|
-
return
|
|
1480
|
+
return;
|
|
1467
1481
|
}
|
|
1468
1482
|
|
|
1469
1483
|
QUICHE_CHECK(info_list != nullptr);
|
|
@@ -1471,7 +1485,7 @@ namespace
|
|
|
1471
1485
|
freeaddrinfo(info_list);
|
|
1472
1486
|
|
|
1473
1487
|
client_ = std::make_unique<Http3Client>(eventloop, address, hostname, local_port,
|
|
1474
|
-
|
|
1488
|
+
std::move(verifier), std::move(cache), std::move(helper));
|
|
1475
1489
|
client_->SetUserAgentID("fails-components/webtransport");
|
|
1476
1490
|
|
|
1477
1491
|
client_->setJS(this);
|
|
@@ -1483,11 +1497,10 @@ namespace
|
|
|
1483
1497
|
client_->Connect();
|
|
1484
1498
|
};
|
|
1485
1499
|
client_->eventloop_->Schedule(task);
|
|
1486
|
-
return
|
|
1500
|
+
return;
|
|
1487
1501
|
}
|
|
1488
1502
|
|
|
1489
|
-
|
|
1490
|
-
void Http3ClientJS::openWTSession(const Napi::CallbackInfo& info)
|
|
1503
|
+
void Http3ClientJS::openWTSession(const Napi::CallbackInfo &info)
|
|
1491
1504
|
{
|
|
1492
1505
|
Http3Client *obj = getObj();
|
|
1493
1506
|
// got the object we can now start the server
|
|
@@ -1501,13 +1514,14 @@ namespace
|
|
|
1501
1514
|
};
|
|
1502
1515
|
obj->eventloop_->Schedule(task);
|
|
1503
1516
|
}
|
|
1504
|
-
else
|
|
1517
|
+
else
|
|
1518
|
+
{
|
|
1505
1519
|
Napi::Error::New(info.Env(), "openWTSession without path").ThrowAsJavaScriptException();
|
|
1506
|
-
return
|
|
1520
|
+
return;
|
|
1507
1521
|
}
|
|
1508
1522
|
}
|
|
1509
1523
|
|
|
1510
|
-
void Http3ClientJS::closeClient(const Napi::CallbackInfo&
|
|
1524
|
+
void Http3ClientJS::closeClient(const Napi::CallbackInfo &info)
|
|
1511
1525
|
{
|
|
1512
1526
|
Http3Client *obj = getObj();
|
|
1513
1527
|
// got the object we can now start the server
|
|
@@ -1515,8 +1529,8 @@ namespace
|
|
|
1515
1529
|
{
|
|
1516
1530
|
if (!obj->closeClientInt())
|
|
1517
1531
|
{
|
|
1518
|
-
printf(
|
|
1519
|
-
return
|
|
1532
|
+
printf("closeClientInt failed for Http3Client");
|
|
1533
|
+
return;
|
|
1520
1534
|
}
|
|
1521
1535
|
};
|
|
1522
1536
|
obj->eventloop_->Schedule(task);
|
package/src/http3client.h
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
#include "quiche/quic/core/quic_packet_reader.h"
|
|
30
30
|
#include "quiche/quic/platform/api/quic_socket_address.h"
|
|
31
31
|
#include "quiche/quic/core/proto/cached_network_parameters_proto.h"
|
|
32
|
+
#include "quiche/quic/core/deterministic_connection_id_generator.h"
|
|
32
33
|
#include "quiche/quic/core/quic_framer.h"
|
|
33
34
|
#include "quiche/quic/core/quic_packet_creator.h"
|
|
34
35
|
#include "quiche/quic/core/quic_packets.h"
|
|
@@ -353,6 +354,8 @@ namespace quic
|
|
|
353
354
|
// Returns true if the corresponding of this client has active requests.
|
|
354
355
|
bool HasActiveRequests();
|
|
355
356
|
|
|
357
|
+
ConnectionIdGeneratorInterface &connection_id_generator();
|
|
358
|
+
|
|
356
359
|
// Actually clean up |fd|.
|
|
357
360
|
void CleanUpUDPSocketImpl(QuicUdpSocketFd fd);
|
|
358
361
|
|
|
@@ -541,6 +544,9 @@ namespace quic
|
|
|
541
544
|
// space than allowed on the stack.
|
|
542
545
|
std::unique_ptr<QuicPacketReader> packet_reader_;
|
|
543
546
|
|
|
547
|
+
DeterministicConnectionIdGenerator connection_id_generator_{
|
|
548
|
+
kQuicDefaultConnectionIdLength};
|
|
549
|
+
|
|
544
550
|
Http3EventLoop *eventloop_;
|
|
545
551
|
// connection workflow
|
|
546
552
|
bool wait_for_encryption_;
|
package/src/http3dispatcher.cc
CHANGED
|
@@ -23,14 +23,16 @@ Http3Dispatcher::Http3Dispatcher(
|
|
|
23
23
|
std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
|
|
24
24
|
std::unique_ptr<QuicAlarmFactory> alarm_factory,
|
|
25
25
|
Http3ServerBackend* http3_server_backend,
|
|
26
|
-
uint8_t expected_server_connection_id_length
|
|
26
|
+
uint8_t expected_server_connection_id_length,
|
|
27
|
+
ConnectionIdGeneratorInterface& generator)
|
|
27
28
|
: QuicDispatcher(config,
|
|
28
29
|
crypto_config,
|
|
29
30
|
version_manager,
|
|
30
31
|
std::move(helper),
|
|
31
32
|
std::move(session_helper),
|
|
32
33
|
std::move(alarm_factory),
|
|
33
|
-
expected_server_connection_id_length
|
|
34
|
+
expected_server_connection_id_length,
|
|
35
|
+
generator),
|
|
34
36
|
http3_server_backend_(http3_server_backend) {}
|
|
35
37
|
|
|
36
38
|
Http3Dispatcher::~Http3Dispatcher() = default;
|
|
@@ -47,7 +49,7 @@ std::unique_ptr<QuicSession> Http3Dispatcher::CreateQuicSession(
|
|
|
47
49
|
new QuicConnection(connection_id, self_address, peer_address, helper(),
|
|
48
50
|
alarm_factory(), writer(),
|
|
49
51
|
/* owns_writer= */ false, Perspective::IS_SERVER,
|
|
50
|
-
ParsedQuicVersionVector{version});
|
|
52
|
+
ParsedQuicVersionVector{version}, connection_id_generator());
|
|
51
53
|
|
|
52
54
|
auto session = std::make_unique<Http3ServerSession>(
|
|
53
55
|
config(), GetSupportedVersions(), connection, this, session_helper(),
|
package/src/http3dispatcher.h
CHANGED
|
@@ -30,7 +30,8 @@ namespace quic
|
|
|
30
30
|
std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
|
|
31
31
|
std::unique_ptr<QuicAlarmFactory> alarm_factory,
|
|
32
32
|
Http3ServerBackend *http3_server_backend,
|
|
33
|
-
uint8_t expected_server_connection_id_length
|
|
33
|
+
uint8_t expected_server_connection_id_length,
|
|
34
|
+
ConnectionIdGeneratorInterface& generator);
|
|
34
35
|
|
|
35
36
|
~Http3Dispatcher() override;
|
|
36
37
|
|
package/src/http3server.cc
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// Use of this source code is governed by a BSD-style license that can be
|
|
8
8
|
// found in the LICENSE file.
|
|
9
9
|
|
|
10
|
+
#include "absl/cleanup/cleanup.h"
|
|
10
11
|
#include "src/http3server.h"
|
|
11
12
|
#include "src/http3dispatcher.h"
|
|
12
13
|
#include "src/http3wtsessionvisitor.h"
|
|
@@ -39,7 +40,8 @@ namespace quic
|
|
|
39
40
|
std::move(proof_source),
|
|
40
41
|
KeyExchangeSource::Default()),
|
|
41
42
|
expected_server_connection_id_length_(kQuicDefaultConnectionIdLength),
|
|
42
|
-
js_(nullptr)
|
|
43
|
+
js_(nullptr),
|
|
44
|
+
connection_id_generator_(expected_server_connection_id_length_)
|
|
43
45
|
{
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -59,6 +61,8 @@ namespace quic
|
|
|
59
61
|
QUIC_LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
|
|
60
62
|
return false;
|
|
61
63
|
}
|
|
64
|
+
auto closer = absl::MakeCleanup([this]
|
|
65
|
+
{ { QuicUdpSocketApi api;api.Destroy(fd_); } });
|
|
62
66
|
|
|
63
67
|
overflow_supported_ = socket_api.EnableDroppedPacketCount(fd_);
|
|
64
68
|
socket_api.EnableReceiveTimestamp(fd_);
|
|
@@ -83,12 +87,16 @@ namespace quic
|
|
|
83
87
|
|
|
84
88
|
const int kEpollFlags = kSocketEventReadable | kSocketEventWritable;
|
|
85
89
|
|
|
86
|
-
eventloop_->getQuicEventLoop()->RegisterSocket(fd_, kEpollFlags, this)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
if (eventloop_->getQuicEventLoop()->RegisterSocket(fd_, kEpollFlags, this))
|
|
91
|
+
{
|
|
92
|
+
// eventloop_->SetNonblocking(fd_); // eventuelly should be part of register socket.
|
|
93
|
+
dispatcher_.reset(CreateQuicDispatcher());
|
|
94
|
+
dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(fd_));
|
|
95
|
+
std::move(closer).Cancel();
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
90
98
|
|
|
91
|
-
return
|
|
99
|
+
return false;
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
bool Http3Server::stopServerInt()
|
|
@@ -119,7 +127,7 @@ namespace quic
|
|
|
119
127
|
new QuicSimpleCryptoServerStreamHelper()),
|
|
120
128
|
std::unique_ptr<QuicAlarmFactory>(
|
|
121
129
|
eventloop_->getQuicEventLoop()->CreateAlarmFactory()),
|
|
122
|
-
&http3_server_backend_, expected_server_connection_id_length_);
|
|
130
|
+
&http3_server_backend_, expected_server_connection_id_length_, connection_id_generator_);
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
Http3ServerJS::Http3ServerJS(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Http3ServerJS>(info)
|
|
@@ -149,7 +157,7 @@ namespace quic
|
|
|
149
157
|
else
|
|
150
158
|
{
|
|
151
159
|
Napi::Error::New(Env(), "No secret set for Http3Server").ThrowAsJavaScriptException();
|
|
152
|
-
return
|
|
160
|
+
return;
|
|
153
161
|
}
|
|
154
162
|
if (lobj.Has("host") && !(lobj).Get("host").IsEmpty())
|
|
155
163
|
{
|
|
@@ -183,6 +191,20 @@ namespace quic
|
|
|
183
191
|
sconfig.SetMaxBidirectionalStreamsToSend(maxconn);
|
|
184
192
|
sconfig.SetMaxUnidirectionalStreamsToSend(maxconn);
|
|
185
193
|
}
|
|
194
|
+
|
|
195
|
+
if (lobj.Has("initialStreamFlowControlWindow") && !(lobj).Get("initialStreamFlowControlWindow").IsEmpty())
|
|
196
|
+
{
|
|
197
|
+
Napi::Value initialStreamFlowControlWindowValue = (lobj).Get("initialStreamFlowControlWindow");
|
|
198
|
+
int initialStreamFlowControlWindow = initialStreamFlowControlWindowValue.As<Napi::Number>().Int32Value();
|
|
199
|
+
sconfig.SetInitialStreamFlowControlWindowToSend(initialStreamFlowControlWindow);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (lobj.Has("initialSessionFlowControlWindow") && !(lobj).Get("initialSessionFlowControlWindow").IsEmpty())
|
|
203
|
+
{
|
|
204
|
+
Napi::Value initialSessionFlowControlWindowValue = (lobj).Get("initialSessionFlowControlWindow");
|
|
205
|
+
int initialSessionFlowControlWindow = initialSessionFlowControlWindowValue.As<Napi::Number>().Int32Value();
|
|
206
|
+
sconfig.SetInitialSessionFlowControlWindowToSend(initialSessionFlowControlWindow);
|
|
207
|
+
}
|
|
186
208
|
}
|
|
187
209
|
// Callback *callback, int port, std::unique_ptr<ProofSource> proof_source, const char *secret
|
|
188
210
|
|
|
@@ -202,7 +224,7 @@ namespace quic
|
|
|
202
224
|
if (proofsource == nullptr)
|
|
203
225
|
{
|
|
204
226
|
Napi::Error::New(Env(), "LoadPemFromStream cert failed for Http3Server").ThrowAsJavaScriptException();
|
|
205
|
-
return
|
|
227
|
+
return;
|
|
206
228
|
}
|
|
207
229
|
Http3EventLoop *eventloop = nullptr;
|
|
208
230
|
if (!info[1].IsUndefined())
|
|
@@ -213,7 +235,7 @@ namespace quic
|
|
|
213
235
|
else
|
|
214
236
|
{
|
|
215
237
|
Napi::Error::New(Env(), "No eventloop arguments passed to Http3Server").ThrowAsJavaScriptException();
|
|
216
|
-
return
|
|
238
|
+
return;
|
|
217
239
|
}
|
|
218
240
|
|
|
219
241
|
server_ = std::make_unique<Http3Server>(eventloop, host, port, std::move(proofsource), secret.c_str(), sconfig);
|
|
@@ -270,6 +292,21 @@ namespace quic
|
|
|
270
292
|
freeaddrinfo(servinfo);
|
|
271
293
|
}
|
|
272
294
|
|
|
295
|
+
const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
|
|
296
|
+
const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
|
|
297
|
+
if (config_.GetInitialStreamFlowControlWindowToSend() ==
|
|
298
|
+
kDefaultFlowControlSendWindow)
|
|
299
|
+
{
|
|
300
|
+
config_.SetInitialStreamFlowControlWindowToSend(
|
|
301
|
+
kInitialStreamFlowControlWindow);
|
|
302
|
+
}
|
|
303
|
+
if (config_.GetInitialSessionFlowControlWindowToSend() ==
|
|
304
|
+
kDefaultFlowControlSendWindow)
|
|
305
|
+
{
|
|
306
|
+
config_.SetInitialSessionFlowControlWindowToSend(
|
|
307
|
+
kInitialSessionFlowControlWindow);
|
|
308
|
+
}
|
|
309
|
+
|
|
273
310
|
QuicSocketAddress address(ipaddress, port_);
|
|
274
311
|
if (!CreateUDPSocketAndListen(address))
|
|
275
312
|
return false; // move to this class
|
package/src/http3server.h
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
#include "src/http3serverbackend.h"
|
|
19
19
|
#include "src/http3eventloop.h"
|
|
20
20
|
#include "quiche/quic/core/crypto/quic_crypto_server_config.h"
|
|
21
|
+
#include "quiche/quic/core/deterministic_connection_id_generator.h"
|
|
21
22
|
#include "quiche/quic/core/quic_udp_socket.h"
|
|
22
23
|
#include "quiche/quic/core/quic_dispatcher.h"
|
|
23
24
|
#include "quiche/quic/core/quic_packet_reader.h"
|
|
@@ -61,7 +62,6 @@ namespace quic
|
|
|
61
62
|
exports.Set("Http3WebTransportServer", tplsrv);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
|
|
65
65
|
void doUnref() override
|
|
66
66
|
{
|
|
67
67
|
Unref();
|
|
@@ -127,6 +127,7 @@ namespace quic
|
|
|
127
127
|
QuicDispatcher *CreateQuicDispatcher();
|
|
128
128
|
|
|
129
129
|
Http3EventLoop *eventloop_;
|
|
130
|
+
DeterministicConnectionIdGenerator connection_id_generator_;
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
}
|
package/test/testsuite.js
CHANGED
|
@@ -123,7 +123,7 @@ export async function echoTestsConnection(transport) {
|
|
|
123
123
|
refArray1.set(data2, data1.length)
|
|
124
124
|
|
|
125
125
|
const resultArray1 = new Uint8Array(i)
|
|
126
|
-
console.log(
|
|
126
|
+
console.log('TEST 1: start')
|
|
127
127
|
|
|
128
128
|
while (true && i > 0) {
|
|
129
129
|
const { done, value } = await reader.read()
|
|
@@ -155,8 +155,8 @@ export async function echoTestsConnection(transport) {
|
|
|
155
155
|
testArraysEqual(refArray1, resultArray1)
|
|
156
156
|
|
|
157
157
|
console.log('webtransport sending bidistream success')
|
|
158
|
-
console.log(
|
|
159
|
-
console.log(
|
|
158
|
+
console.log('TEST 1: finish')
|
|
159
|
+
console.log('TEST 2: start')
|
|
160
160
|
const bidiReader = transport.incomingBidirectionalStreams.getReader()
|
|
161
161
|
const incombidi = await bidiReader.read()
|
|
162
162
|
if (incombidi.value) {
|
|
@@ -204,9 +204,9 @@ export async function echoTestsConnection(transport) {
|
|
|
204
204
|
}
|
|
205
205
|
testArraysEqual(refArray2, resultArray2)
|
|
206
206
|
}
|
|
207
|
-
console.log(
|
|
207
|
+
console.log('TEST 2: finish')
|
|
208
208
|
|
|
209
|
-
console.log(
|
|
209
|
+
console.log('TEST 3: start')
|
|
210
210
|
console.log('now unidirectional tests')
|
|
211
211
|
const unidioutstream = await transport.createUnidirectionalStream()
|
|
212
212
|
const unidiwrite = unidioutstream.getWriter()
|
|
@@ -262,8 +262,8 @@ export async function echoTestsConnection(transport) {
|
|
|
262
262
|
throw new Error('incoming unidi stream test failed')
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
|
-
console.log(
|
|
266
|
-
console.log(
|
|
265
|
+
console.log('TEST 3: finish')
|
|
266
|
+
console.log('TEST 4: start')
|
|
267
267
|
console.log('finally test datagrams')
|
|
268
268
|
const datawrite = await transport.datagrams.writable.getWriter()
|
|
269
269
|
const data7 = new Uint8Array([83, 84, 85])
|
|
@@ -300,6 +300,6 @@ export async function echoTestsConnection(transport) {
|
|
|
300
300
|
throw new Error('datagram stream test failed')
|
|
301
301
|
}
|
|
302
302
|
console.log('test datagrams finished')
|
|
303
|
-
console.log(
|
|
303
|
+
console.log('TEST 4: finish')
|
|
304
304
|
console.log('start close stream tests')
|
|
305
305
|
}
|