diff --git a/docs/proto_v0.txt b/docs/proto_v0.txt index 114f0b120..fdd47e405 100644 --- a/docs/proto_v0.txt +++ b/docs/proto_v0.txt @@ -656,6 +656,7 @@ start a new session A: "H", C: "<1048 bytes ciphertext block>", D: "", + F: "<16 bytes source path_id>", N: "<32 bytes nonce for key exchange>", V: 0, Z: "<64 bytes signature of entire message using sender's signing key>" @@ -691,6 +692,8 @@ C, K = PQKE_A(I_B.k) N = RAND(32) D = SE(X, K, N) +path = PickSendPath() + M = { A: "T", P: I_B.P, @@ -699,6 +702,7 @@ M = { A: "H", C: C, D: D, + F: path.lastHop.txID, N: N, V: 0, Z: "\x00" * 64 @@ -711,6 +715,8 @@ Z = S(A_sk, BE(M)) alice transmits a TDFM to router with public key I_B.K via her path that ends with router with public key I_B.k +path = PickSendPath() + { A: "T", P: I_B.P, @@ -719,6 +725,7 @@ with router with public key I_B.k A: "H", C: C, D: D, + F: path.lastHop.txID, N: N, V: 0, Z: Z @@ -744,6 +751,7 @@ transfer data on a session previously made { A: "H", D: "", + F: "<16 bytes path id of soruce>", N: "<32 bytes nonce for symettric cipher>", T: "<16 bytes converstation tag>", V: 0, diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index cf00ca82f..f3d7931a5 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -172,26 +172,24 @@ namespace llarp IHopHandler* PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id) { - auto own = MapGet( - m_OurPaths, id, - [](__attribute__((unused)) const PathSet* s) -> bool { - // TODO: is this right? - return true; - }, - [remote, id](PathSet* p) -> IHopHandler* { - return p->GetByUpstream(remote, id); - }); + auto own = MapGet(m_OurPaths, id, + [](__attribute__((unused)) const PathSet* s) -> bool { + // TODO: is this right? + return true; + }, + [remote, id](PathSet* p) -> IHopHandler* { + return p->GetByUpstream(remote, id); + }); if(own) return own; - return MapGet( - m_TransitPaths, id, - [remote](const std::shared_ptr< TransitHop >& hop) -> bool { - return hop->info.upstream == remote; - }, - [](const std::shared_ptr< TransitHop >& h) -> IHopHandler* { - return h.get(); - }); + return MapGet(m_TransitPaths, id, + [remote](const std::shared_ptr< TransitHop >& hop) -> bool { + return hop->info.upstream == remote; + }, + [](const std::shared_ptr< TransitHop >& h) -> IHopHandler* { + return h.get(); + }); } bool @@ -208,14 +206,13 @@ namespace llarp IHopHandler* PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) { - return MapGet( - m_TransitPaths, id, - [remote](const std::shared_ptr< TransitHop >& hop) -> bool { - return hop->info.downstream == remote; - }, - [](const std::shared_ptr< TransitHop >& h) -> IHopHandler* { - return h.get(); - }); + return MapGet(m_TransitPaths, id, + [remote](const std::shared_ptr< TransitHop >& hop) -> bool { + return hop->info.downstream == remote; + }, + [](const std::shared_ptr< TransitHop >& h) -> IHopHandler* { + return h.get(); + }); } PathSet* @@ -440,6 +437,13 @@ namespace llarp return intro.latency > 0 && _status == ePathEstablished; } + bool + Path::IsEndpoint(const RouterID& r, const PathID_t& id) const + { + return hops[hops.size() - 1].rc.pubkey == r + && hops[hops.size() - 1].txID == id; + } + RouterID Path::Upstream() const { diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index a186c9652..469899eb1 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -156,6 +156,22 @@ namespace llarp return chosen; } + Path* + PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const + { + Lock_t l(&m_PathsMutex); + auto itr = m_Paths.begin(); + while(itr != m_Paths.end()) + { + if(itr->second->IsEndpoint(ep, id)) + { + return itr->second; + } + ++itr; + } + return nullptr; + } + Path* PathSet::GetPathByID(PathID_t id) const { diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 933840baf..390dce0a2 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -176,6 +176,9 @@ namespace llarp Path* GetPathByID(PathID_t id) const; + Path* + GetByEndpointWithID(RouterID router, PathID_t id) const; + bool GetCurrentIntroductionsWithFilter( std::set< service::Introduction >& intros, diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 7b624d3ef..d89520e78 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -998,6 +998,7 @@ namespace llarp if(!frame->Verify(Crypto(), si)) return false; // remove convotag it doesn't exist + LogWarn("remove convotag T=", frame->T); RemoveConvoTag(frame->T); return true; } @@ -1027,6 +1028,7 @@ namespace llarp , m_Endpoint(ep) { createdAt = ep->Now(); + currentConvoTag.Zero(); } void @@ -1583,6 +1585,7 @@ namespace llarp self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey); self->handler->PutIntroFor(self->msg.tag, self->remoteIntro); self->handler->PutSenderFor(self->msg.tag, self->remote); + self->handler->PutReplyIntroFor(self->msg.tag, self->msg.introReply); self->hook(self->frame); delete self; } @@ -1669,24 +1672,22 @@ namespace llarp ex->msg.PutBuffer(payload); ex->msg.introReply = path->intro; - m_DataHandler->PutReplyIntroFor(currentConvoTag, path->intro); + ex->frame.F = ex->msg.introReply.pathID; llarp_threadpool_queue_job(m_Endpoint->Worker(), {ex, &AsyncKeyExchange::Encrypt}); } bool - Endpoint::SendContext::Send(ProtocolFrame& msg) + Endpoint::SendContext::Send(const ProtocolFrame& msg) { - auto path = m_PathSet->GetPathByRouter(remoteIntro.router); - if(path == nullptr) - path = m_Endpoint->GetPathByRouter(remoteIntro.router); + auto path = m_PathSet->GetByEndpointWithID(remoteIntro.router, msg.F); if(path) { - routing::PathTransferMessage transfer(msg, remoteIntro.pathID); + const routing::PathTransferMessage transfer(msg, remoteIntro.pathID); if(path->SendRoutingMessage(&transfer, m_Endpoint->Router())) { - llarp::LogDebug("sent data to ", remoteIntro.pathID, " on ", - remoteIntro.router); + llarp::LogInfo("sent intro to ", remoteIntro.pathID, " on ", + remoteIntro.router, " seqno=", sequenceNo); lastGoodSend = m_Endpoint->Now(); ++sequenceNo; return true; @@ -1798,16 +1799,23 @@ namespace llarp ++itr; } // send control message if we look too quiet - if(now - lastGoodSend > (sendTimeout / 2)) + if(lastGoodSend) { - if(!GetNewestPathByRouter(remoteIntro.router)) + if(now - lastGoodSend > (sendTimeout / 2)) { - BuildOneAlignedTo(remoteIntro.router); + if(!GetNewestPathByRouter(remoteIntro.router)) + { + BuildOneAlignedTo(remoteIntro.router); + } + Encrypted< 64 > tmp; + tmp.Randomize(); + llarp_buffer_t buf(tmp.data(), tmp.size()); + AsyncEncryptAndSendTo(buf, eProtocolControl); + SharedSecret k; + if(currentConvoTag.IsZero()) + return false; + return !m_DataHandler->HasConvoTag(currentConvoTag); } - Encrypted< 64 > tmp; - tmp.Randomize(); - llarp_buffer_t buf(tmp.data(), tmp.size()); - AsyncEncryptAndSendTo(buf, eProtocolControl); } // if we are dead return true so we are removed return lastGoodSend @@ -1815,6 +1823,12 @@ namespace llarp : (now >= createdAt && now - createdAt > connectTimeout); } + bool + Endpoint::HasConvoTag(const ConvoTag& t) const + { + return m_Sessions.find(t) != m_Sessions.end(); + } + bool Endpoint::OutboundContext::SelectHop(llarp_nodedb* db, const RouterContact& prev, diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index c2574c1f3..5261e5553 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -222,7 +222,7 @@ namespace llarp /// send a fully encrypted hidden service frame /// via a path on our pathset with path id p bool - Send(ProtocolFrame& f); + Send(const ProtocolFrame& f); llarp::SharedSecret sharedKey; ServiceInfo remoteIdent; @@ -261,6 +261,9 @@ namespace llarp static void HandlePathDead(void*); + bool + HasConvoTag(const ConvoTag& t) const override; + bool ShouldBuildMore(llarp_time_t now) const override; diff --git a/llarp/service/handler.hpp b/llarp/service/handler.hpp index e7503f1a7..5b2f9fc74 100644 --- a/llarp/service/handler.hpp +++ b/llarp/service/handler.hpp @@ -28,6 +28,9 @@ namespace llarp virtual void RemoveConvoTag(const ConvoTag& remote) = 0; + virtual bool + HasConvoTag(const ConvoTag& remote) const = 0; + virtual void PutSenderFor(const ConvoTag& remote, const ServiceInfo& si) = 0;