#include
#include
#include
namespace llarp
{
namespace iwp
{
void
OuterMessage::Clear()
{
command = 0;
flow.Zero();
netid.Zero();
nextFlowID.Zero();
rejectReason.clear();
N.Zero();
X.Zero();
Xsize = 0;
Z.Zero();
}
bool
OuterMessage::Decode(llarp_buffer_t* buf)
{
if(buf->size_left() < 34)
return false;
command = *buf->cur;
++buf->cur;
if(*buf->cur != '=')
return false;
std::copy_n(flow.begin(), 32, buf->cur);
buf->cur += 32;
switch(command)
{
case eOCMD_ObtainFlowID:
if(buf->size_left() < 40)
return false;
buf->cur += 32;
std::copy_n(netid.begin(), 8, buf->cur);
return true;
case eOCMD_GiveFlowID:
if(buf->size_left() < 32)
return false;
std::copy_n(nextFlowID.begin(), 32, buf->cur);
return true;
case eOCMD_Reject:
rejectReason = std::string(buf->cur, buf->base + buf->sz);
return true;
case eOCMD_SessionNegotiate:
// explicit fallthrough
case eOCMD_TransmitData:
if(buf->size_left() <= 56)
return false;
std::copy_n(N.begin(), N.size(), buf->cur);
buf->cur += N.size();
Xsize = buf->size_left() - Z.size();
if(Xsize > X.size())
return false;
std::copy_n(X.begin(), Xsize, buf->cur);
buf->cur += Xsize;
std::copy_n(Z.begin(), Z.size(), buf->cur);
return true;
default:
return false;
}
}
LinkLayer::LinkLayer(Crypto* c, const SecretKey& enckey, GetRCFunc getrc,
LinkMessageHandler h, SessionEstablishedHandler est,
SessionRenegotiateHandler reneg, SignBufferFunc sign,
TimeoutHandler t, SessionClosedHandler closed)
: ILinkLayer(enckey, getrc, h, sign, est, reneg, t, closed), crypto(c)
{
}
LinkLayer::~LinkLayer()
{
}
void
LinkLayer::Pump()
{
ILinkLayer::Pump();
}
const char*
LinkLayer::Name() const
{
return "iwp";
}
bool
LinkLayer::KeyGen(SecretKey& k)
{
k.Zero();
crypto->encryption_keygen(k);
return !k.IsZero();
}
uint16_t
LinkLayer::Rank() const
{
return 2;
}
bool
LinkLayer::Start(Logic* l)
{
if(!ILinkLayer::Start(l))
return false;
/// TODO: change me to true when done
return false;
}
void
LinkLayer::RecvFrom(const Addr& from, const void* pkt, size_t sz)
{
m_OuterMsg.Clear();
llarp_buffer_t buf(pkt, sz);
if(!m_OuterMsg.Decode(&buf))
{
LogError("failed to decode outer message");
return;
}
NetID ourNetID;
switch(m_OuterMsg.command)
{
case eOCMD_ObtainFlowID:
if(!ShouldSendFlowID(from))
return; // drop
if(m_OuterMsg.netid == ourNetID)
SendFlowID(from, m_OuterMsg.flow);
else
SendReject(from, m_OuterMsg.flow, "bad net id");
}
}
ILinkSession*
LinkLayer::NewOutboundSession(const RouterContact& rc,
const AddressInfo& ai)
{
(void)rc;
(void)ai;
// TODO: implement me
return nullptr;
}
void
LinkLayer::SendFlowID(const Addr& to, const FlowID_t& flow)
{
// TODO: implement me
(void)to;
(void)flow;
}
bool
LinkLayer::ShouldSendFlowID(const Addr& to) const
{
(void)to;
// TODO: implement me
return false;
}
void
LinkLayer::SendReject(const Addr& to, const FlowID_t& flow, const char* msg)
{
// TODO: implement me
(void)to;
(void)flow;
(void)msg;
}
std::unique_ptr< ILinkLayer >
NewServerFromRouter(AbstractRouter* r)
{
using namespace std::placeholders;
return NewServer(
r->crypto(), r->encryption(), std::bind(&AbstractRouter::rc, r),
std::bind(&AbstractRouter::HandleRecvLinkMessageBuffer, r, _1, _2),
std::bind(&AbstractRouter::OnSessionEstablished, r, _1),
std::bind(&AbstractRouter::CheckRenegotiateValid, r, _1, _2),
std::bind(&AbstractRouter::Sign, r, _1, _2),
std::bind(&AbstractRouter::OnConnectTimeout, r, _1),
std::bind(&AbstractRouter::SessionClosed, r, _1));
}
std::unique_ptr< ILinkLayer >
NewServer(Crypto* c, const SecretKey& enckey, GetRCFunc getrc,
LinkMessageHandler h, SessionEstablishedHandler est,
SessionRenegotiateHandler reneg, SignBufferFunc sign,
TimeoutHandler t, SessionClosedHandler closed)
{
(void)c;
(void)enckey;
(void)getrc;
(void)h;
(void)est;
(void)reneg;
(void)sign;
(void)t;
(void)closed;
// TODO: implement me
return nullptr;
}
} // namespace iwp
} // namespace llarp