#include namespace llarp { namespace iwp { std::array< byte_t, 6 > OuterMessage::obtain_flow_id_magic = std::array< byte_t, 6 >{{'n', 'e', 't', 'i', 'd', '?'}}; std::array< byte_t, 6 > OuterMessage::give_flow_id_magic = std::array< byte_t, 6 >{{'n', 'e', 't', 'i', 'd', '!'}}; OuterMessage::OuterMessage() { Clear(); } OuterMessage::~OuterMessage() { } void OuterMessage::Clear() { command = 0; flow.Zero(); netid.Zero(); reject.fill(0); N.Zero(); X.Zero(); Xsize = 0; Zsig.Zero(); Zhash.Zero(); pubkey.Zero(); magic.fill(0); uinteger = 0; A.reset(); } void OuterMessage::CreateReject(const char* msg, llarp_time_t now, const PubKey& pk) { Clear(); std::copy_n(msg, std::min(strlen(msg), reject.size()), reject.begin()); uinteger = now; pubkey = pk; } bool OuterMessage::Encode(llarp_buffer_t* buf) const { if(buf->size_left() < 2) return false; *buf->cur = command; buf->cur++; *buf->cur = '='; buf->cur++; switch(command) { case eOCMD_ObtainFlowID: case eOCMD_GiveFlowID: if(!buf->write(reject.begin(), reject.end())) return false; if(!buf->write(give_flow_id_magic.begin(), give_flow_id_magic.end())) return false; if(!buf->write(flow.begin(), flow.end())) return false; if(!buf->write(pubkey.begin(), pubkey.end())) return false; return buf->write(Zsig.begin(), Zsig.end()); default: return false; } } bool OuterMessage::Decode(llarp_buffer_t* buf) { static constexpr size_t header_size = 2; if(buf->size_left() < header_size) return false; command = *buf->cur; ++buf->cur; if(*buf->cur != '=') return false; ++buf->cur; switch(command) { case eOCMD_ObtainFlowID: if(!buf->read_into(magic.begin(), magic.end())) return false; if(!buf->read_into(netid.begin(), netid.end())) return false; if(!buf->read_uint64(uinteger)) return false; if(!buf->read_into(pubkey.begin(), pubkey.end())) return false; if(buf->size_left() <= Zsig.size()) return false; Xsize = buf->size_left() - Zsig.size(); if(!buf->read_into(X.begin(), X.begin() + Xsize)) return false; return buf->read_into(Zsig.begin(), Zsig.end()); case eOCMD_GiveFlowID: if(!buf->read_into(magic.begin(), magic.end())) return false; if(!buf->read_into(flow.begin(), flow.end())) return false; if(!buf->read_into(pubkey.begin(), pubkey.end())) return false; buf->cur += buf->size_left() - Zsig.size(); return buf->read_into(Zsig.begin(), Zsig.end()); case eOCMD_Reject: if(!buf->read_into(reject.begin(), reject.end())) return false; if(!buf->read_uint64(uinteger)) return false; if(!buf->read_into(pubkey.begin(), pubkey.end())) return false; buf->cur += buf->size_left() - Zsig.size(); return buf->read_into(Zsig.begin(), Zsig.end()); case eOCMD_SessionNegotiate: if(!buf->read_into(flow.begin(), flow.end())) return false; if(!buf->read_into(pubkey.begin(), pubkey.end())) return false; if(!buf->read_uint64(uinteger)) return false; if(buf->size_left() == Zsig.size() + 32) { A.reset(new AlignedBuffer< 32 >()); if(!buf->read_into(A->begin(), A->end())) return false; } return buf->read_into(Zsig.begin(), Zsig.end()); case eOCMD_TransmitData: if(!buf->read_into(flow.begin(), flow.end())) return false; if(!buf->read_into(N.begin(), N.end())) return false; if(buf->size_left() <= Zhash.size()) return false; Xsize = buf->size_left() - Zhash.size(); if(!buf->read_into(X.begin(), X.begin() + Xsize)) return false; return buf->read_into(Zhash.begin(), Zhash.end()); default: return false; } } } // namespace iwp } // namespace llarp