Browse Source

* i2p::fs migration: AddressBook.*

pull/388/head
hagen 9 years ago
parent
commit
ddd8d4aeb2
  1. 219
      AddressBook.cpp
  2. 2
      AddressBook.h

219
AddressBook.cpp

@ -5,11 +5,11 @@
#include <fstream> #include <fstream>
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "Base.h" #include "Base.h"
#include "util.h" #include "util.h"
#include "Identity.h" #include "Identity.h"
#include "FS.h"
#include "Log.h" #include "Log.h"
#include "NetDb.h" #include "NetDb.h"
#include "ClientContext.h" #include "ClientContext.h"
@ -19,143 +19,96 @@ namespace i2p
{ {
namespace client namespace client
{ {
// TODO: this is actually proxy class
class AddressBookFilesystemStorage: public AddressBookStorage class AddressBookFilesystemStorage: public AddressBookStorage
{ {
public: public:
AddressBookFilesystemStorage () {};
AddressBookFilesystemStorage ();
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const; std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const;
void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address); void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address);
void RemoveAddress (const i2p::data::IdentHash& ident); void RemoveAddress (const i2p::data::IdentHash& ident);
int Load (std::map<std::string, i2p::data::IdentHash>& addresses); int Load (std::map<std::string, i2p::data::IdentHash>& addresses);
int Save (const std::map<std::string, i2p::data::IdentHash>& addresses); int Save (const std::map<std::string, i2p::data::IdentHash>& addresses);
private:
boost::filesystem::path GetPath () const
{
return i2p::util::filesystem::GetDefaultDataDir() / "addressbook";
}
boost::filesystem::path GetAddressPath (const i2p::data::IdentHash& ident) const
{
auto b32 = ident.ToBase32();
return GetPath () / (std::string ("b") + b32[0]) / (b32 + ".b32");
}
}; };
AddressBookFilesystemStorage::AddressBookFilesystemStorage ()
{
auto path = GetPath ();
if (!boost::filesystem::exists (path))
{
// Create directory is necessary
if (!boost::filesystem::create_directory (path))
LogPrint (eLogError, "Addressbook: failed to create addressbook directory");
}
}
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const
{ {
auto filename = GetAddressPath (ident); std::string filename = i2p::fs::GetAddressBook().Path(ident.ToBase32());
if (!boost::filesystem::exists (filename)) std::ifstream f(filename, std::ifstream::binary);
{ if (!f.is_open ()) {
boost::filesystem::create_directory (filename.parent_path ()); LogPrint(eLogDebug, "Addressbook: Requested, but not found: ", filename);
// try to find in main folder return nullptr;
auto filename1 = GetPath () / (ident.ToBase32 () + ".b32");
if (!boost::filesystem::exists (filename1))
{
boost::system::error_code ec;
boost::filesystem::rename (filename1, filename, ec);
if (ec)
LogPrint (eLogError, "Addresbook: couldn't move file ", ec.message ());
}
else
return nullptr; // address doesn't exist
}
std::ifstream f(filename.string (), std::ifstream::binary);
if (f.is_open ())
{
f.seekg (0,std::ios::end);
size_t len = f.tellg ();
if (len < i2p::data::DEFAULT_IDENTITY_SIZE)
{
LogPrint (eLogError, "Addresbook: File ", filename, " is too short. ", len);
return nullptr;
}
f.seekg(0, std::ios::beg);
uint8_t * buf = new uint8_t[len];
f.read((char *)buf, len);
auto address = std::make_shared<i2p::data::IdentityEx>(buf, len);
delete[] buf;
return address;
} }
else
f.seekg (0,std::ios::end);
size_t len = f.tellg ();
if (len < i2p::data::DEFAULT_IDENTITY_SIZE) {
LogPrint (eLogError, "Addresbook: File ", filename, " is too short: ", len);
return nullptr; return nullptr;
}
f.seekg(0, std::ios::beg);
uint8_t * buf = new uint8_t[len];
f.read((char *)buf, len);
auto address = std::make_shared<i2p::data::IdentityEx>(buf, len);
delete[] buf;
return address;
} }
void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
{ {
auto filename = GetAddressPath (address->GetIdentHash ()); std::string path = i2p::fs::GetAddressBook().Path( address->GetIdentHash().ToBase32() );
std::ofstream f (filename.string (), std::ofstream::binary | std::ofstream::out); std::ofstream f (path, std::ofstream::binary | std::ofstream::out);
if (!f.is_open ()) if (!f.is_open ()) {
{ LogPrint (eLogError, "Addresbook: can't open file ", path);
// create subdirectory return;
if (boost::filesystem::create_directory (filename.parent_path ()))
f.open (filename.string (), std::ofstream::binary | std::ofstream::out); // and try to open again
}
if (f.is_open ())
{
size_t len = address->GetFullLen ();
uint8_t * buf = new uint8_t[len];
address->ToBuffer (buf, len);
f.write ((char *)buf, len);
delete[] buf;
} }
else size_t len = address->GetFullLen ();
LogPrint (eLogError, "Addresbook: can't open file ", filename); uint8_t * buf = new uint8_t[len];
address->ToBuffer (buf, len);
f.write ((char *)buf, len);
delete[] buf;
} }
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident) void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
{ {
auto filename = GetAddressPath (ident); i2p::fs::GetAddressBook().Remove( ident.ToBase32() );
if (boost::filesystem::exists (filename))
boost::filesystem::remove (filename);
} }
int AddressBookFilesystemStorage::Load (std::map<std::string, i2p::data::IdentHash>& addresses) int AddressBookFilesystemStorage::Load (std::map<std::string, i2p::data::IdentHash>& addresses)
{ {
int num = 0; int num = 0;
auto filename = GetPath () / "addresses.csv"; std::string s;
std::ifstream f (filename.string (), std::ifstream::in); // in text mode std::string index = i2p::fs::GetAddressBook().IndexPath();
if (f.is_open ()) std::ifstream f (index, std::ifstream::in); // in text mode
{
addresses.clear (); if (f.is_open ()) {
while (!f.eof ()) LogPrint(eLogInfo, "Addressbook: using index file ", index);
} else {
LogPrint(eLogWarning, "Addressbook: Can't open ", index);
return 0;
}
addresses.clear ();
while (!f.eof ()) {
getline(f, s);
if (!s.length())
continue; // skip empty line
std::size_t pos = s.find(',');
if (pos != std::string::npos)
{ {
std::string s; std::string name = s.substr(0, pos++);
getline(f, s); std::string addr = s.substr(pos);
if (!s.length())
continue; // skip empty line
size_t pos = s.find(','); i2p::data::IdentHash ident;
if (pos != std::string::npos) ident.FromBase32 (addr);
{ addresses[name] = ident;
std::string name = s.substr(0, pos++); num++;
std::string addr = s.substr(pos); }
i2p::data::IdentHash ident;
ident.FromBase32 (addr);
addresses[name] = ident;
num++;
}
}
LogPrint (eLogInfo, "Addressbook: ", num, " addresses loaded");
} }
else
LogPrint (eLogWarning, "Addressbook: ", filename, " not found"); LogPrint (eLogInfo, "Addressbook: ", num, " addresses loaded from storage");
return num; return num;
} }
@ -167,24 +120,24 @@ namespace client
} }
int num = 0; int num = 0;
auto filename = GetPath () / "addresses.csv"; std::string index = i2p::fs::GetAddressBook().IndexPath();
std::ofstream f (filename.string (), std::ofstream::out); // in text mode std::ofstream f (index, std::ofstream::out); // in text mode
if (f.is_open ())
{ if (!f.is_open ()) {
for (auto it: addresses) LogPrint (eLogWarning, "Addressbook: Can't open ", index);
{ return 0;
f << it.first << "," << it.second.ToBase32 () << std::endl; }
num++;
} for (auto it: addresses) {
LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved"); f << it.first << "," << it.second.ToBase32 () << std::endl;
num++;
} }
else LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved");
LogPrint (eLogError, "Addresbook: can't open file ", filename);
return num; return num;
} }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
AddressBook::AddressBook (): m_Storage (nullptr), m_IsLoaded (false), m_IsDownloading (false), AddressBook::AddressBook (): m_Storage(new AddressBookFilesystemStorage), m_IsLoaded (false), m_IsDownloading (false),
m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
{ {
} }
@ -239,11 +192,6 @@ namespace client
m_Subscriptions.clear (); m_Subscriptions.clear ();
} }
AddressBookStorage * AddressBook::CreateStorage ()
{
return new AddressBookFilesystemStorage ();
}
bool AddressBook::GetIdentHash (const std::string& address, i2p::data::IdentHash& ident) bool AddressBook::GetIdentHash (const std::string& address, i2p::data::IdentHash& ident)
{ {
auto pos = address.find(".b32.i2p"); auto pos = address.find(".b32.i2p");
@ -287,8 +235,6 @@ namespace client
{ {
auto ident = std::make_shared<i2p::data::IdentityEx>(); auto ident = std::make_shared<i2p::data::IdentityEx>();
ident->FromBase64 (base64); ident->FromBase64 (base64);
if (!m_Storage)
m_Storage = CreateStorage ();
m_Storage->AddAddress (ident); m_Storage->AddAddress (ident);
m_Addresses[address] = ident->GetIdentHash (); m_Addresses[address] = ident->GetIdentHash ();
LogPrint (eLogInfo, "Addressbook: added ", address," -> ", ToAddress(ident->GetIdentHash ())); LogPrint (eLogInfo, "Addressbook: added ", address," -> ", ToAddress(ident->GetIdentHash ()));
@ -296,15 +242,11 @@ namespace client
void AddressBook::InsertAddress (std::shared_ptr<const i2p::data::IdentityEx> address) void AddressBook::InsertAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
{ {
if (!m_Storage)
m_Storage = CreateStorage ();
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::GetAddress (const std::string& address)
{ {
if (!m_Storage)
m_Storage = CreateStorage ();
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
if (!GetIdentHash (address, ident)) return nullptr; if (!GetIdentHash (address, ident)) return nullptr;
return m_Storage->GetAddress (ident); return m_Storage->GetAddress (ident);
@ -312,16 +254,14 @@ namespace client
void AddressBook::LoadHosts () void AddressBook::LoadHosts ()
{ {
if (!m_Storage)
m_Storage = CreateStorage ();
if (m_Storage->Load (m_Addresses) > 0) if (m_Storage->Load (m_Addresses) > 0)
{ {
m_IsLoaded = true; m_IsLoaded = true;
return; return;
} }
// try hosts.txt first // then try hosts.txt
std::ifstream f (i2p::util::filesystem::GetFullPath ("hosts.txt").c_str (), std::ifstream::in); // in text mode std::ifstream f (i2p::fs::DataDirPath("hosts.txt"), std::ifstream::in); // in text mode
if (f.is_open ()) if (f.is_open ())
{ {
LoadHostsFromStream (f); LoadHostsFromStream (f);
@ -384,7 +324,7 @@ namespace client
{ {
if (!m_Subscriptions.size ()) if (!m_Subscriptions.size ())
{ {
std::ifstream f (i2p::util::filesystem::GetFullPath ("subscriptions.txt").c_str (), std::ifstream::in); // in text mode std::ifstream f (i2p::fs::DataDirPath ("subscriptions.txt"), std::ifstream::in); // in text mode
if (f.is_open ()) if (f.is_open ())
{ {
std::string s; std::string s;
@ -443,7 +383,10 @@ namespace client
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
auto dest = i2p::client::context.GetSharedLocalDestination (); auto dest = i2p::client::context.GetSharedLocalDestination ();
if (!dest) return; if (!dest) {
LogPrint(eLogWarning, "Addressbook: missing local destination, skip subscription update");
return;
}
if (m_IsLoaded && !m_IsDownloading && dest->IsReady () && !m_Subscriptions.empty ()) if (m_IsLoaded && !m_IsDownloading && dest->IsReady () && !m_Subscriptions.empty ())
{ {
// pick random subscription // pick random subscription
@ -495,7 +438,7 @@ namespace client
}); });
if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout) if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout)
{ {
LogPrint (eLogError, "Subscription LeaseSet request timeout expired"); LogPrint (eLogError, "Addressbook: Subscription LeaseSet request timeout expired");
i2p::client::context.GetSharedLocalDestination ()->CancelDestinationRequest (ident); i2p::client::context.GetSharedLocalDestination ()->CancelDestinationRequest (ident);
} }
} }
@ -595,7 +538,7 @@ namespace client
LogPrint (eLogError, "Addressbook: Can't resolve ", u.host_); LogPrint (eLogError, "Addressbook: Can't resolve ", u.host_);
if (!success) if (!success)
LogPrint (eLogError, "Addressbook: download failed"); LogPrint (eLogError, "Addressbook: download hosts.txt from ", m_Link, " failed");
m_Book.DownloadComplete (success); m_Book.DownloadComplete (success);
} }

2
AddressBook.h

@ -10,7 +10,6 @@
#include <memory> #include <memory>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Base.h" #include "Base.h"
#include "util.h"
#include "Identity.h" #include "Identity.h"
#include "Log.h" #include "Log.h"
@ -65,7 +64,6 @@ namespace client
void StartSubscriptions (); void StartSubscriptions ();
void StopSubscriptions (); void StopSubscriptions ();
AddressBookStorage * CreateStorage ();
void LoadHosts (); void LoadHosts ();
void LoadSubscriptions (); void LoadSubscriptions ();

Loading…
Cancel
Save