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; }
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); }
CVariant CKadNode::Store(bool bFull) const { CVariant Node; Node["PROT"] = m_Protocol; Node["NID"] = m_ID; CVariant Addr; for(AddressMap::const_iterator I = m_AddressMap.begin(); I != m_AddressMap.end(); I++) { if(bFull) Addr.Append(I->second.ToExtVariant()); else Addr.Append(I->second.ToVariant()); } Node["ADDR"] = Addr; Node["VER"] = m_Version; if(bFull) { Node["FSEN"] = m_uFirstSeen; Node["LSEN"] = m_uLastSeen; } return Node; }
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")); }
void CKadHandler::SendHello(CKadNode* pNode, CComChannel* pChannel, bool bReq) { SKadData* pData = pChannel->GetData<SKadData>(); CVariant Hello(CVariant::EMap); CVariant Addr; TMyAddressMap AddressMap = GetParent<CKademlia>()->Fwh()->AddrPool(); for(TMyAddressMap::const_iterator I = AddressMap.begin(); I != AddressMap.end(); I++) Addr.Append(I->second.ToVariant()); Hello["ADDR"] = Addr; pNode->SetLastHello(); if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRT")) LogLine(LOG_DEBUG, L"Sending 'Hello %s' to %s", bReq ? L"Request" : L"Response", pNode->GetID().ToHex().c_str()); pChannel->QueuePacket(bReq ? KAD_HELLO_REQUEST : KAD_HELLO_RESPONSE, Hello); }
void CKademlia::SaveNodes() { wstring ConfigPath = Cfg()->GetString("ConfigPath"); if(ConfigPath.empty()) return; NodeList Nodes = m_pRootZone->GetAllNodes(); CVariant NodeList; for (NodeList::iterator I = Nodes.begin(); I != Nodes.end(); I++) { CKadNode* pNode = *I; NodeList.Append(pNode->Store(true)); } CVariant NeoNodes; NeoNodes["Nodes"] = NodeList; NeoNodes["LastContact"] = m_pKadHandler->GetLastContact(); WriteFile(ConfigPath + L"NeoNodes.dat", NeoNodes); }
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; }
void CKadOperation::SendRequests(CKadNode* pNode, CComChannel* pChannel, SOpProgress* pProgress, bool bStateless) { CKadHandler* pHandler = GetParent<CKademlia>()->Handler(); CVariant Calls; if(m_pOperator) { const CKadOperator::TRequestMap& ResuestMap = m_pOperator->GetRequests(); for(CKadOperator::TRequestMap::const_iterator I = ResuestMap.begin(); I != ResuestMap.end(); I++) { CKadRequest* pRequest = I->second.pRequest; if(pProgress->Calls.insert(TStatusMap::value_type(pRequest->GetXID(), SOpStatus())).second) // check if we already dealed this task { CVariant Call; Call["FX"] = pRequest->GetName(); Call["ARG"] = pRequest->GetArguments(); Call["XID"] = pRequest->GetXID(); Calls.Append(Call); } } } else { for(TCallOpMap::const_iterator I = m_CallMap.begin(); I != m_CallMap.end(); I++) { CVariant Call = I->second.Call; if(pProgress->Calls.insert(TStatusMap::value_type(Call["XID"], SOpStatus())).second) // check if we already dealed this task Calls.Append(Call); } } if(Calls.Count() > 0) pHandler->SendExecuteReq(pNode, pChannel, this, Calls, bStateless); CVariant Stores; for(TStoreOpMap::const_iterator I = m_StoreMap.begin(); I != m_StoreMap.end(); I++) { if(pProgress->Stores.insert(TStatusMap::value_type(I->first, SOpStatus())).second) // check if we already dealed this task { CVariant Store; Store["XID"] = I->first; Store["PLD"] = I->second.Payload; Stores.Append(Store); } } if(Stores.Count() > 0) pHandler->SendStoreReq(pNode, pChannel, this, Stores, bStateless); CVariant Loads; for(TLoadOpMap::const_iterator I = m_LoadMap.begin(); I != m_LoadMap.end(); I++) { if(pProgress->Loads.insert(TStatusMap::value_type(I->first, SOpStatus())).second) // check if we already dealed this task { CVariant Load; Load["XID"] = I->first; Load["PATH"] = I->second.Path; Loads.Append(Load); } } if(Loads.Count() > 0) pHandler->SendLoadReq(pNode, pChannel, this, Loads, bStateless); }