Browse Source

generic address for AdressBook

pull/1334/head
orignal 5 years ago
parent
commit
baee6a0d91
  1. 115
      libi2pd_client/AddressBook.cpp
  2. 28
      libi2pd_client/AddressBook.h
  3. 8
      libi2pd_client/SAM.cpp

115
libi2pd_client/AddressBook.cpp

@ -40,9 +40,9 @@ namespace client
void RemoveAddress (const i2p::data::IdentHash& ident); void RemoveAddress (const i2p::data::IdentHash& ident);
bool Init (); bool Init ();
int Load (std::map<std::string, i2p::data::IdentHash>& addresses); int Load (std::map<std::string, std::shared_ptr<Address> > & addresses);
int LoadLocal (std::map<std::string, i2p::data::IdentHash>& addresses); int LoadLocal (std::map<std::string, std::shared_ptr<Address> >& addresses);
int Save (const std::map<std::string, i2p::data::IdentHash>& addresses); int Save (const std::map<std::string, std::shared_ptr<Address> >& addresses);
void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified); void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified);
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified); bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
@ -50,7 +50,7 @@ namespace client
private: private:
int LoadFromFile (const std::string& filename, std::map<std::string, i2p::data::IdentHash>& addresses); // returns -1 if can't open file, otherwise number of records int LoadFromFile (const std::string& filename, std::map<std::string, std::shared_ptr<Address> >& addresses); // returns -1 if can't open file, otherwise number of records
private: private:
@ -125,7 +125,7 @@ namespace client
storage.Remove( ident.ToBase32() ); storage.Remove( ident.ToBase32() );
} }
int AddressBookFilesystemStorage::LoadFromFile (const std::string& filename, std::map<std::string, i2p::data::IdentHash>& addresses) int AddressBookFilesystemStorage::LoadFromFile (const std::string& filename, std::map<std::string, std::shared_ptr<Address> >& addresses)
{ {
int num = 0; int num = 0;
std::ifstream f (filename, std::ifstream::in); // in text mode std::ifstream f (filename, std::ifstream::in); // in text mode
@ -144,16 +144,14 @@ namespace client
std::string name = s.substr(0, pos++); std::string name = s.substr(0, pos++);
std::string addr = s.substr(pos); std::string addr = s.substr(pos);
i2p::data::IdentHash ident; addresses[name] = std::make_shared<Address>(addr);
ident.FromBase32 (addr);
addresses[name] = ident;
num++; num++;
} }
} }
return num; return num;
} }
int AddressBookFilesystemStorage::Load (std::map<std::string, i2p::data::IdentHash>& addresses) int AddressBookFilesystemStorage::Load (std::map<std::string, std::shared_ptr<Address> >& addresses)
{ {
int num = LoadFromFile (indexPath, addresses); int num = LoadFromFile (indexPath, addresses);
if (num < 0) if (num < 0)
@ -167,7 +165,7 @@ namespace client
return num; return num;
} }
int AddressBookFilesystemStorage::LoadLocal (std::map<std::string, i2p::data::IdentHash>& addresses) int AddressBookFilesystemStorage::LoadLocal (std::map<std::string, std::shared_ptr<Address> >& addresses)
{ {
int num = LoadFromFile (localPath, addresses); int num = LoadFromFile (localPath, addresses);
if (num < 0) return 0; if (num < 0) return 0;
@ -175,7 +173,7 @@ namespace client
return num; return num;
} }
int AddressBookFilesystemStorage::Save (const std::map<std::string, i2p::data::IdentHash>& addresses) int AddressBookFilesystemStorage::Save (const std::map<std::string, std::shared_ptr<Address> >& addresses)
{ {
if (addresses.empty()) { if (addresses.empty()) {
LogPrint(eLogWarning, "Addressbook: not saving empty addressbook"); LogPrint(eLogWarning, "Addressbook: not saving empty addressbook");
@ -190,9 +188,14 @@ namespace client
return 0; return 0;
} }
for (const auto& it: addresses) { for (const auto& it: addresses)
f << it.first << "," << it.second.ToBase32 () << std::endl; {
num++; if (it.second->IsIdentHash ())
{
f << it.first << "," << it.second->identHash.ToBase32 () << std::endl;
num++;
}
// TODO: save blinded public key
} }
LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved"); LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved");
return num; return num;
@ -232,6 +235,27 @@ namespace client
} }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
Address::Address (const std::string& b32)
{
if (b32.length () <= B33_ADDRESS_THRESHOLD)
{
addressType = eAddressIndentHash;
identHash.FromBase32 (b32);
}
else
{
addressType = eAddressBlindedPublicKey;
blindedPublicKey = std::make_shared<i2p::data::BlindedPublicKey>(b32);
}
}
Address::Address (const i2p::data::IdentHash& hash)
{
addressType = eAddressIndentHash;
identHash = hash;
}
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false), AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
{ {
@ -296,19 +320,29 @@ namespace client
auto pos = address.find(".b32.i2p"); auto pos = address.find(".b32.i2p");
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
Base32ToByteStream (address.c_str(), pos, ident, 32); if (pos <= B33_ADDRESS_THRESHOLD)
return true; {
Base32ToByteStream (address.c_str(), pos, ident, 32);
return true;
}
else
return false;
} }
else else
{ {
pos = address.find (".i2p"); pos = address.find (".i2p");
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
auto identHash = FindAddress (address); auto addr = FindAddress (address);
if (identHash) if (addr)
{ {
ident = *identHash; if (addr->IsIdentHash ())
return true; {
ident = addr->identHash;
return true;
}
else
return false;
} }
else else
{ {
@ -325,11 +359,11 @@ namespace client
return true; return true;
} }
const i2p::data::IdentHash * AddressBook::FindAddress (const std::string& address) std::shared_ptr<const Address> AddressBook::FindAddress (const std::string& address)
{ {
auto it = m_Addresses.find (address); auto it = m_Addresses.find (address);
if (it != m_Addresses.end ()) if (it != m_Addresses.end ())
return &it->second; return it->second;
return nullptr; return nullptr;
} }
@ -338,16 +372,16 @@ namespace client
auto ident = std::make_shared<i2p::data::IdentityEx>(); auto ident = std::make_shared<i2p::data::IdentityEx>();
ident->FromBase64 (base64); ident->FromBase64 (base64);
m_Storage->AddAddress (ident); m_Storage->AddAddress (ident);
m_Addresses[address] = ident->GetIdentHash (); m_Addresses[address] = std::make_shared<Address>(ident->GetIdentHash ());
LogPrint (eLogInfo, "Addressbook: added ", address," -> ", ToAddress(ident->GetIdentHash ())); LogPrint (eLogInfo, "Addressbook: added ", address," -> ", ToAddress(ident->GetIdentHash ()));
} }
void AddressBook::InsertAddress (std::shared_ptr<const i2p::data::IdentityEx> address) void AddressBook::InsertFullAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
{ {
m_Storage->AddAddress (address); m_Storage->AddAddress (address);
} }
std::shared_ptr<const i2p::data::IdentityEx> AddressBook::GetAddress (const std::string& address) std::shared_ptr<const i2p::data::IdentityEx> AddressBook::GetFullAddress (const std::string& address)
{ {
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
if (!GetIdentHash (address, ident)) return nullptr; if (!GetIdentHash (address, ident)) return nullptr;
@ -408,16 +442,16 @@ namespace client
auto it = m_Addresses.find (name); auto it = m_Addresses.find (name);
if (it != m_Addresses.end ()) // already exists ? if (it != m_Addresses.end ()) // already exists ?
{ {
if (it->second != ident->GetIdentHash ()) // address changed? if (it->second->IsIdentHash () && it->second->identHash != ident->GetIdentHash ()) // address changed?
{ {
it->second = ident->GetIdentHash (); it->second->identHash = ident->GetIdentHash ();
m_Storage->AddAddress (ident); m_Storage->AddAddress (ident);
LogPrint (eLogInfo, "Addressbook: updated host: ", name); LogPrint (eLogInfo, "Addressbook: updated host: ", name);
} }
} }
else else
{ {
m_Addresses.insert (std::make_pair (name, ident->GetIdentHash ())); m_Addresses.emplace (name, std::make_shared<Address>(ident->GetIdentHash ()));
m_Storage->AddAddress (ident); m_Storage->AddAddress (ident);
if (is_update) if (is_update)
LogPrint (eLogInfo, "Addressbook: added new host: ", name); LogPrint (eLogInfo, "Addressbook: added new host: ", name);
@ -472,32 +506,33 @@ namespace client
void AddressBook::LoadLocal () void AddressBook::LoadLocal ()
{ {
std::map<std::string, i2p::data::IdentHash> localAddresses; std::map<std::string, std::shared_ptr<Address>> localAddresses;
m_Storage->LoadLocal (localAddresses); m_Storage->LoadLocal (localAddresses);
for (const auto& it: localAddresses) for (const auto& it: localAddresses)
{ {
if (!it.second->IsIdentHash ()) continue; // skip blinded for now
auto dot = it.first.find ('.'); auto dot = it.first.find ('.');
if (dot != std::string::npos) if (dot != std::string::npos)
{ {
auto domain = it.first.substr (dot + 1); auto domain = it.first.substr (dot + 1);
auto it1 = m_Addresses.find (domain); // find domain in our addressbook auto it1 = m_Addresses.find (domain); // find domain in our addressbook
if (it1 != m_Addresses.end ()) if (it1 != m_Addresses.end () && it1->second->IsIdentHash ())
{ {
auto dest = context.FindLocalDestination (it1->second); auto dest = context.FindLocalDestination (it1->second->identHash);
if (dest) if (dest)
{ {
// address is ours // address is ours
std::shared_ptr<AddressResolver> resolver; std::shared_ptr<AddressResolver> resolver;
auto it2 = m_Resolvers.find (it1->second); auto it2 = m_Resolvers.find (it1->second->identHash);
if (it2 != m_Resolvers.end ()) if (it2 != m_Resolvers.end ())
resolver = it2->second; // resolver exists resolver = it2->second; // resolver exists
else else
{ {
// create new resolver // create new resolver
resolver = std::make_shared<AddressResolver>(dest); resolver = std::make_shared<AddressResolver>(dest);
m_Resolvers.insert (std::make_pair(it1->second, resolver)); m_Resolvers.insert (std::make_pair(it1->second->identHash, resolver));
} }
resolver->AddAddress (it.first, it.second); resolver->AddAddress (it.first, it.second->identHash);
} }
} }
} }
@ -627,11 +662,11 @@ namespace client
void AddressBook::LookupAddress (const std::string& address) void AddressBook::LookupAddress (const std::string& address)
{ {
const i2p::data::IdentHash * ident = nullptr; std::shared_ptr<const Address> addr;
auto dot = address.find ('.'); auto dot = address.find ('.');
if (dot != std::string::npos) if (dot != std::string::npos)
ident = FindAddress (address.substr (dot + 1)); addr = FindAddress (address.substr (dot + 1));
if (!ident) if (!addr || !addr->IsIdentHash ()) // TODO:
{ {
LogPrint (eLogError, "Addressbook: Can't find domain for ", address); LogPrint (eLogError, "Addressbook: Can't find domain for ", address);
return; return;
@ -649,14 +684,14 @@ namespace client
std::unique_lock<std::mutex> l(m_LookupsMutex); std::unique_lock<std::mutex> l(m_LookupsMutex);
m_Lookups[nonce] = address; m_Lookups[nonce] = address;
} }
LogPrint (eLogDebug, "Addressbook: Lookup of ", address, " to ", ident->ToBase32 (), " nonce=", nonce); LogPrint (eLogDebug, "Addressbook: Lookup of ", address, " to ", addr->identHash.ToBase32 (), " nonce=", nonce);
size_t len = address.length () + 9; size_t len = address.length () + 9;
uint8_t * buf = new uint8_t[len]; uint8_t * buf = new uint8_t[len];
memset (buf, 0, 4); memset (buf, 0, 4);
htobe32buf (buf + 4, nonce); htobe32buf (buf + 4, nonce);
buf[8] = address.length (); buf[8] = address.length ();
memcpy (buf + 9, address.c_str (), address.length ()); memcpy (buf + 9, address.c_str (), address.length ());
datagram->SendDatagramTo (buf, len, *ident, ADDRESS_RESPONSE_DATAGRAM_PORT, ADDRESS_RESOLVER_DATAGRAM_PORT); datagram->SendDatagramTo (buf, len, addr->identHash, ADDRESS_RESPONSE_DATAGRAM_PORT, ADDRESS_RESOLVER_DATAGRAM_PORT);
delete[] buf; delete[] buf;
} }
} }
@ -686,7 +721,7 @@ namespace client
// TODO: verify from // TODO: verify from
i2p::data::IdentHash hash(buf + 8); i2p::data::IdentHash hash(buf + 8);
if (!hash.IsZero ()) if (!hash.IsZero ())
m_Addresses[address] = hash; m_Addresses[address] = std::make_shared<Address>(hash);
else else
LogPrint (eLogInfo, "AddressBook: Lookup response: ", address, " not found"); LogPrint (eLogInfo, "AddressBook: Lookup response: ", address, " not found");
} }

28
libi2pd_client/AddressBook.h

@ -13,6 +13,7 @@
#include "Identity.h" #include "Identity.h"
#include "Log.h" #include "Log.h"
#include "Destination.h" #include "Destination.h"
#include "LeaseSet.h"
namespace i2p namespace i2p
{ {
@ -28,6 +29,19 @@ namespace client
const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;
const size_t B33_ADDRESS_THRESHOLD = 56; // characters
struct Address
{
enum { eAddressIndentHash, eAddressBlindedPublicKey } addressType;
i2p::data::IdentHash identHash;
std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey;
Address (const std::string& b32);
Address (const i2p::data::IdentHash& hash);
bool IsIdentHash () const { return addressType == eAddressIndentHash; };
};
inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); }
class AddressBookStorage // interface for storage class AddressBookStorage // interface for storage
@ -40,9 +54,9 @@ namespace client
virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0; virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0;
virtual bool Init () = 0; virtual bool Init () = 0;
virtual int Load (std::map<std::string, i2p::data::IdentHash>& addresses) = 0; virtual int Load (std::map<std::string, std::shared_ptr<Address> >& addresses) = 0;
virtual int LoadLocal (std::map<std::string, i2p::data::IdentHash>& addresses) = 0; virtual int LoadLocal (std::map<std::string, std::shared_ptr<Address> >& addresses) = 0;
virtual int Save (const std::map<std::string, i2p::data::IdentHash>& addresses) = 0; virtual int Save (const std::map<std::string, std::shared_ptr<Address> >& addresses) = 0;
virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0; virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0;
virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0; virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0;
@ -61,11 +75,11 @@ namespace client
void StartResolvers (); void StartResolvers ();
void Stop (); void Stop ();
bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident); bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident);
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const std::string& address); std::shared_ptr<const i2p::data::IdentityEx> GetFullAddress (const std::string& address);
const i2p::data::IdentHash * FindAddress (const std::string& address); std::shared_ptr<const Address> FindAddress (const std::string& address);
void LookupAddress (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 (const std::string& address, const std::string& base64); // for jump service
void InsertAddress (std::shared_ptr<const i2p::data::IdentityEx> address); void InsertFullAddress (std::shared_ptr<const i2p::data::IdentityEx> address);
bool LoadHostsFromStream (std::istream& f, bool is_update); bool LoadHostsFromStream (std::istream& f, bool is_update);
void DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified); void DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified);
@ -93,7 +107,7 @@ namespace client
private: private:
std::mutex m_AddressBookMutex; std::mutex m_AddressBookMutex;
std::map<std::string, i2p::data::IdentHash> m_Addresses; std::map<std::string, std::shared_ptr<Address> > m_Addresses;
std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver
std::mutex m_LookupsMutex; std::mutex m_LookupsMutex;
std::map<uint32_t, std::string> m_Lookups; // nonce -> address std::map<uint32_t, std::string> m_Lookups; // nonce -> address

