From a81f34741fb6285b0a61a0c95eedc899a3df3438 Mon Sep 17 00:00:00 2001 From: Greg-Griffith Date: Wed, 18 Mar 2020 18:45:06 -0700 Subject: [PATCH 1/2] use 16 bit int for protocol, up from 8. --- src/net/datapacket.h | 8 ++++---- src/net/packetmanager.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/net/datapacket.h b/src/net/datapacket.h index 7a1dbd1d..82b882bf 100644 --- a/src/net/datapacket.h +++ b/src/net/datapacket.h @@ -22,9 +22,9 @@ const uint8_t PACKET_VERSION = 1; class CPacketHeader { public: - uint8_t nPacketVersion; - uint8_t nProtocolId; - uint8_t nProtocolVersion; + uint8_t nPacketVersion; // versioning of the CPacketHeader and related classes + uint16_t nProtocolId; // protocolId, should match the protocolid in mapBuffers + uint8_t nProtocolVersion; // versioning for use by the protocol itself uint64_t nTotalLength; // header + data in bytes (does not include extra vector serialization bytes) uint16_t nIdenfitication; // randomly generated uint256 nDataChecksum; // sha256 checksum @@ -146,7 +146,7 @@ class CPacket : public CPacketHeader ClearAndSetSize(); } - CPacket(uint8_t nProtocolIdIn, uint8_t nProtocolVersionIn) : CPacketHeader(nProtocolIdIn, nProtocolVersionIn) + CPacket(uint16_t nProtocolIdIn, uint8_t nProtocolVersionIn) : CPacketHeader(nProtocolIdIn, nProtocolVersionIn) { vData.clear(); } diff --git a/src/net/packetmanager.h b/src/net/packetmanager.h index 35e021ae..805fc1ec 100644 --- a/src/net/packetmanager.h +++ b/src/net/packetmanager.h @@ -26,7 +26,7 @@ struct PacketBuffer // vRecievedPackets should be partially stored on disk at some point std::vector vRecievedPackets; // the protocol id using this buffer - uint8_t nProtocolId; + uint16_t nProtocolId; }; class CPacketManager From fdd354aec64e4c05b3c6ab6ca2e08d42c252d083 Mon Sep 17 00:00:00 2001 From: Greg-Griffith Date: Wed, 18 Mar 2020 18:46:51 -0700 Subject: [PATCH 2/2] move packetman functions to cpp file. require sig to bind/fetch buffer --- src/net/packetmanager.cpp | 146 ++++++++++++++++++++++++++++++++++++++ src/net/packetmanager.h | 106 ++++----------------------- src/rpc/rpcaodv.cpp | 12 ++-- 3 files changed, 167 insertions(+), 97 deletions(-) diff --git a/src/net/packetmanager.cpp b/src/net/packetmanager.cpp index 383ac61c..43d6e3cf 100644 --- a/src/net/packetmanager.cpp +++ b/src/net/packetmanager.cpp @@ -4,3 +4,149 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "packetmanager.h" + +//////////////////////// +/// +/// Private +/// +void CPacketManager::FinalizePacket(const uint64_t &nonce, std::map::iterator iter) +{ + uint8_t protocolId = iter->second.nProtocolId; + if (mapBuffers.count(protocolId) == 0) + { + // this is an error, the proper entry should have been made by BindBuffer + return; + } + else + { + mapBuffers[protocolId].vRecievedPackets.push_back(std::move(iter->second)); + } + mapPacketLastUpdated.erase(nonce); + mapPartialPackets.erase(nonce); + GetMainSignals().PacketComplete(protocolId); +} + + +//////////////////////// +/// +/// Public +/// + +bool CPacketManager::BindBuffer(uint16_t protocolId, CPubKey authPubkey) +{ + if (mapBuffers.count(protocolId) != 0) + { + return false; + } + PacketBuffer newBuffer; + newBuffer.nProtocolId = protocolId; + newBuffer.boundPubkey = authPubkey; + mapBuffers.emplace(protocolId, std::move(newBuffer)); + return true; +} + +bool CPacketManager::ProcessPacketHeader(const uint64_t &nonce, CPacketHeader &newHeader) +{ + if (mapPartialPackets.find(nonce) != mapPartialPackets.end()) + { + return false; + } + if (mapBuffers.find(newHeader.nProtocolId) == mapBuffers.end()) + { + // protocolId needs to be bound by BindBuffer + return false; + } + CPacket newPacket(newHeader); + mapPartialPackets.emplace(nonce, std::move(newPacket)); + mapPacketLastUpdated.emplace(nonce, GetTime()); + return true; +} + +bool CPacketManager::ProcessDataSegment(const uint64_t &nonce, CPacketDataSegment newSegment) +{ + std::map::iterator updateIter; + std::map::iterator partialIter; + partialIter = mapPartialPackets.find(nonce); + updateIter = mapPacketLastUpdated.find(nonce); + if (partialIter == mapPartialPackets.end() || updateIter == mapPacketLastUpdated.end()) + { + return false; + } + if (!partialIter->second.InsertData(newSegment)) + { + return false; + } + updateIter->second = GetTime(); + if (partialIter->second.IsComplete()) + { + FinalizePacket(nonce, partialIter); + } + return true; +} + +void CPacketManager::CheckForTimeouts() +{ + // TODO : implement a thread to check for packet timeouts once a minute, + // a timeout is any partial packet that hasnt been updated in 30 seconds or more +} + +bool CPacketManager::SendPacket(const std::vector &vPubKey, const uint8_t &nProtocolId, const uint8_t &nProtocolVersion, const std::vector vData) +{ + NodeId peerNode; + if (!g_aodvtable.GetKeyNode(vPubKey, peerNode)) + { + return false; + } + CPubKey searchKey(vPubKey); + CPacket newPacket(nProtocolId, nProtocolVersion); + newPacket.PushBackData(vData); + + uint64_t nonce = 0; + while (nonce == 0) + { + GetRandBytes((uint8_t *)&nonce, sizeof(nonce)); + } + // segments might not be needed. it is a good way to keep message sizes low to prevent a DOS by sending someone an infinitely + // large message but might now be necessary + std::vector segments = newPacket.GetSegments(); + { + LOCK(cs_main); + g_connman->PushMessageToId(peerNode, NetMsgType::SPH, nonce, searchKey, newPacket.GetHeader()); + for (auto segment : segments) + { + g_connman->PushMessageToId(peerNode, NetMsgType::SPD, nonce, searchKey, segment); + } + } + return true; +} + +bool CPacketManager::GetBuffer(uint8_t &protocolId, std::vector &bufferData, const std::string &sig) +{ + if (mapBuffers.count(protocolId) == 1) + { + PacketBuffer buffer = mapBuffers[protocolId]; + bool fInvalid = false; + std::vector vchSig = DecodeBase64(sig.c_str(), &fInvalid); + if (fInvalid) + { + return false; + } + CHashWriter ss(SER_GETHASH, 0); + ss << std::string("GetBUfferRequest:"); + std::string requestMessage = std::to_string(protocolId) + std::to_string(buffer.requestCount); + ss << requestMessage; + CPubKey pubkey; + if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) + { + return false; + } + if (pubkey.GetID() == buffer.boundPubkey.GetID()) + { + return false; + } + bufferData = buffer.vRecievedPackets; + mapBuffers[protocolId].vRecievedPackets.clear(); + return true; + } + return false; +} diff --git a/src/net/packetmanager.h b/src/net/packetmanager.h index 805fc1ec..49d5ebe7 100644 --- a/src/net/packetmanager.h +++ b/src/net/packetmanager.h @@ -27,6 +27,12 @@ struct PacketBuffer std::vector vRecievedPackets; // the protocol id using this buffer uint16_t nProtocolId; + // the token needed for authentication to read vRecievedPackets + // TODO : use a different token method because this one is very expensive to use often + CPubKey boundPubkey; + // used in the request buffer method for authentication + uint64_t requestCount; + }; class CPacketManager @@ -34,7 +40,7 @@ class CPacketManager // Data members private: // protocolId : Buffer - std::map mapBuffers; + std::map mapBuffers; // partial packets waiting for all required data segments to reconstruct // map stores nonce, time and when packet is complete it is removed from this // map and stored in our messages vector @@ -50,23 +56,7 @@ class CPacketManager private: // disallow copies CPacketManager(const CPacketManager &pman){} - void FinalizePacket(const uint64_t &nonce, std::map::iterator iter) - { - uint8_t &protocolId = iter->second.nProtocolId; - if (mapBuffers.count(protocolId) == 0) - { - PacketBuffer newBuffer; - newBuffer.vRecievedPackets.push_back(std::move(iter->second)); - mapBuffers.emplace(protocolId, std::move(newBuffer)); - } - else - { - mapBuffers[protocolId].vRecievedPackets.push_back(std::move(iter->second)); - } - mapPacketLastUpdated.erase(nonce); - mapPartialPackets.erase(nonce); - GetMainSignals().PacketComplete(protocolId); - } + void FinalizePacket(const uint64_t &nonce, std::map::iterator iter); public: CPacketManager() @@ -75,85 +65,17 @@ class CPacketManager mapPacketLastUpdated.clear(); mapPartialPackets.clear(); } + bool BindBuffer(uint16_t protocolId, CPubKey authPubkey); - bool ProcessPacketHeader(const uint64_t &nonce, CPacketHeader &newHeader) - { - if (mapPartialPackets.find(nonce) != mapPartialPackets.end()) - { - return false; - } - CPacket newPacket(newHeader); - mapPartialPackets.emplace(nonce, std::move(newPacket)); - mapPacketLastUpdated.emplace(nonce, GetTime()); - return true; - } + bool ProcessPacketHeader(const uint64_t &nonce, CPacketHeader &newHeader); - bool ProcessDataSegment(const uint64_t &nonce, CPacketDataSegment newSegment) - { - std::map::iterator updateIter; - std::map::iterator partialIter; - partialIter = mapPartialPackets.find(nonce); - updateIter = mapPacketLastUpdated.find(nonce); - if (partialIter == mapPartialPackets.end() || updateIter == mapPacketLastUpdated.end()) - { - return false; - } - if (!partialIter->second.InsertData(newSegment)) - { - return false; - } - updateIter->second = GetTime(); - if (partialIter->second.IsComplete()) - { - FinalizePacket(nonce, partialIter); - } - return true; - } + bool ProcessDataSegment(const uint64_t &nonce, CPacketDataSegment newSegment); - void CheckForTimeouts() - { - // TODO : implement a thread to check for packet timeouts once a minute, - // a timeout is any partial packet that hasnt been updated in 30 seconds or more - } + void CheckForTimeouts(); - bool SendPacket(const std::vector &vPubKey, const uint8_t &nProtocolId, const uint8_t &nProtocolVersion, const std::vector vData) - { - NodeId peerNode; - if (!g_aodvtable.GetKeyNode(vPubKey, peerNode)) - { - return false; - } - CPubKey searchKey(vPubKey); - CPacket newPacket(nProtocolId, nProtocolVersion); - newPacket.PushBackData(vData); - - uint64_t nonce = 0; - while (nonce == 0) - { - GetRandBytes((uint8_t *)&nonce, sizeof(nonce)); - } - std::vector segments = newPacket.GetSegments(); - { - LOCK(cs_main); - g_connman->PushMessageToId(peerNode, NetMsgType::SPH, nonce, searchKey, newPacket.GetHeader()); - for (auto segment : segments) - { - g_connman->PushMessageToId(peerNode, NetMsgType::SPD, nonce, searchKey, segment); - } - } - return true; - } + bool SendPacket(const std::vector &vPubKey, const uint8_t &nProtocolId, const uint8_t &nProtocolVersion, const std::vector vData); - bool GetBuffer(uint8_t &protocolId, PacketBuffer &buffer) - { - if (mapBuffers.count(protocolId) == 1) - { - buffer = mapBuffers[protocolId]; - mapBuffers[protocolId].vRecievedPackets.clear(); - return true; - } - return false; - } + bool GetBuffer(uint8_t &protocolId, std::vector &bufferData, const std::string &sig); }; extern CPacketManager g_packetman; diff --git a/src/rpc/rpcaodv.cpp b/src/rpc/rpcaodv.cpp index 96f1fd43..661deea2 100644 --- a/src/rpc/rpcaodv.cpp +++ b/src/rpc/rpcaodv.cpp @@ -262,18 +262,20 @@ UniValue getbuffer(const UniValue ¶ms, bool fHelp) "\nattempts to get the buffer for a network service protocol\n" "\nArguments:\n" "1. \"protocolId\" (number, required) The id of the protocol being requested\n" + "2. \"signature\" (string, required) The authentication signature required to request the buffer\n" "\nExamples:\n" + - HelpExampleCli("getbuffer", "1") + - HelpExampleRpc("getbuffer", "1") + HelpExampleCli("getbuffer", "1 \"BHcOxO9SxZshlmXffMFdJYuAXqusM3zVS7Ary66j5SiupLsnGeMONwmM/qG6zIEJpoGznWtmFFZ63mo5YXGWBcU=\"") + + HelpExampleRpc("getbuffer", "1, \"BHcOxO9SxZshlmXffMFdJYuAXqusM3zVS7Ary66j5SiupLsnGeMONwmM/qG6zIEJpoGznWtmFFZ63mo5YXGWBcU=\"") ); } uint8_t nProtocolId = (uint8_t)params[0].get_int(); - PacketBuffer buffer; + std::string sig = params[1].get_str(); + std::vector bufferData; UniValue obj(UniValue::VOBJ); - if (g_packetman.GetBuffer(nProtocolId, buffer)) + if (g_packetman.GetBuffer(nProtocolId, bufferData, sig)) { uint64_t counter = 0; - for (auto &entry: buffer.vRecievedPackets) + for (auto &entry: bufferData) { std::stringstream hexstream; hexstream << std::hex;