lokinet/llarp/service/sendcontext.cpp

128 lines
3.2 KiB
C++
Raw Normal View History

2019-04-19 16:02:32 +00:00
#include <service/sendcontext.hpp>
#include <messages/path_transfer.hpp>
#include <service/endpoint.hpp>
#include <router/abstractrouter.hpp>
#include <util/logic.hpp>
2019-04-19 16:02:32 +00:00
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, path::Path_ptr path)
2019-04-19 16:02:32 +00:00
{
auto transfer = std::make_shared< const routing::PathTransferMessage >(
msg, remoteIntro.pathID);
2019-04-25 17:15:56 +00:00
{
util::Lock lock(&m_SendQueueMutex);
m_SendQueue.emplace_back(transfer, path);
}
return true;
}
void
SendContext::FlushUpstream()
2019-04-25 17:15:56 +00:00
{
auto r = m_Endpoint->Router();
util::Lock lock(&m_SendQueueMutex);
for(const auto& item : m_SendQueue)
{
if(item.second->SendRoutingMessage(*item.first, r))
2019-04-19 16:02:32 +00:00
{
2019-04-25 17:15:56 +00:00
lastGoodSend = r->Now();
2019-04-19 16:02:32 +00:00
}
else
LogError("Failed to send frame on path");
2019-04-25 17:15:56 +00:00
}
m_SendQueue.clear();
2019-04-19 16:02:32 +00:00
}
/// send on an established convo tag
void
SendContext::EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t)
{
SharedSecret shared;
ProtocolFrame f;
2019-04-19 16:02:32 +00:00
f.N.Randomize();
f.T = currentConvoTag;
2019-06-06 10:52:27 +00:00
f.S = ++sequenceNo;
2019-04-19 16:02:32 +00:00
auto now = m_Endpoint->Now();
if(remoteIntro.ExpiresSoon(now))
{
// shift intro
if(MarkCurrentIntroBad(now))
{
LogInfo("intro shifted");
2019-04-19 16:02:32 +00:00
}
}
auto path = m_PathSet->GetNewestPathByRouter(remoteIntro.router);
if(!path)
{
LogError("cannot encrypt and send: no path for intro ", remoteIntro);
2019-04-19 16:02:32 +00:00
return;
}
if(!m_DataHandler->GetCachedSessionKeyFor(f.T, shared))
2019-04-19 16:02:32 +00:00
{
LogError("No cached session key");
2019-04-19 16:02:32 +00:00
return;
}
2019-05-22 16:20:50 +00:00
ProtocolMessage m;
m_DataHandler->PutIntroFor(f.T, remoteIntro);
m_DataHandler->PutReplyIntroFor(f.T, path->intro);
m.proto = t;
2019-06-06 10:52:27 +00:00
m.seqno = m_Endpoint->GetSeqNoForConvo(f.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(m, shared, m_Endpoint->GetIdentity()))
{
LogError("failed to sign");
return;
2019-05-22 16:20:50 +00:00
}
Send(f, path);
2019-04-19 16:02:32 +00:00
}
void
SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data,
ProtocolType protocol)
{
auto now = m_Endpoint->Now();
if(remoteIntro.ExpiresSoon(now))
{
2019-05-17 11:41:11 +00:00
if(!ShiftIntroduction())
2019-04-19 16:02:32 +00:00
{
LogWarn("no good path yet, your message may drop");
2019-04-19 16:02:32 +00:00
}
}
if(lastGoodSend)
2019-04-19 16:02:32 +00:00
{
EncryptAndSendTo(data, protocol);
}
else
{
AsyncGenIntro(data, protocol);
}
}
} // namespace service
} // namespace llarp