Skip to content
This repository was archived by the owner on Feb 1, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/net/datapacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
Expand Down
146 changes: 146 additions & 0 deletions src/net/packetmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint64_t, CPacket>::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<uint64_t, int64_t>::iterator updateIter;
std::map<uint64_t, CPacket>::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<unsigned char> &vPubKey, const uint8_t &nProtocolId, const uint8_t &nProtocolVersion, const std::vector<uint8_t> 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<CPacketDataSegment> 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<CPacket> &bufferData, const std::string &sig)
{
if (mapBuffers.count(protocolId) == 1)
{
PacketBuffer buffer = mapBuffers[protocolId];
bool fInvalid = false;
std::vector<unsigned char> 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;
}
108 changes: 15 additions & 93 deletions src/net/packetmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@ struct PacketBuffer
// vRecievedPackets should be partially stored on disk at some point
std::vector<CPacket> vRecievedPackets;
// the protocol id using this buffer
uint8_t nProtocolId;
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
{
// Data members
private:
// protocolId : Buffer
std::map<uint8_t, PacketBuffer> mapBuffers;
std::map<uint16_t, PacketBuffer> 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
Expand All @@ -50,23 +56,7 @@ class CPacketManager
private:
// disallow copies
CPacketManager(const CPacketManager &pman){}
void FinalizePacket(const uint64_t &nonce, std::map<uint64_t, CPacket>::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<uint64_t, CPacket>::iterator iter);

public:
CPacketManager()
Expand All @@ -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<uint64_t, int64_t>::iterator updateIter;
std::map<uint64_t, CPacket>::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<unsigned char> &vPubKey, const uint8_t &nProtocolId, const uint8_t &nProtocolVersion, const std::vector<uint8_t> 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<CPacketDataSegment> 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<unsigned char> &vPubKey, const uint8_t &nProtocolId, const uint8_t &nProtocolVersion, const std::vector<uint8_t> 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<CPacket> &bufferData, const std::string &sig);
};

extern CPacketManager g_packetman;
Expand Down
12 changes: 7 additions & 5 deletions src/rpc/rpcaodv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,18 +262,20 @@ UniValue getbuffer(const UniValue &params, 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<CPacket> 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;
Expand Down