You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lokinet/llarp/iwp/session.cpp

830 lines
24 KiB
C++

5 years ago
#include <iwp/session.hpp>
5 years ago
#include <messages/link_intro.hpp>
#include <messages/discard.hpp>
#include <util/meta/memfn.hpp>
5 years ago
namespace llarp
{
namespace iwp
{
5 years ago
ILinkSession::Packet_t
CreatePacket(Command cmd, size_t plainsize, size_t minpad, size_t variance)
{
const size_t pad = minpad > 0 ? minpad + randint() % variance : 0;
5 years ago
ILinkSession::Packet_t pkt(PacketOverhead + plainsize + pad + 2);
// randomize pad
if(pad)
{
CryptoManager::instance()->randbytes(
pkt.data() + PacketOverhead + 2 + plainsize, pad);
}
// randomize nounce
CryptoManager::instance()->randbytes(pkt.data() + HMACSIZE, TUNNONCESIZE);
5 years ago
pkt[PacketOverhead] = LLARP_PROTO_VERSION;
pkt[PacketOverhead + 1] = cmd;
return pkt;
}
5 years ago
Session::Session(LinkLayer* p, RouterContact rc, AddressInfo ai)
: m_State{State::Initial}
, m_Inbound{false}
, m_Parent{p}
, m_CreatedAt{p->Now()}
, m_RemoteAddr{ai}
, m_ChosenAI{std::move(ai)}
, m_RemoteRC{std::move(rc)}
{
token.Zero();
GotLIM = util::memFn(&Session::GotOutboundLIM, this);
CryptoManager::instance()->shorthash(m_SessionKey,
llarp_buffer_t(rc.pubkey));
m_EncryptNext = std::make_shared< CryptoQueue_t >();
m_DecryptNext = std::make_shared< CryptoQueue_t >();
5 years ago
}
Session::Session(LinkLayer* p, Addr from)
: m_State{State::Initial}
, m_Inbound{true}
, m_Parent{p}
, m_CreatedAt{p->Now()}
, m_RemoteAddr{from}
{
token.Randomize();
GotLIM = util::memFn(&Session::GotInboundLIM, this);
const PubKey pk = m_Parent->GetOurRC().pubkey;
CryptoManager::instance()->shorthash(m_SessionKey, llarp_buffer_t(pk));
m_EncryptNext = std::make_shared< CryptoQueue_t >();
m_DecryptNext = std::make_shared< CryptoQueue_t >();
5 years ago
}
void
Session::Send_LL(const llarp_buffer_t& pkt)
{
LogDebug("send ", pkt.sz, " to ", m_RemoteAddr);
m_Parent->SendTo_LL(m_RemoteAddr, pkt);
m_LastTX = time_now_ms();
}
bool
Session::GotInboundLIM(const LinkIntroMessage* msg)
5 years ago
{
if(msg->rc.pubkey != m_ExpectedIdent)
{
LogError("ident key missmatch from ", m_RemoteAddr, " ", msg->rc.pubkey,
" != ", m_ExpectedIdent);
5 years ago
return false;
}
m_State = State::Ready;
GotLIM = util::memFn(&Session::GotRenegLIM, this);
m_RemoteRC = msg->rc;
m_Parent->MapAddr(m_RemoteRC.pubkey, this);
return m_Parent->SessionEstablished(this);
5 years ago
}
bool
Session::GotOutboundLIM(const LinkIntroMessage* msg)
5 years ago
{
if(msg->rc.pubkey != m_RemoteRC.pubkey)
{
LogError("ident key missmatch");
5 years ago
return false;
}
m_RemoteRC = msg->rc;
GotLIM = util::memFn(&Session::GotRenegLIM, this);
auto self = shared_from_this();
SendOurLIM([self](ILinkSession::DeliveryStatus st) {
if(st == ILinkSession::DeliveryStatus::eDeliverySuccess)
{
self->m_State = State::Ready;
self->m_Parent->MapAddr(self->m_RemoteRC.pubkey, self.get());
self->m_Parent->SessionEstablished(self.get());
}
});
5 years ago
return true;
}
void
Session::SendOurLIM(ILinkSession::CompletionHandler h)
5 years ago
{
LinkIntroMessage msg;
msg.rc = m_Parent->GetOurRC();
msg.N.Randomize();
msg.P = 60000;
if(not msg.Sign(m_Parent->Sign))
{
LogError("failed to sign our RC for ", m_RemoteAddr);
return;
}
ILinkSession::Message_t data(LinkIntroMessage::MaxSize + PacketOverhead);
llarp_buffer_t buf(data);
5 years ago
if(not msg.BEncode(&buf))
{
LogError("failed to encode LIM for ", m_RemoteAddr);
}
if(!SendMessageBuffer(std::move(data), h))
5 years ago
{
LogError("failed to send LIM to ", m_RemoteAddr);
}
LogDebug("sent LIM to ", m_RemoteAddr);
}
void
5 years ago
Session::EncryptAndSend(ILinkSession::Packet_t data)
5 years ago
{
m_EncryptNext->emplace_back(std::move(data));
if(!IsEstablished())
{
EncryptWorker(std::move(m_EncryptNext));
m_EncryptNext = std::make_shared< CryptoQueue_t >();
}
}
void
Session::EncryptWorker(CryptoQueue_ptr msgs)
{
LogDebug("encrypt worker ", msgs->size(), " messages");
for(auto& pkt : *msgs)
{
llarp_buffer_t pktbuf(pkt);
const TunnelNonce nonce_ptr{pkt.data() + HMACSIZE};
pktbuf.base += PacketOverhead;
pktbuf.cur = pktbuf.base;
pktbuf.sz -= PacketOverhead;
CryptoManager::instance()->xchacha20(pktbuf, m_SessionKey, nonce_ptr);
pktbuf.base = pkt.data() + HMACSIZE;
pktbuf.sz = pkt.size() - HMACSIZE;
CryptoManager::instance()->hmac(pkt.data(), pktbuf, m_SessionKey);
pktbuf.base = pkt.data();
pktbuf.cur = pkt.data();
pktbuf.sz = pkt.size();
Send_LL(pktbuf);
}
5 years ago
}
void
Session::Close()
{
if(m_State == State::Closed)
return;
5 years ago
auto close_msg = CreatePacket(Command::eCLOS, 0, 16, 16);
EncryptAndSend(std::move(close_msg));
if(m_State == State::Ready)
m_Parent->UnmapAddr(m_RemoteAddr);
5 years ago
m_State = State::Closed;
LogInfo("closing connection to ", m_RemoteAddr);
5 years ago
}
bool
5 years ago
Session::SendMessageBuffer(ILinkSession::Message_t buf,
5 years ago
ILinkSession::CompletionHandler completed)
{
if(m_TXMsgs.size() >= MaxSendQueueSize)
return false;
const auto now = m_Parent->Now();
5 years ago
const auto msgid = m_TXID++;
auto& msg =
5 years ago
m_TXMsgs
.emplace(msgid,
OutboundMessage{msgid, std::move(buf), now, completed})
.first->second;
EncryptAndSend(msg.XMIT());
msg.FlushUnAcked(util::memFn(&Session::EncryptAndSend, this), now);
5 years ago
LogDebug("send message ", msgid);
return true;
}
void
Session::SendMACK()
{
// send multi acks
while(!m_SendMACKS.empty())
{
5 years ago
const auto sz = m_SendMACKS.size();
const auto max = Session::MaxACKSInMACK;
auto numAcks = std::min(sz, max);
5 years ago
auto mack =
CreatePacket(Command::eMACK, numAcks * sizeof(uint64_t), 0, 0);
mack[PacketOverhead + 2] = byte_t{numAcks};
byte_t* ptr = mack.data() + 3 + PacketOverhead;
while(numAcks > 0)
{
htobe64buf(ptr, m_SendMACKS.back());
m_SendMACKS.pop_back();
numAcks--;
ptr += sizeof(uint64_t);
}
5 years ago
EncryptAndSend(std::move(mack));
}
}
5 years ago
void
Session::Pump()
{
const auto now = m_Parent->Now();
if(m_State == State::Ready || m_State == State::LinkIntro)
5 years ago
{
if(ShouldPing())
SendKeepAlive();
SendMACK();
for(auto& item : m_RXMsgs)
5 years ago
{
if(item.second.ShouldSendACKS(now))
5 years ago
{
item.second.SendACKS(util::memFn(&Session::EncryptAndSend, this),
now);
5 years ago
}
}
for(auto& item : m_TXMsgs)
5 years ago
{
if(item.second.ShouldFlush(now))
{
item.second.FlushUnAcked(
util::memFn(&Session::EncryptAndSend, this), now);
}
5 years ago
}
}
5 years ago
auto self = shared_from_this();
if(!m_EncryptNext->empty())
{
5 years ago
m_Parent->QueueWork([self, data = std::move(m_EncryptNext)] {
self->EncryptWorker(data);
});
m_EncryptNext = std::make_shared< CryptoQueue_t >();
}
if(!m_DecryptNext->empty())
{
5 years ago
m_Parent->QueueWork([self, data = std::move(m_DecryptNext)] {
self->DecryptWorker(data);
});
m_DecryptNext = std::make_shared< CryptoQueue_t >();
}
5 years ago
}
bool
Session::GotRenegLIM(const LinkIntroMessage* lim)
5 years ago
{
LogDebug("renegotiate session on ", m_RemoteAddr);
5 years ago
return m_Parent->SessionRenegotiate(lim->rc, m_RemoteRC);
}
bool
5 years ago
Session::RenegotiateSession()
{
SendOurLIM();
return true;
}
bool
Session::ShouldPing() const
{
if(m_State == State::Ready)
{
const auto now = m_Parent->Now();
return now - m_LastTX > PingInterval;
}
return false;
5 years ago
}
util::StatusObject
Session::ExtractStatus() const
{
return {{"remoteAddr", m_RemoteAddr.ToString()},
{"remoteRC", m_RemoteRC.ExtractStatus()}};
5 years ago
}
bool
Session::TimedOut(llarp_time_t now) const
{
if(m_State == State::Ready || m_State == State::LinkIntro)
{
return now > m_LastRX && now - m_LastRX > SessionAliveTimeout;
}
return now - m_CreatedAt > SessionAliveTimeout;
5 years ago
}
void
Session::Tick(llarp_time_t now)
5 years ago
{
// remove pending outbound messsages that timed out
// inform waiters
{
auto itr = m_TXMsgs.begin();
while(itr != m_TXMsgs.end())
{
if(itr->second.IsTimedOut(now))
{
itr->second.InformTimeout();
itr = m_TXMsgs.erase(itr);
}
else
++itr;
}
}
{
// remove pending inbound messages that timed out
auto itr = m_RXMsgs.begin();
while(itr != m_RXMsgs.end())
{
if(itr->second.IsTimedOut(now))
{
m_ReplayFilter.emplace(itr->first, now);
itr = m_RXMsgs.erase(itr);
}
else
++itr;
}
}
{
// decay replay window
auto itr = m_ReplayFilter.begin();
while(itr != m_ReplayFilter.end())
{
5 years ago
if(itr->second + ReplayWindow <= now)
{
itr = m_ReplayFilter.erase(itr);
}
else
++itr;
}
}
5 years ago
}
using Introduction = AlignedBuffer< PubKey::SIZE + PubKey::SIZE
+ TunnelNonce::SIZE + Signature::SIZE >;
5 years ago
void
5 years ago
Session::GenerateAndSendIntro()
{
TunnelNonce N;
N.Randomize();
ILinkSession::Packet_t req(Introduction::SIZE + PacketOverhead);
const auto pk = m_Parent->GetOurRC().pubkey;
const auto e_pk = m_Parent->RouterEncryptionSecret().toPublic();
auto itr = req.begin() + PacketOverhead;
std::copy_n(pk.begin(), pk.size(), itr);
itr += pk.size();
std::copy_n(e_pk.begin(), e_pk.size(), itr);
itr += e_pk.size();
std::copy(N.begin(), N.end(), itr);
Signature Z;
llarp_buffer_t signbuf(req.data() + PacketOverhead,
Introduction::SIZE - Signature::SIZE);
m_Parent->Sign(Z, signbuf);
std::copy_n(Z.begin(), Z.size(),
req.begin() + PacketOverhead
+ (Introduction::SIZE - Signature::SIZE));
CryptoManager::instance()->randbytes(req.data() + HMACSIZE, TUNNONCESIZE);
5 years ago
EncryptAndSend(std::move(req));
5 years ago
m_State = State::Introduction;
if(not CryptoManager::instance()->transport_dh_client(
m_SessionKey, m_ChosenAI.pubkey,
m_Parent->RouterEncryptionSecret(), N))
{
LogError("failed to transport_dh_client on outbound session to ",
m_RemoteAddr);
return;
}
LogDebug("sent intro to ", m_RemoteAddr);
5 years ago
}
5 years ago
void
5 years ago
Session::HandleCreateSessionRequest(Packet_t pkt)
5 years ago
{
5 years ago
if(not DecryptMessageInPlace(pkt))
5 years ago
{
LogError("failed to decrypt session request from ", m_RemoteAddr);
return;
}
5 years ago
if(pkt.size() < token.size() + PacketOverhead)
5 years ago
{
LogError("bad session request size, ", pkt.size(), " < ",
5 years ago
token.size() + PacketOverhead, " from ", m_RemoteAddr);
5 years ago
return;
}
5 years ago
const auto begin = pkt.begin() + PacketOverhead;
if(not std::equal(begin, begin + token.size(), token.begin()))
5 years ago
{
LogError("token missmatch from ", m_RemoteAddr);
return;
}
m_LastRX = m_Parent->Now();
m_State = State::LinkIntro;
5 years ago
SendOurLIM();
}
void
5 years ago
Session::HandleGotIntro(Packet_t pkt)
5 years ago
{
5 years ago
if(pkt.size() < Introduction::SIZE + PacketOverhead)
{
LogWarn("intro too small from ", m_RemoteAddr);
5 years ago
return;
}
byte_t* ptr = pkt.data() + PacketOverhead;
5 years ago
TunnelNonce N;
std::copy_n(ptr, PubKey::SIZE, m_ExpectedIdent.begin());
ptr += PubKey::SIZE;
std::copy_n(ptr, PubKey::SIZE, m_RemoteOnionKey.begin());
ptr += PubKey::SIZE;
std::copy_n(ptr, TunnelNonce::SIZE, N.begin());
ptr += TunnelNonce::SIZE;
Signature Z;
std::copy_n(ptr, Z.size(), Z.begin());
const llarp_buffer_t verifybuf(pkt.data() + PacketOverhead,
Introduction::SIZE - Signature::SIZE);
if(!CryptoManager::instance()->verify(m_ExpectedIdent, verifybuf, Z))
{
LogError("intro verify failed from ", m_RemoteAddr);
return;
}
5 years ago
const PubKey pk = m_Parent->TransportSecretKey().toPublic();
LogDebug("got intro: remote-pk=", m_RemoteOnionKey.ToHex(),
5 years ago
" N=", N.ToHex(), " local-pk=", pk.ToHex());
if(not CryptoManager::instance()->transport_dh_server(
m_SessionKey, m_RemoteOnionKey, m_Parent->TransportSecretKey(), N))
5 years ago
{
LogError("failed to transport_dh_server on inbound intro from ",
m_RemoteAddr);
5 years ago
return;
}
5 years ago
std::vector< byte_t > reply(token.size() + PacketOverhead);
// random nonce
CryptoManager::instance()->randbytes(reply.data() + HMACSIZE,
5 years ago
TUNNONCESIZE);
// set token
std::copy_n(token.begin(), token.size(), reply.begin() + PacketOverhead);
5 years ago
m_LastRX = m_Parent->Now();
5 years ago
EncryptAndSend(std::move(reply));
LogDebug("sent intro ack to ", m_RemoteAddr);
5 years ago
m_State = State::Introduction;
}
void
5 years ago
Session::HandleGotIntroAck(Packet_t pkt)
5 years ago
{
5 years ago
if(pkt.size() < token.size() + PacketOverhead)
5 years ago
{
LogError("bad intro ack size ", pkt.size(), " < ",
5 years ago
token.size() + PacketOverhead, " from ", m_RemoteAddr);
5 years ago
return;
}
5 years ago
std::vector< byte_t > reply(token.size() + PacketOverhead);
if(not DecryptMessageInPlace(pkt))
5 years ago
{
5 years ago
LogError("intro ack decrypt failed from ", m_RemoteAddr);
5 years ago
return;
}
m_LastRX = m_Parent->Now();
5 years ago
std::copy_n(pkt.begin() + PacketOverhead, token.size(), token.begin());
std::copy_n(token.begin(), token.size(), reply.begin() + PacketOverhead);
// random nounce
CryptoManager::instance()->randbytes(reply.data() + HMACSIZE,
TUNNONCESIZE);
5 years ago
EncryptAndSend(std::move(reply));
LogDebug("sent session request to ", m_RemoteAddr);
5 years ago
m_State = State::LinkIntro;
}
bool
5 years ago
Session::DecryptMessageInPlace(Packet_t& pkt)
5 years ago
{
5 years ago
if(pkt.size() <= PacketOverhead)
{
5 years ago
LogError("packet too small from ", m_RemoteAddr);
5 years ago
return false;
}
5 years ago
const llarp_buffer_t buf(pkt);
5 years ago
ShortHash H;
llarp_buffer_t curbuf(buf.base, buf.sz);
5 years ago
curbuf.base += ShortHash::SIZE;
curbuf.sz -= ShortHash::SIZE;
if(not CryptoManager::instance()->hmac(H.data(), curbuf, m_SessionKey))
{
LogError("failed to caclulate keyed hash for ", m_RemoteAddr);
return false;
}
const ShortHash expected{buf.base};
if(H != expected)
{
LogError("keyed hash missmatch ", H, " != ", expected, " from ",
m_RemoteAddr, " state=", int(m_State), " size=", buf.sz);
5 years ago
return false;
}
const TunnelNonce N{curbuf.base};
5 years ago
curbuf.base += 32;
curbuf.sz -= 32;
LogDebug("decrypt: ", curbuf.sz, " bytes from ", m_RemoteAddr);
5 years ago
return CryptoManager::instance()->xchacha20(curbuf, m_SessionKey, N);
5 years ago
}
void
Session::Start()
{
if(m_Inbound)
return;
GenerateAndSendIntro();
}
void
5 years ago
Session::HandleSessionData(Packet_t pkt)
5 years ago
{
m_DecryptNext->emplace_back(pkt);
}
void
Session::DecryptWorker(CryptoQueue_ptr msgs)
{
CryptoQueue_t recvMsgs;
for(auto& pkt : *msgs)
5 years ago
{
5 years ago
if(not DecryptMessageInPlace(pkt))
{
LogError("failed to decrypt session data from ", m_RemoteAddr);
continue;
}
5 years ago
if(pkt[PacketOverhead] != LLARP_PROTO_VERSION)
{
LogError("protocol version missmatch ", int(pkt[PacketOverhead]),
" != ", LLARP_PROTO_VERSION);
continue;
}
recvMsgs.emplace_back(std::move(pkt));
5 years ago
}
LogDebug("decrypted ", recvMsgs.size(), " packets from ", m_RemoteAddr);
m_Parent->logic()->queue_func(std::bind(
&Session::HandlePlaintext, shared_from_this(), std::move(recvMsgs)));
}
void
Session::HandlePlaintext(CryptoQueue_t msgs)
{
for(auto& result : msgs)
5 years ago
{
5 years ago
switch(result[PacketOverhead + 1])
{
case Command::eXMIT:
HandleXMIT(std::move(result));
break;
case Command::eDATA:
HandleDATA(std::move(result));
break;
case Command::eACKS:
HandleACKS(std::move(result));
break;
case Command::ePING:
HandlePING(std::move(result));
break;
case Command::eNACK:
HandleNACK(std::move(result));
break;
case Command::eCLOS:
HandleCLOS(std::move(result));
break;
case Command::eMACK:
HandleMACK(std::move(result));
break;
default:
5 years ago
LogError("invalid command ", int(result[PacketOverhead + 1]),
" from ", m_RemoteAddr);
}
5 years ago
}
}
void
Session::HandleMACK(std::vector< byte_t > data)
{
if(data.size() < 3 + PacketOverhead)
{
LogError("impossibly short mack from ", m_RemoteAddr);
return;
}
byte_t numAcks = data[2 + PacketOverhead];
if(data.size() < ((numAcks * sizeof(uint64_t)) + 3))
{
LogError("short mack from ", m_RemoteAddr);
return;
}
byte_t* ptr = data.data() + 3 + PacketOverhead;
while(numAcks > 0)
{
uint64_t acked = bufbe64toh(ptr);
auto itr = m_TXMsgs.find(acked);
if(itr != m_TXMsgs.end())
{
itr->second.Completed();
m_TXMsgs.erase(itr);
}
else
{
LogDebug("ignored mack for txid=", acked, " from ", m_RemoteAddr);
}
ptr += sizeof(uint64_t);
numAcks--;
}
}
5 years ago
void
Session::HandleNACK(std::vector< byte_t > data)
{
if(data.size() < 10 + PacketOverhead)
{
LogError("short nack from ", m_RemoteAddr);
return;
}
uint64_t txid = bufbe64toh(data.data() + 2 + PacketOverhead);
LogDebug("got nack on ", txid, " from ", m_RemoteAddr);
auto itr = m_TXMsgs.find(txid);
if(itr != m_TXMsgs.end())
{
auto xmit = itr->second.XMIT();
EncryptAndSend(std::move(xmit));
}
m_LastRX = m_Parent->Now();
}
void
Session::HandleXMIT(std::vector< byte_t > data)
5 years ago
{
if(data.size() < 44 + PacketOverhead)
5 years ago
{
LogError("short XMIT from ", m_RemoteAddr);
5 years ago
return;
}
uint16_t sz = bufbe16toh(data.data() + 2 + PacketOverhead);
uint64_t rxid = bufbe64toh(data.data() + 4 + PacketOverhead);
ShortHash h{data.data() + 12 + PacketOverhead};
5 years ago
LogDebug("rxid=", rxid, " sz=", sz, " h=", h.ToHex());
m_LastRX = m_Parent->Now();
{
// check for replay
auto itr = m_ReplayFilter.find(rxid);
if(itr != m_ReplayFilter.end())
{
LogDebug("duplicate rxid=", rxid, " from ", m_RemoteAddr);
return;
}
}
{
auto itr = m_RXMsgs.find(rxid);
if(itr == m_RXMsgs.end())
m_RXMsgs.emplace(
rxid, InboundMessage{rxid, sz, std::move(h), m_Parent->Now()});
else
LogDebug("got duplicate xmit on ", rxid, " from ", m_RemoteAddr);
}
5 years ago
}
void
Session::HandleDATA(std::vector< byte_t > data)
5 years ago
{
if(data.size() <= 12 + PacketOverhead)
5 years ago
{
LogError("short DATA from ", m_RemoteAddr, " ", data.size());
5 years ago
return;
}
m_LastRX = m_Parent->Now();
uint16_t sz = bufbe16toh(data.data() + 2 + PacketOverhead);
uint64_t rxid = bufbe64toh(data.data() + 4 + PacketOverhead);
auto itr = m_RXMsgs.find(rxid);
5 years ago
if(itr == m_RXMsgs.end())
{
if(m_ReplayFilter.find(rxid) == m_ReplayFilter.end())
{
LogDebug("no rxid=", rxid, " for ", m_RemoteAddr);
auto nack = CreatePacket(Command::eNACK, 8);
htobe64buf(nack.data() + PacketOverhead + 2, rxid);
EncryptAndSend(std::move(nack));
}
5 years ago
return;
}
{
const llarp_buffer_t buf(data.data() + PacketOverhead + 12,
data.size() - (PacketOverhead + 12));
itr->second.HandleData(sz, buf, m_Parent->Now());
}
if(itr->second.IsCompleted())
{
if(itr->second.Verify())
{
5 years ago
auto msg = std::move(itr->second);
const llarp_buffer_t buf(msg.m_Data.data(), msg.m_Size);
m_Parent->HandleMessage(this, buf);
m_ReplayFilter.emplace(itr->first, m_Parent->Now());
m_SendMACKS.emplace_back(itr->first);
}
else
{
LogError("hash missmatch for message ", itr->first);
}
m_RXMsgs.erase(itr);
}
5 years ago
}
void
Session::HandleACKS(std::vector< byte_t > data)
5 years ago
{
if(data.size() < 11 + PacketOverhead)
5 years ago
{
LogError("short ACKS from ", m_RemoteAddr);
5 years ago
return;
}
const auto now = m_Parent->Now();
m_LastRX = now;
uint64_t txid = bufbe64toh(data.data() + 2 + PacketOverhead);
auto itr = m_TXMsgs.find(txid);
5 years ago
if(itr == m_TXMsgs.end())
{
5 years ago
LogDebug("no txid=", txid, " for ", m_RemoteAddr);
5 years ago
return;
}
itr->second.Ack(data[10 + PacketOverhead]);
if(itr->second.IsTransmitted())
{
LogDebug("sent message ", itr->first);
itr->second.Completed();
itr = m_TXMsgs.erase(itr);
}
else
{
itr->second.FlushUnAcked(util::memFn(&Session::EncryptAndSend, this),
now);
}
5 years ago
}
void Session::HandleCLOS(std::vector< byte_t >)
5 years ago
{
LogInfo("remote closed by ", m_RemoteAddr);
5 years ago
Close();
}
void Session::HandlePING(std::vector< byte_t >)
5 years ago
{
m_LastRX = m_Parent->Now();
}
bool
Session::SendKeepAlive()
{
if(m_State == State::Ready)
{
auto pkt = CreatePacket(Command::ePING, 0);
EncryptAndSend(std::move(pkt));
return true;
}
5 years ago
return false;
}
bool
Session::IsEstablished() const
{
return m_State == State::Ready;
}
void
Session::Recv_LL(ILinkSession::Packet_t data)
5 years ago
{
switch(m_State)
{
case State::Initial:
if(m_Inbound)
{
// initial data
// enter introduction phase
if(DecryptMessageInPlace(data))
HandleGotIntro(std::move(data));
else
LogError("bad intro from ", m_RemoteAddr);
5 years ago
}
else
{
// this case should never happen
::abort();
}
break;
case State::Introduction:
if(m_Inbound)
{
// we are replying to an intro ack
HandleCreateSessionRequest(std::move(data));
5 years ago
}
else
{
// we got an intro ack
// send a session request
HandleGotIntroAck(std::move(data));
5 years ago
}
break;
case State::LinkIntro:
default:
HandleSessionData(std::move(data));
5 years ago
break;
}
}
} // namespace iwp
} // namespace llarp