From 215d39fc547e8159692e3a535967ad56091ec2b1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Mar 2016 10:31:47 -0400 Subject: [PATCH] address lookup --- AddressBook.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++-- AddressBook.h | 13 +++++- ClientContext.cpp | 2 + 3 files changed, 126 insertions(+), 6 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index f972d48f..e26ce024 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "Base.h" #include "util.h" #include "Identity.h" @@ -218,10 +219,17 @@ namespace client m_Storage->Init(); LoadHosts (); /* try storage, then hosts.txt, then download */ StartSubscriptions (); + StartLookups (); } + + void AddressBook::StartResolvers () + { + LoadLocal (); + } void AddressBook::Stop () { + StopLookups (); StopSubscriptions (); if (m_SubscriptionsUpdateTimer) { @@ -330,7 +338,6 @@ namespace client LoadHostsFromStream (f); m_IsLoaded = true; } - LoadLocal (); } void AddressBook::LoadHostsFromStream (std::istream& f) @@ -518,6 +525,94 @@ namespace client } } + void AddressBook::StartLookups () + { + auto dest = i2p::client::context.GetSharedLocalDestination (); + if (dest) + { + auto datagram = dest->GetDatagramDestination (); + if (!datagram) + datagram = dest->CreateDatagramDestination (); + datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + ADDRESS_RESPONSE_DATAGRAM_PORT); + } + } + + void AddressBook::StopLookups () + { + auto dest = i2p::client::context.GetSharedLocalDestination (); + if (dest) + { + auto datagram = dest->GetDatagramDestination (); + if (datagram) + datagram->ResetReceiver (ADDRESS_RESPONSE_DATAGRAM_PORT); + } + } + + void AddressBook::LookupAddress (const std::string& address) + { + const i2p::data::IdentHash * ident = nullptr; + auto dot = address.find ('.'); + if (dot != std::string::npos) + ident = FindAddress (address.substr (dot + 1)); + if (!ident) + { + LogPrint (eLogError, "AddressBook: Can't find domain for ", address); + return; + } + + auto dest = i2p::client::context.GetSharedLocalDestination (); + if (dest) + { + auto datagram = dest->GetDatagramDestination (); + if (datagram) + { + uint32_t nonce; + RAND_bytes ((uint8_t *)&nonce, 4); + { + std::unique_lock l(m_LookupsMutex); + m_Lookups[nonce] = address; + } + LogPrint (eLogDebug, "AddressBook: Lookup of ", address, " to ", ident->ToBase32 (), " nonce=", nonce); + size_t len = address.length () + 9; + uint8_t * buf = new uint8_t[len]; + memset (buf, 0, 4); + htobe32buf (buf + 4, nonce); + buf[8] = address.length (); + memcpy (buf + 9, address.c_str (), address.length ()); + datagram->SendDatagramTo (buf, len, *ident, ADDRESS_RESPONSE_DATAGRAM_PORT, ADDRESS_RESOLVER_DATAGRAM_PORT); + delete[] buf; + } + } + } + + void AddressBook::HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + if (len < 44) + { + LogPrint (eLogError, "AddressBook: Lookup response is too short ", len); + return; + } + uint32_t nonce = bufbe32toh (buf + 4); + LogPrint (eLogDebug, "AddressBook: Lookup response received from ", from.GetIdentHash ().ToBase32 (), " nonce=", nonce); + std::string address; + { + std::unique_lock l(m_LookupsMutex); + auto it = m_Lookups.find (nonce); + if (it != m_Lookups.end ()) + { + address = it->second; + m_Lookups.erase (it); + } + } + if (address.length () > 0) + { + // TODO: verify from + m_Addresses[address] = buf + 8; + } + } + AddressBookSubscription::AddressBookSubscription (AddressBook& book, const std::string& link): m_Book (book), m_Link (link) { @@ -701,20 +796,31 @@ namespace client } } + AddressResolver::~AddressResolver () + { + if (m_LocalDestination) + { + auto datagram = m_LocalDestination->GetDatagramDestination (); + if (datagram) + datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT); + } + } + void AddressResolver::HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { if (len < 9 || len < buf[8] + 9U) { - LogPrint (eLogError, "Address request is too short ", len); + LogPrint (eLogError, "AddressBook: Address request is too short ", len); return; } // read requested address uint8_t l = buf[8]; char address[255]; memcpy (address, buf + 9, l); - address[l] = 0; + address[l] = 0; + LogPrint (eLogDebug, "AddressBook: Address request ", address); // send response - uint8_t response[40]; + uint8_t response[44]; memset (response, 0, 4); // reserved memcpy (response + 4, buf + 4, 4); // nonce auto it = m_LocalAddresses.find (address); // address lookup @@ -722,7 +828,8 @@ namespace client memcpy (response + 8, it->second, 32); // ident else memset (response + 8, 0, 32); // not found - m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 40, from.GetIdentHash (), toPort, fromPort); + memset (response + 40, 0, 4); // set expiration time to zero + m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 44, from.GetIdentHash (), toPort, fromPort); } void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident) diff --git a/AddressBook.h b/AddressBook.h index 436e7c8b..24a7e151 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -25,6 +25,9 @@ namespace client const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second + const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; + const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; + inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } class AddressBookStorage // interface for storage @@ -54,10 +57,12 @@ namespace client AddressBook (); ~AddressBook (); void Start (); + void StartResolvers (); void Stop (); bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident); std::shared_ptr GetAddress (const std::string& address); const i2p::data::IdentHash * FindAddress (const std::string& address); + void LookupAddress (const std::string& address); void InsertAddress (const std::string& address, const std::string& base64); // for jump service void InsertAddress (std::shared_ptr address); @@ -80,11 +85,17 @@ namespace client void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode); + void StartLookups (); + void StopLookups (); + void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + private: std::mutex m_AddressBookMutex; std::map m_Addresses; std::map > m_Resolvers; // local destination->resolver + std::mutex m_LookupsMutex; + std::map m_Lookups; // nonce -> address AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; std::vector m_Subscriptions; @@ -111,12 +122,12 @@ namespace client // m_Etag must be surrounded by "" }; - const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; class AddressResolver { public: AddressResolver (std::shared_ptr destination); + ~AddressResolver (); void AddAddress (const std::string& name, const i2p::data::IdentHash& ident); private: diff --git a/ClientContext.cpp b/ClientContext.cpp index 8d675286..8c626b25 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -96,6 +96,8 @@ namespace client m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort); m_BOBCommandChannel->Start (); } + + m_AddressBook.StartResolvers (); } void ClientContext::Stop ()