CVariant CKademlia::StartLookup(const CUInt128& TargetID, const CVariant& CodeID, const TCallMap& Execute, const TStoreMap& Store, CPrivateKey* pStoreKey, const TLoadMap& Load , int Timeout, int HopLimit, int JumpCount, int SpreadCount, bool bTrace, const wstring& Name) { if(!m_pKadHandler) return CVariant(); if(!CodeID.IsValid() && Store.empty() && Load.empty()) { LogLine(LOG_ERROR, L"Attempted to start an empty Lookup"); return CVariant(); } CPointer<CKadTask> pLookup = new CKadTask(TargetID, m_pLookupManager); pLookup->SetName(Name); if(Timeout != -1) pLookup->SetTimeOut(Timeout); if(HopLimit != -1) pLookup->SetHopLimit(HopLimit); if(JumpCount != -1) pLookup->SetJumpCount(JumpCount); if(SpreadCount != -1) pLookup->SetSpreadCount(SpreadCount); if(bTrace) pLookup->EnableTrace(); if(pStoreKey) pLookup->SetStoreKey(pStoreKey); for(TStoreMap::const_iterator I = Store.begin(); I != Store.end(); I++) pLookup->Store(I->first, I->second.Path, I->second.Data); for(TLoadMap::const_iterator I = Load.begin(); I != Load.end(); I++) pLookup->Load(I->first, I->second.Path); if(CodeID.IsValid()) { if(!pLookup->SetupScript(CodeID)) { LogLine(LOG_ERROR, L"Attempted to start a smart lookup with an unavailable script: %s", ToHex(CodeID.GetData(), CodeID.GetSize()).c_str()); return CVariant(); } for(TCallMap::const_iterator I = Execute.begin(); I != Execute.end(); I++) pLookup->AddCall(I->second.Function, I->second.Parameters, I->first); } CVariant LookupID = m_pLookupManager->StartLookup(pLookup.Obj()); return LookupID; }
void CLookupProxy::LogReport(UINT Flags, const wstring& ErrorMessage, const string& Error, const CVariant& Trace) { CKadOperation::LogReport(Flags, ErrorMessage, Error, Trace); if(!Trace.IsValid()) // if the trace is valid its a remote report that means it wil be relayed automatically, send only local reports GetParent<CKademlia>()->Handler()->SendReportPkt(GetReturnChannel(), Flags, ErrorMessage, Error); }
CVariant CKadOperator::Init(const CVariant& InitParam) { ASSERT(m_pJSScript); // WARNING: this is a week pointer if(!m_pJSScript) return CVariant(); CKadOperation* pOperation = GetParent<CKadOperation>(); ASSERT(pOperation); if(CLookupProxy* pProxy = pOperation->Cast<CLookupProxy>()) { CJSKadNode* &JSKadNode = m_KadNodes[NULL]; // NULL means its the return node if(JSKadNode = (CJSKadNode*)m_pJSScript->SetObject(pProxy->GetReturnNode())) // Note: the instance handler for this object is persistent! JSKadNode->SetOperation(pOperation); } if(!m_pJSScript->Has("lookupAPI", "init")) return CVariant(); // nothing to do here CDebugScope Debug(m_pKadScript, pOperation); vector<CPointer<CObject> > Parameters; Parameters.push_back(pOperation); if(InitParam.IsValid()) Parameters.push_back(new CVariantPrx(InitParam)); CPointer<CObject> Return; m_pJSScript->Call(string("lookupAPI"), "init", Parameters, Return); if(CVariantPrx* pVariant = Return->Cast<CVariantPrx>()) return pVariant->GetCopy(); return CVariant(); }
bool CKademlia::InvokeScript(const CVariant& CodeID, const string& Function, const CVariant& Arguments, CVariant& Result, const CVariant& CallerID) { CKadScript* pKadScript = m_pKadEngine->GetScript(CodeID); if(!pKadScript) return false; CDebugScope Debug(pKadScript); vector<CPointer<CObject> > Parameters; Parameters.push_back(new CVariantPrx(Arguments)); if(CallerID.IsValid()) Parameters.push_back(new CVariantPrx(CallerID)); try { CJSScript* pScript = pKadScript->GetJSScript(true); CPointer<CObject> Return; pScript->Call(string("localAPI"), Function, Parameters, Return); if(CVariantPrx* pVariant = Return->Cast<CVariantPrx>()) Result = pVariant->GetCopy(); } catch(const CJSException& Exception) { pKadScript->LogReport(Exception.GetFlag(), Exception.GetLine(), Exception.GetError()); return false; } return true; }
bool CKadHandler::SendRelayRes(CKadNode* pNode, CComChannel* pChannel, const CVariant& Frame, const string& Error, const CVariant& Load) { CVariant RelayRes; CVariant FrameRes; if(Frame.Has("TID")) FrameRes["TID"] = Frame["TID"]; FrameRes["EID"] = Frame["EID"]; FrameRes["RID"] = Frame["RID"]; FrameRes["FID"] = Frame["FID"]; // peer to peer (local) ACK if(!Error.empty()) FrameRes["ERR"] = Error; if(Load.IsValid()) FrameRes["LOAD"] = Load; RelayRes["FRM"] = FrameRes; if(GetParent<CKademlia>()->Cfg()->GetBool("DebugRE")) LogLine(LOG_DEBUG, L"Sending 'Relay Response' to %s", pNode->GetID().ToHex().c_str()); return pChannel->QueuePacket(KAD_RELAY_RESPONSE, RelayRes); }
CKademlia::CKademlia(uint16 Port, bool bIPv6, const CVariant& Config, const string& Version) { m_Protocol = KAD_PROT_VER; if(!Version.empty()) m_Version += Version; else m_Version = "v " STR(KAD_PROT_MJR) "." STR(KAD_PROT_MIN); m_pConfig = new CKadConfig(this); if(Config.IsValid()) m_pConfig->Merge(Config); LoadData(); if(m_pKadKey->GetAlgorithm() == CAbstractKey::eUndefined) { m_pKadKey->SetAlgorithm(CAbstractKey::eECP); //m_pKadKey->GenerateKey("secp256r1"); // NIST: P-256 m_pKadKey->GenerateKey("brainpoolP256r1"); // dont trust NIST (NSA) curves, use brainpool LogLine(LOG_INFO, L"Generated new Private NodeKey"); SaveData(); } m_pSocket = new CSmartSocket(SEC2MS(Cfg()->GetInt("ConnectionTimeout")), this); CScoped<CPublicKey> pKey = m_pKadKey->PublicKey(); CUInt128 ID; CKadID::MakeID(pKey, ID.GetData(), ID.GetSize()); LogLine(LOG_INFO, L"Neo Kad ID: %s", ID.ToHex().c_str()); uint64 RecvKey; CAbstractKey::Fold(ID.GetData(), ID.GetSize(),(byte*)&RecvKey, sizeof(RecvKey)); m_pSocket->SetupCrypto(RecvKey, m_pKadKey); #ifdef _DEBUG LogLine(LOG_INFO, L"Socket PassKey is %I64u", RecvKey); #endif m_Port = 0; m_IPv4 = CAddress(CAddress::IPv4); m_IPv6 = CAddress(CAddress::IPv6); for(int i=Port; i < Port + 1000; i++) { CUTPSocketListner* pSocketListner = new CUTPSocketListner(m_pSocket); CUTPSocketListner* pSocketListnerV6 = bIPv6 ? new CUTPSocketListner(m_pSocket) : NULL; bool bV4 = pSocketListner->Bind(i, CAddress(CAddress::IPv4)); bool bV6 = !pSocketListnerV6 || pSocketListnerV6->Bind(i, CAddress(CAddress::IPv6)); if(bV4 && bV6) { m_pSocket->InstallListener(pSocketListner); if(pSocketListnerV6) m_pSocket->InstallListener(pSocketListnerV6); m_Port = i; break; } delete pSocketListner; delete pSocketListnerV6; } }