void CKadHandler::HandleRouteReq(const CVariant& RouteReq, CKadNode* pNode, CComChannel* pChannel) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRU")) LogLine(LOG_DEBUG, L"Recived 'Route Resuest' from %s", pNode->GetID().ToHex().c_str()); CVariant RouteRes(CVariant::EMap); SKadData* pData = pChannel->GetData<SKadData>(); CPointer<CKadRelay> pRelay = pData->pLookup->Cast<CKadRelay>(); if(!pRelay) { if(!RouteReq.Has("TID")) // this is optional it is not send on a refresn throw CException(LOG_ERROR, L"Invalid Lookup Request"); if(pData->pLookup) throw CException(LOG_ERROR, L"Recived Route Resuest for a lookup that is not a CKadRelay"); CLookupManager* pLookupManager = GetParent<CKademlia>()->Manager(); pRelay = pLookupManager->GetRelayEx(RouteReq["EID"], RouteReq["TID"]); // find already existing relay for this Entity and target combination //ASSERT(pRelay == pLookupManager->GetLookup(RouteReq["LID"])->Cast<CKadRelay>()); // lookup ID should be consistent if(!pRelay) { pRelay = new CKadRelay(RouteReq["TID"], pLookupManager); if(pRelay->InitRelay(RouteReq)) // if false it means the lookup is invalid { pRelay->SetHopLimit(RouteReq.Get("JMPS")); pRelay->SetJumpCount(RouteReq.Get("HOPS")); pRelay->SetBrancheCount(RouteReq.Get("BRCH")); pRelay->SetLookupID(RouteReq["LID"]); pLookupManager->StartLookup(pRelay.Obj()); if(RouteReq.Has("TRACE")) pRelay->EnableTrace(); } } // For this cahnnel the relay was new, setup BC pData->pLookup = CPointer<CKadLookup>(pRelay, true); // weak pointer pChannel->AddUpLimit(pData->pLookup->GetUpLimit()); pChannel->AddDownLimit(pData->pLookup->GetDownLimit()); } string Error = pRelay->AddDownLink(pNode, pChannel); // add or update if(!Error.empty()) RouteRes["ERR"] = Error; if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRU")) LogLine(LOG_DEBUG, L"Sending 'Route Response' to %s", pNode->GetID().ToHex().c_str()); pChannel->QueuePacket(KAD_ROUTE_RESPONSE, RouteRes); }
CVariant CKadOperation::AddLoadRes(const CVariant& LoadRes, CKadNode* pNode) { SOpProgress* pProgress = GetProgress(pNode); CVariant FilteredRes = LoadRes.Clone(false); // Make a Shellow Copy const CVariant& LoadedList = LoadRes["RES"]; CVariant FilteredList; for(uint32 i=0; i < LoadedList.Count(); i++) { CVariant Loaded = LoadedList.At(i).Clone(false); // Make a Shellow Copy const CVariant& XID = Loaded["XID"]; // Counting if(pProgress) // might be NULL if we filter our own index response right now { SOpStatus &Status = pProgress->Loads[XID]; Status.Results++; if(!Loaded.Get("MORE")) Status.Done = true; // this marks that no more results are to be expected form this node } SOpStatus* pStatus = &m_LoadMap[XID].Status; pStatus->Results++; if(!pStatus->Done) pStatus->Done = IsDone(SOpProgress::GetLoads, XID); if(!pStatus->Done) Loaded.Insert("MORE", true); else Loaded.Remove("MORE"); // if(Loaded.Has("ERR")) { FilteredList.Append(Loaded); continue; } // Filtering CVariant UniquePayloads; const CVariant& Payloads = Loaded["PLD"]; for(uint32 j=0; j < Payloads.Count(); j++) { const CVariant& Payload = Payloads.At(j); if(m_LoadFilter[XID].insert(Payload["DATA"].GetFP()).second) UniquePayloads.Append(Payload); } // Note: we must add this even if UniquePayloads is empty or else we will misscount replys CVariant NewLoaded; NewLoaded["XID"] = XID; NewLoaded["PLD"] = UniquePayloads; FilteredList.Append(NewLoaded); // } FilteredRes.Insert("RES", FilteredList); return FilteredRes; }
bool CKadScript::LoadData(const wstring& Path) { CVariant Data; if(!ReadFile(Path, Data)) return false; try { m_LastUsed = Data["LastUsed"].To<uint64>(); if(!m_LastUsed) m_LastUsed = GetTime(); m_Data->Set(Data["Data"]); if(Data.Has("KEY")) { CVariant SecretKey = Data["KEY"]; if(SecretKey.Decrypt(GetParent<CKademlia>()->Root()->GetID().GetPrivateKey())) { m_SecretKey = new CAbstractKey; if(!m_SecretKey->SetKey(SecretKey.GetData(), SecretKey.GetSize())) m_SecretKey = NULL; } } m_Authentication = Data.Get("AUTH"); } catch(const CException&) { return false; } return true; }
void CKadHandler::HandleNodeReq(const CVariant& NodeReq, CKadNode* pNode, CComChannel* pChannel) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRT")) LogLine(LOG_DEBUG, L"Recived 'Node Resuest' to %s", pNode->GetID().ToHex().c_str()); CVariant NodeRes; uint32 uDesiredCount = NodeReq["RCT"]; if(uDesiredCount == 0) throw CException(LOG_ERROR, L"node requested 0 nodes"); int iMaxState = NodeReq.Get("MNC", NODE_2ND_CLASS); NodeMap Nodes; if(!NodeReq.Has("TID")) GetParent<CKademlia>()->Root()->GetBootstrapNodes(GetParent<CKademlia>()->Root()->GetID(), Nodes, uDesiredCount, pChannel->GetAddress().GetProtocol(), iMaxState); else GetParent<CKademlia>()->Root()->GetClosestNodes(NodeReq["TID"], Nodes, uDesiredCount, pChannel->GetAddress().GetProtocol(), iMaxState); CVariant List; for(NodeMap::iterator I = Nodes.begin(); I != Nodes.end(); I++) List.Append(I->second->Store()); NodeRes["LIST"] = List; if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRT")) LogLine(LOG_DEBUG, L"Sending 'Node Response' to %s", pNode->GetID().ToHex().c_str()); pChannel->QueuePacket(KAD_NODE_RESPONSE, NodeRes); }
void CKadHandler::HandleRouteRes(const CVariant& RouteRes, CKadNode* pNode, CComChannel* pChannel) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRU")) LogLine(LOG_DEBUG, L"Recived 'Route Response' from %s", pNode->GetID().ToHex().c_str()); SKadData* pData = pChannel->GetData<SKadData>(); CKadRelay* pRelay = pData->pLookup->Cast<CKadRelay>(); if(!pRelay) throw CException(LOG_ERROR, L"Recived Route Response for a lookup that is not a CKadRelay"); // Note: this is for trace only, it does not have any deeper purpose if(pRelay->IsTraced()) { CVariant Trace = RouteRes.Get("TRACE").Clone(); Trace.Append(pNode->GetID()); if(!pRelay->Inherits("CKadRoute")) // if its just a relay we have to relay the trace back { CVariant RouteRel; RouteRel["TID"] = RouteRes["TID"]; // pRelay->GetID() RouteRel["TRACE"] = Trace; if(CFrameRelay* pDownLink = pRelay->GetDownLink()) { CFrameRelay::TRelayMap& DownNodes = pDownLink->GetNodes(); for(CFrameRelay::TRelayMap::iterator I = DownNodes.begin(); I != DownNodes.end(); I++) { if(I->first.pChannel->IsConnected()) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugLU")) LogLine(LOG_DEBUG, L"Relaying 'Route Response' from %s to %s", pNode->GetID().ToHex().c_str(), I->first.pNode->GetID().ToHex().c_str()); I->first.pChannel->QueuePacket(KAD_ROUTE_RESPONSE, RouteRel); } } } } else pRelay->RecivedTraceResults(Trace); } if(RouteRes.Has("TRACE")) // if this is set its a pro forma trace response ignore it return; pRelay->UpLinkResponse(pNode, pChannel, RouteRes.Get("ERR")); }
CVariant CKadOperation::AddStoreRes(const CVariant& StoreRes, CKadNode* pNode) { SOpProgress* pProgress = GetProgress(pNode); CVariant FilteredRes = StoreRes.Clone(false); // Make a Shellow Copy const CVariant& StoredList = StoreRes["RES"]; CVariant FilteredList; for(uint32 i=0; i < StoredList.Count(); i++) { CVariant Stored = StoredList.At(i).Clone(false); // Make a Shellow Copy const CVariant& XID = Stored["XID"]; // Counting if(pProgress) // might be NULL if we filter our own index response right now { SOpStatus &Status = pProgress->Stores[XID]; Status.Results++; if(!Stored.Get("MORE")) Status.Done = true; // this marks that no more results are to be expected form this node } SOpStatus* pStatus = &m_StoreMap[XID].Status; pStatus->Results++; if(!pStatus->Done) pStatus->Done = IsDone(SOpProgress::GetStores, XID); if(!pStatus->Done) Stored.Insert("MORE", true); else Stored.Remove("MORE"); // //m_StoredCounter[Stored["XID"]].push_back(Stored.Get("EXP", 0)); // on error there is no EXP FilteredList.Append(Stored); } FilteredRes.Insert("RES", FilteredList); return FilteredRes; }
CVariant CKadOperation::AddCallRes(const CVariant& CallRes, CKadNode* pNode) { SOpProgress* pProgress = GetProgress(pNode); CVariant FilteredRes = CallRes.Clone(false); // Make a Shellow Copy const CVariant& Results = CallRes["RET"]; CVariant Filtered; for(uint32 i=0; i < Results.Count(); i++) { CVariant Result = Results.At(i).Clone(false); // Make a Shellow Copy const CVariant& XID = Result["XID"]; // this checks if this particular response is the last and and if this node is done if(pProgress) // might be NULL if we filter our own index response right now { SOpStatus &Status = pProgress->Calls[XID]; Status.Results++; if(!Result.Get("MORE")) Status.Done = true; // this marks that no more results are to be expected form this node } SOpStatus* pStatus = NULL; TCallOpMap::iterator I = m_CallMap.find(XID); if(I != m_CallMap.end()) { pStatus = &I->second.Status; pStatus->Results++; // count the response even if it gets filtered lateron if(!pStatus->Done) pStatus->Done = IsDone(SOpProgress::GetCalls, XID); } if(m_pOperator) { CKadOperator::TRequestMap& ResuestMap = m_pOperator->GetRequests(); CKadOperator::TRequestMap::iterator I = ResuestMap.find(XID); if(I != ResuestMap.end()) // this should not fail { SOpStatus* pAuxStatus = &I->second.Status; pAuxStatus->Results++; // count the response even if it gets filtered lateron if(!pAuxStatus->Done) pAuxStatus->Done = IsDone(SOpProgress::GetCalls, XID); } } if(!Result.Has("ERR")) { if(m_pOperator && m_pOperator->IsValid()) { try { if(m_pOperator->AddCallRes(Result["RET"], XID)) continue; // intercepted response - Note: if we add a response to this request now it wil be marked as no more results if thats so } catch(const CJSException& Exception) { LogReport(Exception.GetFlag(), Exception.GetLine(), Exception.GetError()); } } } //else // LogLine(LOG_ERROR | LOG_DEBUG, L"Got Execution Error %s", Result["ERR"].To<wstring>().c_str()); // check if this is a call we issued, that is one not present in the call map, in that case its never to be relayed if(pStatus) { // UpdateMore sets the "MORE" flag on the packet we relay further down to the source, and checks if we considder this request done if(!pStatus->Done) Result.Insert("MORE", true); else Result.Remove("MORE"); Filtered.Append(Result); } } if(m_pOperator) // add new result to the filtered list Filtered.Merge(m_pOperator->GetResponses()); FilteredRes.Insert("RET", Filtered); return FilteredRes; }
bool CKadHandler::ProcessPacket(const string& Name, const CVariant& Packet, CComChannel* pChannel) { CKadNode* pNode = NULL; try { // Process cahnnel initialisation if(Name == KAD_INIT) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugTL")) LogLine(LOG_DEBUG, L"Recived 'Transaction Init' from %s", CUInt128(Packet["NID"]).ToHex().c_str()); bool bAdded = false; SKadData* pData = pChannel->GetData<SKadData>(&bAdded); if(!pData->pNode) { pData->pNode = GetParent<CKademlia>()->Root()->GetNode(Packet["NID"]); if(!pData->pNode) { pData->pNode = new CKadNode(GetParent<CKademlia>()->Root()); pData->pNode->SetID(Packet["NID"]); GetParent<CKademlia>()->Root()->AddNode(pData->pNode); } pChannel->AddUpLimit(pData->pNode->GetUpLimit()); pChannel->AddDownLimit(pData->pNode->GetDownLimit()); } else if(pData->pNode->GetID() != Packet["NID"]) throw CException(LOG_ERROR, L"KadNode Miss Match"); // this should never ever happen! pData->pNode->SetProtocol(Packet["PROT"]); pData->pNode->SetVersion(Packet.Get("VER")); // Version is optional pData->Connected = true; if(bAdded) // if it was added it means its an incomming connectziona dnwe have to answer { SendInit(pData->pNode, pChannel); pData->pNode->UpdateAddress(pChannel->GetAddress()); // If this is incomming update addresses } return true; } else { if(SKadData* pData = pChannel->GetData<SKadData>()) pNode = pData->pNode; if(!pNode || !pNode->GetParent()) throw CException(LOG_WARNING, L"Kad Packet Recived %S on not initialized channel", Name.c_str()); } if(Name.compare(KAD_CRYPTO_REQUEST) == 0) HandleCryptoRequest(Packet, pNode, pChannel); else if(Name.compare(KAD_CRYPTO_RESPONSE) == 0) HandleCryptoResponse(Packet, pNode, pChannel); else if(Name.compare(KAD_HELLO_REQUEST) == 0) HandleHello(Packet, pNode, pChannel, true); else if(Name.compare(KAD_HELLO_RESPONSE) == 0) HandleHello(Packet, pNode, pChannel, false); else if(Name.compare(KAD_NODE_REQUEST) == 0) HandleNodeReq(Packet, pNode, pChannel); else if(Name.compare(KAD_NODE_RESPONSE) == 0) HandleNodeRes(Packet, pNode, pChannel); // Lookup Handling else if(Name.compare(KAD_PROXY_REQUEST) == 0) HandleProxyReq(Packet, pNode, pChannel); else if(Name.compare(KAD_PROXY_RESPONSE) == 0) HandleProxyRes(Packet, pNode, pChannel); else if(Name.compare(KAD_CODE_REQUEST) == 0) HandleCodeReq(Packet, pNode, pChannel); else if(Name.compare(KAD_CODE_RESPONSE) == 0) HandleCodeRes(Packet, pNode, pChannel); else if(Name.compare(KAD_LOOKUP_MESSAGE) == 0) HandleMessagePkt(Packet, pNode, pChannel); else if(Name.compare(KAD_EXECUTE_REQUEST) == 0) HandleExecuteReq(Packet, pNode, pChannel); else if(Name.compare(KAD_EXECUTE_RESPONSE) == 0) HandleExecuteRes(Packet, pNode, pChannel); else if(Name.compare(KAD_STORE_REQUEST) == 0) HandleStoreReq(Packet, pNode, pChannel); else if(Name.compare(KAD_STORE_RESPONSE) == 0) HandleStoreRes(Packet, pNode, pChannel); else if(Name.compare(KAD_LOAD_REQUEST) == 0) HandleLoadReq(Packet, pNode, pChannel); else if(Name.compare(KAD_LOAD_RESPONSE) == 0) HandleLoadRes(Packet, pNode, pChannel); else if(Name.compare(KAD_LOOKUP_REPORT) == 0) HandleReportPkt(Packet, pNode, pChannel); // Routing Handling else if(Name.compare(KAD_ROUTE_REQUEST) == 0) HandleRouteReq(Packet, pNode, pChannel); else if(Name.compare(KAD_ROUTE_RESPONSE) == 0) HandleRouteRes(Packet, pNode, pChannel); else if(Name.compare(KAD_RELAY_REQUEST) == 0) HandleRelayReq(Packet, pNode, pChannel); else if(Name.compare(KAD_RELAY_RESPONSE) == 0) HandleRelayRes(Packet, pNode, pChannel); else if(Name.compare(KAD_RELAY_RETURN) == 0) HandleRelayRet(Packet, pNode, pChannel); else if(Name.compare(KAD_RELAY_CONTROL) == 0) HandleRelayCtrl(Packet, pNode, pChannel); else if(Name.compare(KAD_RELAY_STATUS) == 0) HandleRelayStat(Packet, pNode, pChannel); else throw CException(LOG_WARNING, L"Unsupported Kad Packet Recived %S", Name.c_str()); } catch(const CException& Exception) { LogLine(Exception.GetFlag(), L"Packet \'%S\' Error: '%s' from: %s (%s)", Name.c_str(), Exception.GetLine().c_str(), pNode ? pNode->GetID().ToHex().c_str() : L"Unknown", pChannel->GetAddress().ToString().c_str()); pChannel->Close(); return false; } return true; }