void CKadHandler::HandleNodeRes(const CVariant& NodeRes, CKadNode* pNode, CComChannel* pChannel) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRT")) LogLine(LOG_DEBUG, L"Recived 'Node Response' from %s", pNode->GetID().ToHex().c_str()); CVariant List = NodeRes["LIST"]; if(List.Count() > (uint32)GetParent<CKademlia>()->Cfg()->GetInt("NodeReqCount")) throw CException(LOG_ERROR, L"Node returned more nodes than requested (spam)"); SKadData* pData = pChannel->GetData<SKadData>(); // Note: if pData->pLookup is NULL this was just a bootstrap request NodeMap Nodes; for(uint32 i = 0; i<List.Count(); i++) { CPointer<CKadNode> pNewNode = new CKadNode(GetParent<CKademlia>()->Root()); pNewNode->Load(List.At(i)); if(GetParent<CKademlia>()->Root()->AddNode(pNewNode) && pData->pLookup) { CUInt128 uDistance = pData->pLookup->GetID() ^ pNewNode->GetID(); Nodes.insert(NodeMap::value_type(uDistance, pNewNode)); } } if(pData->pLookup) GetParent<CKademlia>()->Manager()->AddNodes(pData->pLookup, pNode, pChannel, Nodes); }
void CLookupHistory::RecivedTraceResults(const CVariant& Trace) { if(Trace.Count() < 1) return; CUInt128 PrevID = Trace.At(Trace.Count()-1); for(int i=Trace.Count()-2; i >= 0; i--) { CUInt128 CurID = Trace.At(i); RecivedTraceResults(CurID, PrevID); PrevID = CurID; } }
CVariant CLookupProxy::AddCallReq(const CVariant& Requests) { CVariant Results(CVariant::EList); for(uint32 i=0; i<Requests.Count(); i++) { const CVariant& Request = Requests[i]; if(!m_CallMap.insert(TCallOpMap::value_type(Request["XID"], SCallOp(Request))).second) continue; // we already got this request, ignore it if(m_pOperator && m_pOperator->IsValid()) { try { m_pOperator->AddCallReq(Request["FX"], Request["ARG"], Request["XID"]); } catch(const CJSException& Exception) { LogReport(Exception.GetFlag(), Exception.GetLine(), Exception.GetError()); CKadOperation::SOpStatus &Progress = m_CallMap[Request["XID"]].Status; Progress.Done = true; // this one is finished CVariant Result; Result["XID"] = Request["XID"]; Result["ERR"] = Exception.GetError(); Results.Append(Result); } } } if(m_pOperator) Results.Merge(m_pOperator->GetResponses()); return Results; }
void CKadOperation::LogReport(UINT Flags, const wstring& ErrorMessage, const string& Error, const CVariant& Trace) { wstring Operation = L"Kad Operation"; if(m_pOperator) { CKadScript* pKadScript = m_pOperator->GetScript(); ASSERT(pKadScript); Operation += L" (" + pKadScript->GetName() + L" v" + CKadScript::GetVersion(pKadScript->GetVersion()) + L")"; } if(Trace.Count() > 0) // remote result { wstring Sender = CUInt128(Trace.At((uint32)0)).ToHex(); if(!Error.empty()) LogLine(LOG_DEBUG | Flags, L"%s recived an Error: %s from %s", Operation.c_str(), ErrorMessage.c_str(), Sender.c_str()); else LogLine(LOG_DEBUG | Flags, L"%s recived a Report: %s from %s", Operation.c_str(), ErrorMessage.c_str(), Sender.c_str()); } else { if(!Error.empty()) LogLine(LOG_DEBUG | Flags, L"%s caused an Error: %s", Operation.c_str(), ErrorMessage.c_str()); else LogLine(LOG_DEBUG | Flags, L"%s Reports: %s", Operation.c_str(), ErrorMessage.c_str()); } }
bool CKadOperator::CallLoadClBk(const CVariant& XID, const CVariant& Payloads) { map<CVariant, uint32>::iterator I = m_LoadClBks.find(XID); if(I == m_LoadClBks.end()) return false; if(I->second == 0) return true; ASSERT(m_pJSScript); // WARNING: this is a week pointer if(!m_pJSScript) return false; CKadOperation* pOperation = GetParent<CKadOperation>(); ASSERT(pOperation); CDebugScope Debug(m_pKadScript, pOperation); for(uint32 j=0; j < Payloads.Count(); j++) { const CVariant& Payload = Payloads[j]; vector<CPointer<CObject> > Parameters; Parameters.push_back(pOperation); // lookup Parameters.push_back(new CVariantPrx(Payload["DATA"])); Parameters.push_back(new CVariantPrx(Payload["PATH"])); Parameters.push_back(new CVariantPrx(Payload["RELD"])); CPointer<CObject> Return; m_pJSScript->Callback(I->second, Parameters, Return, false, pOperation); } return true; }
void CKadHandler::HandleHello(const CVariant& Hello, CKadNode* pNode, CComChannel* pChannel, bool bReq) { if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRT")) LogLine(LOG_DEBUG, L"Recived 'Hello %s' to %s", bReq ? L"Request" : L"Response", pNode->GetID().ToHex().c_str()); SKadData* pData = pChannel->GetData<SKadData>(); CVariant Addr = Hello["ADDR"]; vector<CNodeAddress> AuthAddress; for(uint32 i=0; i < Addr.Count(); i++) { AuthAddress.push_back(CNodeAddress()); AuthAddress.back().FromVariant(Addr.At(i)); } // update node addresses for(vector<CNodeAddress>::iterator I = AuthAddress.begin(); I != AuthAddress.end(); I++) { if(pData->Authenticated) I->SetVerifyed(); pNode->UpdateAddress(*I); } if(bReq) SendHello(pNode, pChannel, false); SetLastContact(); pNode->UpdateClass(true, pChannel->GetAddress()); }
void CKadNode::Load(const CVariant& Node, bool bFull) { m_Protocol = Node["PROT"]; m_ID.SetValue(CUInt128(Node["NID"])); CVariant Addr = Node["ADDR"]; for(uint32 i=0; i < Addr.Count(); i++) { CNodeAddress Address; if(bFull) Address.FromExtVariant(Addr.At(i)); else Address.FromVariant(Addr.At(i)); InsertAddress(Address); } if(bFull) { m_Version = Node["VER"].To<string>(); m_uFirstSeen = Node["FSEN"]; m_uLastSeen = Node["LSEN"]; if(IsFading()) { for(AddressMap::iterator I = m_AddressMap.begin(); I != m_AddressMap.end(); I++) I->second.SetClass(NODE_DEFAULT_CLASS); m_uLastSeen = GetTime(); } } }
void CLookupProxy::AddLoadReq(const CVariant& LoadReq) { for(int i=0; i < LoadReq.Count(); i++) { const CVariant& Load = LoadReq.At(i); if(!m_LoadMap.insert(TLoadOpMap::value_type(Load["XID"], SLoadOp(Load["PATH"]))).second) continue; } }
void CLookupProxy::AddStoreReq(const CVariant& StoreReq) { for(int i=0; i < StoreReq.Count(); i++) { const CVariant& Store = StoreReq.At(i); if(!m_StoreMap.insert(TStoreOpMap::value_type(Store["XID"], SStoreOp(Store["PLD"]))).second) continue; } }
void CLookupProxy::FlushCaches() { if(m_pOperator) { CVariant Results = m_pOperator->GetResponses(); if(Results.Count() > 0) GetParent<CKademlia>()->Handler()->SendExecuteRes(this, Results); } }
CVariant CKadScript::Execute(const CVariant& Requests, const CUInt128& TargetID, CReportLogger* pLogger) { KeepAlive(); m_pLogger = CPointer<CReportLogger>(pLogger, true); // this is a week pointer and it gets cleared when the caller exits CVariant Results(CVariant::EList); for(uint32 i=0; i < Requests.Count(); i++) { const CVariant& Request = Requests.At(i); Results.Append(Call(Request["FX"], Request["ARG"], TargetID, Request["XID"])); } return Results; }
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); }