@@ -92,19 +92,18 @@ STAT_STRUCT(Endpoint, ENDPOINT)
9292TokenBucket::TokenBucket (double rate, double burst)
9393 : rate(rate), burst(burst), tokens(burst), last_ts(uv_hrtime()) {}
9494
95- void TokenBucket::InitOnce (double r, double b) {
95+ void TokenBucket::InitOnce (double r, double b, uint64_t now ) {
9696 if (last_ts == 0 ) {
9797 rate = r;
9898 burst = b;
9999 tokens = b;
100- last_ts = uv_hrtime () ;
100+ last_ts = now ;
101101 }
102102}
103103
104104// Try to consume one token. Refills based on elapsed time, then
105105// attempts to consume. Returns true if the request is allowed.
106- bool TokenBucket::consume () {
107- uint64_t now = uv_hrtime ();
106+ bool TokenBucket::consume (uint64_t now) {
108107 double elapsed = static_cast <double >(now - last_ts) / 1e9 ; // seconds
109108 last_ts = now;
110109 tokens = std::min (burst, tokens + elapsed * rate);
@@ -1025,9 +1024,9 @@ void Endpoint::SendBatch(Packet::Ptr* packets, size_t count) {
10251024 }
10261025}
10271026
1028- void Endpoint::SendRetry (const PathDescriptor& options) {
1027+ void Endpoint::SendRetry (const PathDescriptor& options, uint64_t now ) {
10291028 Debug (this , " Sending retry on path %s" , options);
1030- if (!retry_bucket_.consume ()) {
1029+ if (!retry_bucket_.consume (now )) {
10311030 Debug (this , " Retry rate limit exceeded (global)" );
10321031 STAT_INCREMENT (Stats, retry_rate_limited);
10331032 return ;
@@ -1041,9 +1040,10 @@ void Endpoint::SendRetry(const PathDescriptor& options) {
10411040 }
10421041}
10431042
1044- void Endpoint::SendVersionNegotiation (const PathDescriptor& options) {
1043+ void Endpoint::SendVersionNegotiation (const PathDescriptor& options,
1044+ uint64_t now) {
10451045 Debug (this , " Sending version negotiation on path %s" , options);
1046- if (!version_negotiation_bucket_.consume ()) {
1046+ if (!version_negotiation_bucket_.consume (now )) {
10471047 Debug (this , " Version negotiation rate limit exceeded (global)" );
10481048 STAT_INCREMENT (Stats, version_negotiation_rate_limited);
10491049 return ;
@@ -1057,7 +1057,8 @@ void Endpoint::SendVersionNegotiation(const PathDescriptor& options) {
10571057}
10581058
10591059bool Endpoint::SendStatelessReset (const PathDescriptor& options,
1060- size_t source_len) {
1060+ size_t source_len,
1061+ uint64_t now) {
10611062 if (options_.disable_stateless_reset ) [[unlikely]] {
10621063 return false ;
10631064 }
@@ -1066,7 +1067,7 @@ bool Endpoint::SendStatelessReset(const PathDescriptor& options,
10661067 options,
10671068 source_len);
10681069
1069- if (!stateless_reset_bucket_.consume ()) {
1070+ if (!stateless_reset_bucket_.consume (now )) {
10701071 Debug (this , " Stateless reset rate limit exceeded (global)" );
10711072 STAT_INCREMENT (Stats, stateless_reset_rate_limited);
10721073 return false ;
@@ -1086,12 +1087,13 @@ bool Endpoint::SendStatelessReset(const PathDescriptor& options,
10861087}
10871088
10881089void Endpoint::SendImmediateConnectionClose (const PathDescriptor& options,
1089- QuicError reason) {
1090+ QuicError reason,
1091+ uint64_t now) {
10901092 Debug (this ,
10911093 " Sending immediate connection close on path %s with reason %s" ,
10921094 options,
10931095 reason);
1094- if (!immediate_close_bucket_.consume ()) {
1096+ if (!immediate_close_bucket_.consume (now )) {
10951097 Debug (this , " Immediate connection close rate limit exceeded (global)" );
10961098 STAT_INCREMENT (Stats, immediate_close_rate_limited);
10971099 return ;
@@ -1313,6 +1315,8 @@ void Endpoint::CloseGracefully() {
13131315void Endpoint::Receive (const uint8_t * data,
13141316 size_t len,
13151317 const SocketAddress& remote_address) {
1318+ const uint64_t now = uv_hrtime ();
1319+
13161320 const auto receive = [&](Session* session,
13171321 const uint8_t * pkt_data,
13181322 size_t pkt_len,
@@ -1327,7 +1331,12 @@ void Endpoint::Receive(const uint8_t* data,
13271331 // are generated. The deferred flush via BindingData's uv_check
13281332 // callback calls SendPendingData once per dirty session after all
13291333 // packets in the burst have been read.
1330- if (session->ReadPacket (pkt_data, pkt_len, local_address, remote_address)) {
1334+ if (session->ReadPacket (pkt_data,
1335+ pkt_len,
1336+ local_address,
1337+ remote_address,
1338+ PacketInfo (),
1339+ now)) {
13311340 STAT_INCREMENT_N (Stats, bytes_received, pkt_len);
13321341 STAT_INCREMENT (Stats, packets_received);
13331342 }
@@ -1349,10 +1358,10 @@ void Endpoint::Receive(const uint8_t* data,
13491358
13501359 // Per-host session creation rate limit. The bucket is initialized
13511360 // on first access with the configured rate/burst from options.
1352- auto info = addr_validation_lru_.Upsert (config.remote_address );
1353- info->session_creation_bucket .InitOnce (options_. session_creation_rate ,
1354- options_.session_creation_burst );
1355- if (!info->session_creation_bucket .consume ()) {
1361+ auto info = addr_validation_lru_.Upsert (config.remote_address , now );
1362+ info->session_creation_bucket .InitOnce (
1363+ options_. session_creation_rate , options_.session_creation_burst , now );
1364+ if (!info->session_creation_bucket .consume (now )) {
13561365 Debug (this ,
13571366 " Session creation rate limit exceeded for %s" ,
13581367 config.remote_address );
@@ -1451,7 +1460,8 @@ void Endpoint::Receive(const uint8_t* data,
14511460 if (state_->busy ) STAT_INCREMENT (Stats, server_busy_count);
14521461 SendImmediateConnectionClose (
14531462 PathDescriptor{version, dcid, scid, local_address, remote_address},
1454- QuicError::ForTransport (NGTCP2_CONNECTION_REFUSED ));
1463+ QuicError::ForTransport (NGTCP2_CONNECTION_REFUSED ),
1464+ now);
14551465 // The packet was successfully processed, even if we did refuse the
14561466 // connection.
14571467 STAT_INCREMENT (Stats, packets_received);
@@ -1525,7 +1535,8 @@ void Endpoint::Receive(const uint8_t* data,
15251535 Debug (this , " Retry token from %s is invalid." , remote_address);
15261536 SendImmediateConnectionClose (
15271537 PathDescriptor{version, scid, dcid, local_address, remote_address},
1528- QuicError::ForTransport (NGTCP2_CONNECTION_REFUSED ));
1538+ QuicError::ForTransport (NGTCP2_CONNECTION_REFUSED ),
1539+ now);
15291540 STAT_INCREMENT (Stats, packets_received);
15301541 return ;
15311542 }
@@ -1541,7 +1552,7 @@ void Endpoint::Receive(const uint8_t* data,
15411552 // Mark the address as validated since the retry round-trip proves
15421553 // reachability.
15431554 Debug (this , " Remote address %s is validated" , remote_address);
1544- addr_validation_lru_.Upsert (remote_address)->validated = true ;
1555+ addr_validation_lru_.Upsert (remote_address, now )->validated = true ;
15451556 }
15461557
15471558 // Step 2: Address validation — decide whether to send a Retry or
@@ -1557,13 +1568,15 @@ void Endpoint::Receive(const uint8_t* data,
15571568 " Initial packet has no token. Sending retry to %s to start "
15581569 " validation" ,
15591570 remote_address);
1560- SendRetry (PathDescriptor{
1561- version,
1562- dcid,
1563- scid,
1564- local_address,
1565- remote_address,
1566- });
1571+ SendRetry (
1572+ PathDescriptor{
1573+ version,
1574+ dcid,
1575+ scid,
1576+ local_address,
1577+ remote_address,
1578+ },
1579+ now);
15671580 STAT_INCREMENT (Stats, packets_received);
15681581 return ;
15691582 }
@@ -1584,13 +1597,15 @@ void Endpoint::Receive(const uint8_t* data,
15841597 Debug (this ,
15851598 " Regular token from %s is invalid." ,
15861599 remote_address);
1587- SendRetry (PathDescriptor{
1588- version,
1589- dcid,
1590- scid,
1591- local_address,
1592- remote_address,
1593- });
1600+ SendRetry (
1601+ PathDescriptor{
1602+ version,
1603+ dcid,
1604+ scid,
1605+ local_address,
1606+ remote_address,
1607+ },
1608+ now);
15941609 STAT_INCREMENT (Stats, packets_received);
15951610 return ;
15961611 }
@@ -1602,20 +1617,22 @@ void Endpoint::Receive(const uint8_t* data,
16021617 Debug (this ,
16031618 " Initial packet from %s has unknown token type" ,
16041619 remote_address);
1605- SendRetry (PathDescriptor{
1606- version,
1607- dcid,
1608- scid,
1609- local_address,
1610- remote_address,
1611- });
1620+ SendRetry (
1621+ PathDescriptor{
1622+ version,
1623+ dcid,
1624+ scid,
1625+ local_address,
1626+ remote_address,
1627+ },
1628+ now);
16121629 STAT_INCREMENT (Stats, packets_received);
16131630 return ;
16141631 }
16151632 }
16161633
16171634 Debug (this , " Remote address %s is validated" , remote_address);
1618- addr_validation_lru_.Upsert (remote_address)->validated = true ;
1635+ addr_validation_lru_.Upsert (remote_address, now )->validated = true ;
16191636 } else if (hd.tokenlen > 0 ) {
16201637 Debug (this ,
16211638 " Ignoring initial packet from %s with unexpected token" ,
@@ -1627,13 +1644,15 @@ void Endpoint::Receive(const uint8_t* data,
16271644 if (options_.validate_address ) {
16281645 Debug (
16291646 this , " Sending retry to %s due to 0RTT packet" , remote_address);
1630- SendRetry (PathDescriptor{
1631- version,
1632- dcid,
1633- scid,
1634- local_address,
1635- remote_address,
1636- });
1647+ SendRetry (
1648+ PathDescriptor{
1649+ version,
1650+ dcid,
1651+ scid,
1652+ local_address,
1653+ remote_address,
1654+ },
1655+ now);
16371656 STAT_INCREMENT (Stats, packets_received);
16381657 return ;
16391658 }
@@ -1742,8 +1761,12 @@ void Endpoint::Receive(const uint8_t* data,
17421761 pversion_cid.version );
17431762 CID dcid (pversion_cid.dcid , pversion_cid.dcidlen );
17441763 CID scid (pversion_cid.scid , pversion_cid.scidlen );
1745- SendVersionNegotiation (PathDescriptor{
1746- pversion_cid.version , dcid, scid, local_address (), remote_address});
1764+ SendVersionNegotiation (PathDescriptor{pversion_cid.version ,
1765+ dcid,
1766+ scid,
1767+ local_address (),
1768+ remote_address},
1769+ now);
17471770 STAT_INCREMENT (Stats, packets_received);
17481771 return ;
17491772 }
@@ -1822,7 +1845,8 @@ void Endpoint::Receive(const uint8_t* data,
18221845 SendStatelessReset (
18231846 PathDescriptor{
18241847 pversion_cid.version , dcid, scid, addr, remote_address},
1825- len);
1848+ len,
1849+ now);
18261850 return ;
18271851 }
18281852
@@ -1884,13 +1908,14 @@ void Endpoint::MemoryInfo(MemoryTracker* tracker) const {
18841908// Endpoint::SocketAddressInfoTraits
18851909
18861910bool Endpoint::SocketAddressInfoTraits::CheckExpired (
1887- const SocketAddress& address, const Type& type) {
1888- return (uv_hrtime () - type.timestamp ) > kSocketAddressInfoTimeout ;
1911+ const SocketAddress& address, const Type& type, uint64_t now ) {
1912+ return (now - type.timestamp ) > kSocketAddressInfoTimeout ;
18891913}
18901914
18911915void Endpoint::SocketAddressInfoTraits::Touch (const SocketAddress& address,
1892- Type* type) {
1893- type->timestamp = uv_hrtime ();
1916+ Type* type,
1917+ uint64_t now) {
1918+ type->timestamp = now;
18941919}
18951920
18961921// ======================================================================================
0 commit comments