8
libi2pd_client/SAM.cpp

@ -467,7 +467,7 @@ namespace client
size_t l = dest->FromBase64(destination); size_t l = dest->FromBase64(destination);
if (l > 0) if (l > 0)
{ {
context.GetAddressBook().InsertAddress(dest); context.GetAddressBook().InsertFullAddress(dest);
auto leaseSet = session->localDestination->FindLeaseSet(dest->GetIdentHash()); auto leaseSet = session->localDestination->FindLeaseSet(dest->GetIdentHash());
if (leaseSet) if (leaseSet)
Connect(leaseSet); Connect(leaseSet);
@ -615,7 +615,7 @@ namespace client
auto dest = session == nullptr ? context.GetSharedLocalDestination() : session->localDestination; auto dest = session == nullptr ? context.GetSharedLocalDestination() : session->localDestination;
if (name == "ME") if (name == "ME")
SendNamingLookupReply (dest->GetIdentity ()); SendNamingLookupReply (dest->GetIdentity ());
else if ((identity = context.GetAddressBook ().GetAddress (name)) != nullptr) else if ((identity = context.GetAddressBook ().GetFullAddress (name)) != nullptr)
SendNamingLookupReply (identity); SendNamingLookupReply (identity);
else if (context.GetAddressBook ().GetIdentHash (name, ident)) else if (context.GetAddressBook ().GetIdentHash (name, ident))
{ {
@ -654,7 +654,7 @@ namespace client
{ {
if (leaseSet) if (leaseSet)
{ {
context.GetAddressBook ().InsertAddress (leaseSet->GetIdentity ()); context.GetAddressBook ().InsertFullAddress (leaseSet->GetIdentity ());
SendNamingLookupReply (leaseSet->GetIdentity ()); SendNamingLookupReply (leaseSet->GetIdentity ());
} }
else else
@ -844,7 +844,7 @@ namespace client
m_SocketType = eSAMSocketTypeStream; m_SocketType = eSAMSocketTypeStream;
m_IsAccepting = false; m_IsAccepting = false;
m_Stream = stream; m_Stream = stream;
context.GetAddressBook ().InsertAddress (stream->GetRemoteIdentity ()); context.GetAddressBook ().InsertFullAddress (stream->GetRemoteIdentity ());
auto session = m_Owner.FindSession (m_ID); auto session = m_Owner.FindSession (m_ID);
if (session) if (session)
{ {

Loading…
Cancel
Save