diff --git a/AddressBook.cpp b/AddressBook.cpp index 22008294..f972d48f 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -330,8 +330,7 @@ namespace client LoadHostsFromStream (f); m_IsLoaded = true; } - // load local - m_Storage->LoadLocal (m_Addresses); + LoadLocal (); } void AddressBook::LoadHostsFromStream (std::istream& f) @@ -395,6 +394,40 @@ namespace client LogPrint (eLogError, "Addressbook: subscriptions already loaded"); } + void AddressBook::LoadLocal () + { + std::map localAddresses; + m_Storage->LoadLocal (localAddresses); + for (auto it: localAddresses) + { + auto dot = it.first.find ('.'); + if (dot != std::string::npos) + { + auto domain = it.first.substr (dot + 1); + auto it1 = m_Addresses.find (domain); // find domain in our addressbook + if (it1 != m_Addresses.end ()) + { + auto dest = context.FindLocalDestination (it1->second); + if (dest) + { + // address is ours + std::shared_ptr resolver; + auto it2 = m_Resolvers.find (it1->second); + if (it2 != m_Resolvers.end ()) + resolver = it2->second; // resolver exists + else + { + // create new resolver + resolver = std::make_shared(dest); + m_Resolvers.insert (std::make_pair(it1->second, resolver)); + } + resolver->AddAddress (it.first, it.second); + } + } + } + } + } + bool AddressBook::GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) { if (m_Storage) @@ -653,6 +686,50 @@ namespace client m_Book.LoadHostsFromStream (s); return true; } + + AddressResolver::AddressResolver (std::shared_ptr destination): + m_LocalDestination (destination) + { + if (m_LocalDestination) + { + auto datagram = m_LocalDestination->GetDatagramDestination (); + if (!datagram) + datagram = m_LocalDestination->CreateDatagramDestination (); + datagram->SetReceiver (std::bind (&AddressResolver::HandleRequest, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + 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); + return; + } + // read requested address + uint8_t l = buf[8]; + char address[255]; + memcpy (address, buf + 9, l); + address[l] = 0; + // send response + uint8_t response[40]; + memset (response, 0, 4); // reserved + memcpy (response + 4, buf + 4, 4); // nonce + auto it = m_LocalAddresses.find (address); // address lookup + if (it != m_LocalAddresses.end ()) + 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); + } + + void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident) + { + m_LocalAddresses[name] = ident; + } + } } diff --git a/AddressBook.h b/AddressBook.h index 98422fe1..436e7c8b 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -12,6 +12,7 @@ #include "Base.h" #include "Identity.h" #include "Log.h" +#include "Destination.h" namespace i2p { @@ -23,7 +24,7 @@ namespace client const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second - + inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } class AddressBookStorage // interface for storage @@ -45,6 +46,7 @@ namespace client }; class AddressBookSubscription; + class AddressResolver; class AddressBook { public: @@ -74,13 +76,15 @@ namespace client void LoadHosts (); void LoadSubscriptions (); + void LoadLocal (); void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode); private: std::mutex m_AddressBookMutex; - std::map m_Addresses, m_LocalAddresses; + std::map m_Addresses; + std::map > m_Resolvers; // local destination->resolver AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; std::vector m_Subscriptions; @@ -106,6 +110,24 @@ namespace client std::string m_Link, m_Etag, m_LastModified; // m_Etag must be surrounded by "" }; + + const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; + class AddressResolver + { + public: + + AddressResolver (std::shared_ptr destination); + void AddAddress (const std::string& name, const i2p::data::IdentHash& ident); + + private: + + void HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + + private: + + std::shared_ptr m_LocalDestination; + std::map m_LocalAddresses; + }; } }