2019-08-22 20:53:27 +00:00
|
|
|
#include <iwp/message_buffer.hpp>
|
|
|
|
#include <crypto/crypto.hpp>
|
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
namespace iwp
|
|
|
|
{
|
2019-08-23 11:32:52 +00:00
|
|
|
OutboundMessage::OutboundMessage() : m_Size{0}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
OutboundMessage::OutboundMessage(uint64_t msgid, const llarp_buffer_t &pkt,
|
|
|
|
ILinkSession::CompletionHandler handler)
|
|
|
|
: m_Size{std::min(pkt.sz, MAX_LINK_MSG_SIZE)}
|
|
|
|
, m_MsgID{msgid}
|
|
|
|
, m_Completed{handler}
|
|
|
|
{
|
|
|
|
m_Data.Zero();
|
|
|
|
std::copy_n(pkt.base, m_Size, m_Data.begin());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector< byte_t >
|
|
|
|
OutboundMessage::XMIT() const
|
|
|
|
{
|
|
|
|
std::vector< byte_t > xmit{
|
|
|
|
LLARP_PROTO_VERSION, Command::eXMIT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
2019-08-22 20:53:27 +00:00
|
|
|
htobe16buf(xmit.data() + 2, m_Size);
|
|
|
|
htobe64buf(xmit.data() + 4, m_MsgID);
|
|
|
|
const llarp_buffer_t buf{m_Data.data(), m_Size};
|
|
|
|
ShortHash H;
|
|
|
|
CryptoManager::instance()->shorthash(H, buf);
|
|
|
|
std::copy(H.begin(), H.end(), std::back_inserter(xmit));
|
|
|
|
LogDebug("xmit H=", H.ToHex());
|
|
|
|
return xmit;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-08-23 11:32:52 +00:00
|
|
|
OutboundMessage::Completed()
|
2019-08-22 20:53:27 +00:00
|
|
|
{
|
|
|
|
if(m_Completed)
|
|
|
|
{
|
|
|
|
m_Completed(ILinkSession::DeliveryStatus::eDeliverySuccess);
|
|
|
|
}
|
|
|
|
m_Completed = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
OutboundMessage::ShouldFlush(llarp_time_t now) const
|
|
|
|
{
|
2019-08-23 11:32:52 +00:00
|
|
|
static constexpr llarp_time_t FlushInterval = 500;
|
2019-08-22 20:53:27 +00:00
|
|
|
return now - m_LastFlush >= FlushInterval;
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
void
|
2019-08-22 20:53:27 +00:00
|
|
|
OutboundMessage::Ack(byte_t bitmask)
|
|
|
|
{
|
2019-08-23 11:32:52 +00:00
|
|
|
m_Acks = std::bitset< 8 >(bitmask);
|
2019-08-22 20:53:27 +00:00
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
void
|
|
|
|
OutboundMessage::FlushUnAcked(
|
|
|
|
std::function< void(const llarp_buffer_t &) > sendpkt, llarp_time_t now)
|
2019-08-22 20:53:27 +00:00
|
|
|
{
|
|
|
|
uint16_t idx = 0;
|
|
|
|
while(idx < m_Size)
|
|
|
|
{
|
|
|
|
if(not m_Acks[idx / FragmentSize])
|
|
|
|
{
|
2019-08-23 11:32:52 +00:00
|
|
|
std::vector< byte_t > frag{LLARP_PROTO_VERSION,
|
|
|
|
Command::eDATA,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0};
|
2019-08-22 20:53:27 +00:00
|
|
|
htobe16buf(frag.data() + 2, idx);
|
|
|
|
htobe64buf(frag.data() + 4, m_MsgID);
|
2019-08-23 11:32:52 +00:00
|
|
|
std::copy(m_Data.begin() + idx, m_Data.begin() + idx + FragmentSize,
|
|
|
|
std::back_inserter(frag));
|
2019-08-22 20:53:27 +00:00
|
|
|
const llarp_buffer_t pkt{frag};
|
|
|
|
sendpkt(pkt);
|
|
|
|
}
|
|
|
|
idx += FragmentSize;
|
|
|
|
}
|
|
|
|
m_LastFlush = now;
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
bool
|
|
|
|
OutboundMessage::IsTransmitted() const
|
|
|
|
{
|
|
|
|
for(uint16_t idx = 0; idx < m_Size; idx += FragmentSize)
|
|
|
|
{
|
|
|
|
if(!m_Acks.test(idx / FragmentSize))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2019-08-22 20:53:27 +00:00
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
InboundMessage::InboundMessage() : m_Size{0}
|
|
|
|
{
|
|
|
|
}
|
2019-08-22 20:53:27 +00:00
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
InboundMessage::InboundMessage(uint64_t msgid, uint16_t sz, ShortHash h)
|
|
|
|
: m_Digset{std::move(h)}, m_Size{sz}, m_MsgID{msgid}
|
|
|
|
{
|
|
|
|
}
|
2019-08-22 20:53:27 +00:00
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
void
|
|
|
|
InboundMessage::HandleData(uint16_t idx, const byte_t *ptr)
|
2019-08-22 20:53:27 +00:00
|
|
|
{
|
|
|
|
if(idx + FragmentSize > MAX_LINK_MSG_SIZE)
|
|
|
|
return;
|
2019-08-23 11:32:52 +00:00
|
|
|
auto *dst = m_Data.data() + idx;
|
2019-08-22 20:53:27 +00:00
|
|
|
std::copy_n(ptr, FragmentSize, dst);
|
|
|
|
m_Acks.set(idx / FragmentSize);
|
2019-08-23 11:32:52 +00:00
|
|
|
LogDebug("got fragment ", idx / FragmentSize, " of ", m_Size);
|
2019-08-22 20:53:27 +00:00
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
std::vector< byte_t >
|
|
|
|
InboundMessage::ACKS() const
|
2019-08-22 20:53:27 +00:00
|
|
|
{
|
2019-08-23 11:32:52 +00:00
|
|
|
std::vector< byte_t > acks{
|
|
|
|
LLARP_PROTO_VERSION, Command::eACKS, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
uint8_t{m_Acks.to_ulong()}};
|
|
|
|
|
2019-08-22 20:53:27 +00:00
|
|
|
htobe64buf(acks.data() + 2, m_MsgID);
|
|
|
|
return acks;
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
bool
|
2019-08-22 20:53:27 +00:00
|
|
|
InboundMessage::IsCompleted() const
|
|
|
|
{
|
|
|
|
for(uint16_t idx = 0; idx < m_Size; idx += FragmentSize)
|
|
|
|
{
|
|
|
|
if(!m_Acks.test(idx / FragmentSize))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
InboundMessage::ShouldSendACKS(llarp_time_t now) const
|
|
|
|
{
|
|
|
|
return now - m_LastACKSent > 1000 || IsCompleted();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-08-23 11:32:52 +00:00
|
|
|
InboundMessage::SendACKS(
|
|
|
|
std::function< void(const llarp_buffer_t &) > sendpkt, llarp_time_t now)
|
2019-08-22 20:53:27 +00:00
|
|
|
{
|
|
|
|
auto acks = ACKS();
|
|
|
|
const llarp_buffer_t pkt{acks};
|
|
|
|
sendpkt(pkt);
|
|
|
|
m_LastACKSent = now;
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
bool
|
2019-08-22 20:53:27 +00:00
|
|
|
InboundMessage::Verify() const
|
|
|
|
{
|
|
|
|
ShortHash gotten;
|
|
|
|
const llarp_buffer_t buf{m_Data.data(), m_Size};
|
|
|
|
CryptoManager::instance()->shorthash(gotten, buf);
|
2019-08-23 11:32:52 +00:00
|
|
|
LogDebug("gotten=", gotten.ToHex());
|
2019-08-22 20:53:27 +00:00
|
|
|
if(gotten != m_Digset)
|
|
|
|
{
|
|
|
|
DumpBuffer(buf);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:32:52 +00:00
|
|
|
} // namespace iwp
|
|
|
|
} // namespace llarp
|