I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::RouterInfo * router) { if (!router) // we send own RouterInfo router = &context.GetRouterInfo (); I2NPMessage * m = NewI2NPShortMessage (); I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)m->GetPayload (); memcpy (msg->key, router->GetIdentHash (), 32); msg->type = 0; msg->replyToken = 0; CryptoPP::Gzip compressor; compressor.Put (router->GetBuffer (), router->GetBufferLen ()); compressor.MessageEnd(); auto size = compressor.MaxRetrievable (); uint8_t * buf = m->GetPayload () + sizeof (I2NPDatabaseStoreMsg); *(uint16_t *)buf = htobe16 (size); // size buf += 2; // TODO: check if size doesn't exceed buffer compressor.Get (buf, size); m->len += sizeof (I2NPDatabaseStoreMsg) + 2 + size; // payload size FillI2NPMessageHeader (m, eI2NPDatabaseStore); return m; }
I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::LeaseSet * leaseSet, uint32_t replyToken) { if (!leaseSet) return nullptr; I2NPMessage * m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)payload; memcpy (msg->key, leaseSet->GetIdentHash (), 32); msg->type = 1; // LeaseSet msg->replyToken = htobe32 (replyToken); size_t size = sizeof (I2NPDatabaseStoreMsg); if (replyToken) { auto leases = leaseSet->GetNonExpiredLeases (); if (leases.size () > 0) { *(uint32_t *)(payload + size) = htobe32 (leases[0].tunnelID); size += 4; // reply tunnelID memcpy (payload + size, leases[0].tunnelGateway, 32); size += 32; // reply tunnel gateway } else msg->replyToken = 0; } memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); size += leaseSet->GetBufferLen (); m->len += size; FillI2NPMessageHeader (m, eI2NPDatabaseStore); return m; }
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LeaseSet> leaseSet, uint32_t replyToken) { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken); size_t size = DATABASE_STORE_HEADER_SIZE; if (replyToken) { auto leases = leaseSet->GetNonExpiredLeases (); if (leases.size () > 0) { htobe32buf (payload + size, leases[0].tunnelID); size += 4; // reply tunnelID memcpy (payload + size, leases[0].tunnelGateway, 32); size += 32; // reply tunnel gateway } else htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); } memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); size += leaseSet->GetBufferLen (); m->len += size; m->FillI2NPMessageHeader (eI2NPDatabaseStore); return m; }
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf) { auto msg = NewI2NPShortMessage (); msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; }
void TunnelGatewayBuffer::CreateCurrentTunnelDataMessage () { m_CurrentTunnelDataMsg = NewI2NPShortMessage (); m_CurrentTunnelDataMsg->Align (12); // we reserve space for padding m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE; m_CurrentTunnelDataMsg->len = m_CurrentTunnelDataMsg->offset; m_RemainingSize = TUNNEL_DATA_MAX_PAYLOAD_SIZE; }
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) { auto msg = NewI2NPShortMessage (); htobe32buf (msg->GetPayload (), tunnelID); msg->len += 4; // tunnelID msg->Concat (payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; }
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory, std::set<i2p::data::IdentHash> * excludedPeers) { auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); memcpy (buf, key, 32); // key buf += 32; memcpy (buf, from, 32); // from buf += 32; uint8_t flag = exploratory ? DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP : DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP; if (replyTunnelID) { *buf = flag | DATABASE_LOOKUP_DELIVERY_FLAG; // set delivery flag htobe32buf (buf+1, replyTunnelID); buf += 5; } else { *buf = flag; // flag buf++; } if (excludedPeers) { int cnt = excludedPeers->size (); htobe16buf (buf, cnt); buf += 2; for (auto& it: *excludedPeers) { memcpy (buf, it, 32); buf += 32; } } else { // nothing to exclude htobuf16 (buf, 0); buf += 2; } m->len += (buf - m->GetPayload ()); m->FillI2NPMessageHeader (eI2NPDatabaseLookup); return m; }
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID) { auto m = NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); if (msgID) { htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID); htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::util::GetMillisecondsSinceEpoch ()); } else // for SSU establishment { RAND_bytes ((uint8_t *)&msgID, 4); htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID); htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, 2); // netID = 2 } m->len += DELIVERY_STATUS_SIZE; m->FillI2NPMessageHeader (eI2NPDeliveryStatus); return m; }
I2NPMessage * CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, const i2p::data::RouterInfo * floodfill) { I2NPMessage * m = NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); size_t len = 0; memcpy (buf, ident, 32); len += 32; buf[len] = floodfill ? 1 : 0; // 1 router for now len++; if (floodfill) { memcpy (buf + len, floodfill->GetIdentHash (), 32); len += 32; } memcpy (buf + len, i2p::context.GetRouterInfo ().GetIdentHash (), 32); len += 32; m->len += len; FillI2NPMessageHeader (m, eI2NPDatabaseSearchReply); return m; }
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers) { auto m = NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); size_t len = 0; memcpy (buf, ident, 32); len += 32; buf[len] = routers.size (); len++; for (auto it: routers) { memcpy (buf + len, it, 32); len += 32; } memcpy (buf + len, i2p::context.GetRouterInfo ().GetIdentHash (), 32); len += 32; m->len += len; m->FillI2NPMessageHeader (eI2NPDatabaseSearchReply); return m; }
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router, uint32_t replyToken) { if (!router) // we send own RouterInfo router = context.GetSharedRouterInfo (); auto m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, router->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 0; // RouterInfo htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken); uint8_t * buf = payload + DATABASE_STORE_HEADER_SIZE; if (replyToken) { memset (buf, 0, 4); // zero tunnelID means direct reply buf += 4; memcpy (buf, router->GetIdentHash (), 32); buf += 32; } uint8_t * sizePtr = buf; buf += 2; m->len += (buf - payload); // payload size i2p::data::GzipDeflator deflator; size_t size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len); if (size) { htobe16buf (sizePtr, size); // size m->len += size; } else m = nullptr; if (m) m->FillI2NPMessageHeader (eI2NPDatabaseStore); return m; }
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, const std::set<i2p::data::IdentHash>& excludedFloodfills, const i2p::tunnel::InboundTunnel * replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag) { int cnt = excludedFloodfills.size (); auto m = cnt > 0 ? NewI2NPMessage () : NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); memcpy (buf, dest, 32); // key buf += 32; memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW buf += 32; *buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_ENCYPTION_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags htobe32buf (buf + 1, replyTunnel->GetNextTunnelID ()); // reply tunnel ID buf += 5; // excluded htobe16buf (buf, cnt); buf += 2; if (cnt > 0) { for (auto& it: excludedFloodfills) { memcpy (buf, it, 32); buf += 32; } } // encryption memcpy (buf, replyKey, 32); buf[32] = 1; // 1 tag memcpy (buf + 33, replyTag, 32); buf += 65; m->len += (buf - m->GetPayload ()); m->FillI2NPMessageHeader (eI2NPDatabaseLookup); return m; }
I2NPMessage * NewI2NPMessage (size_t len) { return (len < I2NP_MAX_SHORT_MESSAGE_SIZE/2) ? NewI2NPShortMessage () : NewI2NPMessage (); }
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg () { auto msg = NewI2NPShortMessage (); msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; return msg; }
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len) { return (len < I2NP_MAX_SHORT_MESSAGE_SIZE/2) ? NewI2NPShortMessage () : NewI2NPMessage (); }