track path data usage and don't kill paths when under heavy use

pull/16/head
Jeff Becker 6 years ago
parent d784d1de82
commit 17d2aa1df1
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -326,6 +326,9 @@ namespace llarp
RouterID
Endpoint() const;
bool
IsEndpoint(const RouterID& router, const PathID_t& path) const;
const PathID_t&
RXID() const;
@ -343,6 +346,7 @@ namespace llarp
DataHandlerFunc m_DataHandler;
DropHandlerFunc m_DropHandler;
CheckForDeadFunc m_CheckForDead;
llarp_time_t m_LastRecvMessage = 0;
llarp_time_t m_LastLatencyTestTime = 0;
uint64_t m_LastLatencyTestID = 0;
};

@ -63,7 +63,9 @@ namespace llarp
bool
operator<(const Introduction& other) const
{
return expiresAt < other.expiresAt || pathID < other.pathID;
return expiresAt < other.expiresAt || pathID < other.pathID
|| router < other.router || version < other.version
|| latency < other.latency;
}
bool
@ -79,6 +81,15 @@ namespace llarp
{
return !(*this == other);
}
struct Hash
{
size_t
operator()(const Introduction& i) const
{
return *i.router.data_l() ^ *i.pathID.data_l();
}
};
};
} // namespace service
} // namespace llarp

@ -194,8 +194,11 @@ namespace llarp
ShiftIntroduction(){};
virtual void
UpdateIntroSet(){};
virtual void
MarkCurrentIntroBad(){};
virtual bool
MarkCurrentIntroBad(llarp_time_t now)
{
return true;
};
private:
void
@ -227,14 +230,17 @@ namespace llarp
ShiftIntroduction();
/// mark the current remote intro as bad
void
MarkCurrentIntroBad();
bool
MarkCurrentIntroBad(llarp_time_t now);
/// tick internal state
/// return true to remove otherwise don't remove
bool
Tick(llarp_time_t now);
bool
CheckPathIsDead(path::Path* p, llarp_time_t dlt);
void
AsyncGenIntro(llarp_buffer_t payload, ProtocolType t);
@ -264,7 +270,8 @@ namespace llarp
uint64_t m_UpdateIntrosetTX = 0;
IntroSet currentIntroSet;
std::set< Introduction > m_BadIntros;
std::unordered_map< Introduction, llarp_time_t, Introduction::Hash >
m_BadIntros;
llarp_time_t lastShift = 0;
};

@ -427,7 +427,8 @@ namespace llarp
SendRoutingMessage(&latency, r);
}
// check to see if this path is dead
if(_status == ePathEstablished)
if(_status == ePathEstablished
&& (now > m_LastRecvMessage && now - m_LastRecvMessage > 1000))
{
if(m_CheckForDead)
{
@ -590,7 +591,13 @@ namespace llarp
Path::HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* frame)
{
if(m_DataHandler)
return m_DataHandler(this, frame);
{
if(m_DataHandler(this, frame))
{
m_LastRecvMessage = llarp_time_now_ms();
return true;
}
}
return false;
}

@ -722,8 +722,11 @@ namespace llarp
{
llarp::LogWarn(Name(), " message ", seq, " dropped by endpoint ",
p->Endpoint(), " via ", dst);
MarkCurrentIntroBad();
UpdateIntroSet();
if(MarkCurrentIntroBad(llarp_time_now_ms()))
llarp::LogInfo(Name(), " switched intros to ", remoteIntro.router,
" via ", remoteIntro.pathID);
else
UpdateIntroSet();
}
return true;
}
@ -778,7 +781,7 @@ namespace llarp
}
bool
Endpoint::CheckPathIsDead(path::Path*, llarp_time_t latency)
Endpoint::CheckPathIsDead(path::Path* p, llarp_time_t latency)
{
if(latency >= m_MinPathLatency)
{
@ -985,32 +988,35 @@ namespace llarp
return true;
} // namespace service
void
Endpoint::OutboundContext::MarkCurrentIntroBad()
bool
Endpoint::OutboundContext::MarkCurrentIntroBad(llarp_time_t now)
{
auto now = llarp_time_now_ms();
bool shifted = false;
bool success = false;
// insert bad intro
m_BadIntros.insert(remoteIntro);
m_BadIntros.insert(std::make_pair(remoteIntro, now));
// shift off current intro
for(const auto& intro : currentIntroSet.I)
{
if(m_BadIntros.count(intro) == 0 && !intro.ExpiresSoon(now))
if(m_BadIntros.find(intro) == m_BadIntros.end()
&& !intro.ExpiresSoon(now))
{
shifted = intro.router != remoteIntro.router;
remoteIntro = intro;
success = true;
break;
}
}
// don't rebuild paths rapidly
if(now - lastShift < MIN_SHIFT_INTERVAL)
return;
return success;
// rebuild path if shifted
if(shifted)
{
lastShift = now;
ManualRebuild(1);
}
return success;
}
void
@ -1025,7 +1031,7 @@ namespace llarp
m_Endpoint->EnsureRouterIsKnown(intro.router);
if(intro.ExpiresSoon(now))
continue;
if(m_BadIntros.count(intro) == 0 && remoteIntro != intro)
if(m_BadIntros.find(intro) == m_BadIntros.end() && remoteIntro != intro)
{
shifted = intro.router != remoteIntro.router;
remoteIntro = intro;
@ -1172,7 +1178,10 @@ namespace llarp
auto now = llarp_time_now_ms();
if(remoteIntro.ExpiresSoon(now))
{
MarkCurrentIntroBad();
if(!MarkCurrentIntroBad(now))
{
llarp::LogWarn("no good path yet, your message may drop");
}
}
routing::PathTransferMessage transfer(msg, remoteIntro.pathID);
if(!path->SendRoutingMessage(&transfer, m_Endpoint->Router()))
@ -1220,13 +1229,17 @@ namespace llarp
{
if(remoteIntro.ExpiresSoon(now))
{
MarkCurrentIntroBad();
if(!MarkCurrentIntroBad(now))
{
// TODO: log?
}
}
m_Endpoint->EnsureRouterIsKnown(remoteIntro.router);
if(!remoteIntro.router.IsZero())
m_Endpoint->EnsureRouterIsKnown(remoteIntro.router);
auto itr = m_BadIntros.begin();
while(itr != m_BadIntros.end())
{
if(itr->IsExpired(now))
if(now - itr->second > DEFAULT_PATH_LIFETIME)
itr = m_BadIntros.erase(itr);
else
++itr;
@ -1294,7 +1307,11 @@ namespace llarp
if(remoteIntro.ExpiresSoon(now))
{
// shift intro
MarkCurrentIntroBad();
if(!MarkCurrentIntroBad(now))
{
llarp::LogError("dropping message, no path after shifting intros");
return;
}
}
auto path = m_PathSet->GetNewestPathByRouter(remoteIntro.router);

Loading…
Cancel
Save