mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-19 09:25:28 +00:00
139 lines
3.8 KiB
C++
139 lines
3.8 KiB
C++
#include <service/sendcontext.hpp>
|
|
|
|
#include <messages/path_transfer.hpp>
|
|
#include <service/endpoint.hpp>
|
|
#include <router/abstractrouter.hpp>
|
|
|
|
namespace llarp
|
|
{
|
|
namespace service
|
|
{
|
|
SendContext::SendContext(const ServiceInfo& ident,
|
|
const Introduction& intro, path::PathSet* send,
|
|
Endpoint* ep)
|
|
: remoteIdent(ident)
|
|
, remoteIntro(intro)
|
|
, m_PathSet(send)
|
|
, m_DataHandler(ep)
|
|
, m_Endpoint(ep)
|
|
{
|
|
createdAt = ep->Now();
|
|
currentConvoTag.Zero();
|
|
}
|
|
|
|
bool
|
|
SendContext::Send(const ProtocolFrame& msg)
|
|
{
|
|
auto path = m_PathSet->GetByEndpointWithID(remoteIntro.router, msg.F);
|
|
if(path)
|
|
{
|
|
const routing::PathTransferMessage transfer(msg, remoteIntro.pathID);
|
|
if(path->SendRoutingMessage(transfer, m_Endpoint->Router()))
|
|
{
|
|
llarp::LogInfo("sent intro to ", remoteIntro.pathID, " on ",
|
|
remoteIntro.router, " seqno=", sequenceNo);
|
|
lastGoodSend = m_Endpoint->Now();
|
|
++sequenceNo;
|
|
return true;
|
|
}
|
|
else
|
|
llarp::LogError("Failed to send frame on path");
|
|
}
|
|
else
|
|
llarp::LogError("cannot send because we have no path to ",
|
|
remoteIntro.router);
|
|
return false;
|
|
}
|
|
|
|
/// send on an established convo tag
|
|
void
|
|
SendContext::EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t)
|
|
{
|
|
auto crypto = m_Endpoint->Router()->crypto();
|
|
SharedSecret shared;
|
|
routing::PathTransferMessage msg;
|
|
ProtocolFrame& f = msg.T;
|
|
f.N.Randomize();
|
|
f.T = currentConvoTag;
|
|
f.S = m_Endpoint->GetSeqNoForConvo(f.T);
|
|
|
|
auto now = m_Endpoint->Now();
|
|
if(remoteIntro.ExpiresSoon(now))
|
|
{
|
|
// shift intro
|
|
if(MarkCurrentIntroBad(now))
|
|
{
|
|
llarp::LogInfo("intro shifted");
|
|
}
|
|
}
|
|
auto path = m_PathSet->GetNewestPathByRouter(remoteIntro.router);
|
|
if(!path)
|
|
{
|
|
llarp::LogError("cannot encrypt and send: no path for intro ",
|
|
remoteIntro);
|
|
return;
|
|
}
|
|
|
|
if(m_DataHandler->GetCachedSessionKeyFor(f.T, shared))
|
|
{
|
|
ProtocolMessage m;
|
|
m_DataHandler->PutIntroFor(f.T, remoteIntro);
|
|
m_DataHandler->PutReplyIntroFor(f.T, path->intro);
|
|
m.proto = t;
|
|
m.introReply = path->intro;
|
|
f.F = m.introReply.pathID;
|
|
m.sender = m_Endpoint->GetIdentity().pub;
|
|
m.tag = f.T;
|
|
m.PutBuffer(payload);
|
|
if(!f.EncryptAndSign(crypto, m, shared, m_Endpoint->GetIdentity()))
|
|
{
|
|
llarp::LogError("failed to sign");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
llarp::LogError("No cached session key");
|
|
return;
|
|
}
|
|
|
|
msg.P = remoteIntro.pathID;
|
|
msg.Y.Randomize();
|
|
if(path->SendRoutingMessage(msg, m_Endpoint->Router()))
|
|
{
|
|
llarp::LogDebug("sent message via ", remoteIntro.pathID, " on ",
|
|
remoteIntro.router);
|
|
++sequenceNo;
|
|
lastGoodSend = now;
|
|
}
|
|
else
|
|
{
|
|
llarp::LogWarn("Failed to send routing message for data");
|
|
}
|
|
}
|
|
|
|
void
|
|
SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data,
|
|
ProtocolType protocol)
|
|
{
|
|
auto now = m_Endpoint->Now();
|
|
if(remoteIntro.ExpiresSoon(now))
|
|
{
|
|
if(!MarkCurrentIntroBad(now))
|
|
{
|
|
llarp::LogWarn("no good path yet, your message may drop");
|
|
}
|
|
}
|
|
if(sequenceNo)
|
|
{
|
|
EncryptAndSendTo(data, protocol);
|
|
}
|
|
else
|
|
{
|
|
AsyncGenIntro(data, protocol);
|
|
}
|
|
}
|
|
} // namespace service
|
|
|
|
} // namespace llarp
|