mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 04:04:16 +00:00
Merge branch 'openssl' into new-fs
Conflicts: AddressBook.cpp NetDb.cpp filelist.mk
This commit is contained in:
commit
55315fca80
@ -193,11 +193,7 @@ namespace client
|
|||||||
delete m_Storage;
|
delete m_Storage;
|
||||||
m_Storage = nullptr;
|
m_Storage = nullptr;
|
||||||
}
|
}
|
||||||
if (m_DefaultSubscription)
|
m_DefaultSubscription = nullptr;
|
||||||
{
|
|
||||||
delete m_DefaultSubscription;
|
|
||||||
m_DefaultSubscription = nullptr;
|
|
||||||
}
|
|
||||||
for (auto it: m_Subscriptions)
|
for (auto it: m_Subscriptions)
|
||||||
delete it;
|
delete it;
|
||||||
m_Subscriptions.clear ();
|
m_Subscriptions.clear ();
|
||||||
@ -278,19 +274,6 @@ namespace client
|
|||||||
LoadHostsFromStream (f);
|
LoadHostsFromStream (f);
|
||||||
m_IsLoaded = true;
|
m_IsLoaded = true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// if not found download it from http://i2p-projekt.i2p/hosts.txt
|
|
||||||
LogPrint (eLogInfo, "Addressbook: hosts.txt not found, trying to download it from default subscription.");
|
|
||||||
if (!m_IsDownloading)
|
|
||||||
{
|
|
||||||
m_IsDownloading = true;
|
|
||||||
if (!m_DefaultSubscription)
|
|
||||||
m_DefaultSubscription = new AddressBookSubscription (*this, DEFAULT_SUBSCRIPTION_ADDRESS);
|
|
||||||
m_DefaultSubscription->CheckSubscription ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressBook::LoadHostsFromStream (std::istream& f)
|
void AddressBook::LoadHostsFromStream (std::istream& f)
|
||||||
@ -357,6 +340,11 @@ namespace client
|
|||||||
void AddressBook::DownloadComplete (bool success)
|
void AddressBook::DownloadComplete (bool success)
|
||||||
{
|
{
|
||||||
m_IsDownloading = false;
|
m_IsDownloading = false;
|
||||||
|
if (success && m_DefaultSubscription)
|
||||||
|
{
|
||||||
|
m_DefaultSubscription.reset (nullptr);
|
||||||
|
m_IsLoaded = true;
|
||||||
|
}
|
||||||
if (m_SubscriptionsUpdateTimer)
|
if (m_SubscriptionsUpdateTimer)
|
||||||
{
|
{
|
||||||
m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(
|
m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(
|
||||||
@ -369,8 +357,8 @@ namespace client
|
|||||||
void AddressBook::StartSubscriptions ()
|
void AddressBook::StartSubscriptions ()
|
||||||
{
|
{
|
||||||
LoadSubscriptions ();
|
LoadSubscriptions ();
|
||||||
if (!m_Subscriptions.size ()) return;
|
if (m_IsLoaded && m_Subscriptions.empty ()) return;
|
||||||
|
|
||||||
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||||
if (dest)
|
if (dest)
|
||||||
{
|
{
|
||||||
@ -398,12 +386,24 @@ namespace client
|
|||||||
LogPrint(eLogWarning, "Addressbook: missing local destination, skip subscription update");
|
LogPrint(eLogWarning, "Addressbook: missing local destination, skip subscription update");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_IsLoaded && !m_IsDownloading && dest->IsReady () && !m_Subscriptions.empty ())
|
if (!m_IsDownloading && dest->IsReady ())
|
||||||
{
|
{
|
||||||
// pick random subscription
|
if (!m_IsLoaded)
|
||||||
auto ind = rand () % m_Subscriptions.size();
|
{
|
||||||
m_IsDownloading = true;
|
// download it from http://i2p-projekt.i2p/hosts.txt
|
||||||
m_Subscriptions[ind]->CheckSubscription ();
|
LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
|
||||||
|
if (!m_DefaultSubscription)
|
||||||
|
m_DefaultSubscription.reset (new AddressBookSubscription (*this, DEFAULT_SUBSCRIPTION_ADDRESS));
|
||||||
|
m_IsDownloading = true;
|
||||||
|
m_DefaultSubscription->CheckSubscription ();
|
||||||
|
}
|
||||||
|
else if (!m_Subscriptions.empty ())
|
||||||
|
{
|
||||||
|
// pick random subscription
|
||||||
|
auto ind = rand () % m_Subscriptions.size();
|
||||||
|
m_IsDownloading = true;
|
||||||
|
m_Subscriptions[ind]->CheckSubscription ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -461,6 +461,8 @@ namespace client
|
|||||||
<< "Host: " << u.host_ << "\r\n"
|
<< "Host: " << u.host_ << "\r\n"
|
||||||
<< "Accept: */*\r\n"
|
<< "Accept: */*\r\n"
|
||||||
<< "User-Agent: Wget/1.11.4\r\n"
|
<< "User-Agent: Wget/1.11.4\r\n"
|
||||||
|
//<< "Accept-Encoding: gzip\r\n"
|
||||||
|
<< "X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n"
|
||||||
<< "Connection: close\r\n";
|
<< "Connection: close\r\n";
|
||||||
if (m_Etag.length () > 0) // etag
|
if (m_Etag.length () > 0) // etag
|
||||||
request << i2p::util::http::IF_NONE_MATCH << ": \"" << m_Etag << "\"\r\n";
|
request << i2p::util::http::IF_NONE_MATCH << ": \"" << m_Etag << "\"\r\n";
|
||||||
@ -499,7 +501,7 @@ namespace client
|
|||||||
response >> status; // status
|
response >> status; // status
|
||||||
if (status == 200) // OK
|
if (status == 200) // OK
|
||||||
{
|
{
|
||||||
bool isChunked = false;
|
bool isChunked = false, isGzip = false;
|
||||||
std::string header, statusMessage;
|
std::string header, statusMessage;
|
||||||
std::getline (response, statusMessage);
|
std::getline (response, statusMessage);
|
||||||
// read until new line meaning end of header
|
// read until new line meaning end of header
|
||||||
@ -510,6 +512,8 @@ namespace client
|
|||||||
if (colon != std::string::npos)
|
if (colon != std::string::npos)
|
||||||
{
|
{
|
||||||
std::string field = header.substr (0, colon);
|
std::string field = header.substr (0, colon);
|
||||||
|
boost::to_lower (field); // field are not case-sensitive
|
||||||
|
colon++;
|
||||||
header.resize (header.length () - 1); // delete \r
|
header.resize (header.length () - 1); // delete \r
|
||||||
if (field == i2p::util::http::ETAG)
|
if (field == i2p::util::http::ETAG)
|
||||||
m_Etag = header.substr (colon + 1);
|
m_Etag = header.substr (colon + 1);
|
||||||
@ -517,6 +521,9 @@ namespace client
|
|||||||
m_LastModified = header.substr (colon + 1);
|
m_LastModified = header.substr (colon + 1);
|
||||||
else if (field == i2p::util::http::TRANSFER_ENCODING)
|
else if (field == i2p::util::http::TRANSFER_ENCODING)
|
||||||
isChunked = !header.compare (colon + 1, std::string::npos, "chunked");
|
isChunked = !header.compare (colon + 1, std::string::npos, "chunked");
|
||||||
|
else if (field == i2p::util::http::CONTENT_ENCODING)
|
||||||
|
isGzip = !header.compare (colon + 1, std::string::npos, "gzip") ||
|
||||||
|
!header.compare (colon + 1, std::string::npos, "x-i2p-gzip");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogPrint (eLogInfo, "Addressbook: ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified);
|
LogPrint (eLogInfo, "Addressbook: ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified);
|
||||||
@ -524,13 +531,13 @@ namespace client
|
|||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
if (!isChunked)
|
if (!isChunked)
|
||||||
m_Book.LoadHostsFromStream (response);
|
success = ProcessResponse (response, isGzip);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// merge chunks
|
// merge chunks
|
||||||
std::stringstream merged;
|
std::stringstream merged;
|
||||||
i2p::util::http::MergeChunkedResponse (response, merged);
|
i2p::util::http::MergeChunkedResponse (response, merged);
|
||||||
m_Book.LoadHostsFromStream (merged);
|
success = ProcessResponse (merged, isGzip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,6 +560,23 @@ namespace client
|
|||||||
|
|
||||||
m_Book.DownloadComplete (success);
|
m_Book.DownloadComplete (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddressBookSubscription::ProcessResponse (std::stringstream& s, bool isGzip)
|
||||||
|
{
|
||||||
|
if (isGzip)
|
||||||
|
{
|
||||||
|
std::stringstream uncompressed;
|
||||||
|
i2p::data::GzipInflator inflator;
|
||||||
|
inflator.Inflate (s, uncompressed);
|
||||||
|
if (!uncompressed.fail ())
|
||||||
|
m_Book.LoadHostsFromStream (uncompressed);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_Book.LoadHostsFromStream (s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ namespace client
|
|||||||
AddressBookStorage * m_Storage;
|
AddressBookStorage * m_Storage;
|
||||||
volatile bool m_IsLoaded, m_IsDownloading;
|
volatile bool m_IsLoaded, m_IsDownloading;
|
||||||
std::vector<AddressBookSubscription *> m_Subscriptions;
|
std::vector<AddressBookSubscription *> m_Subscriptions;
|
||||||
AddressBookSubscription * m_DefaultSubscription; // in case if we don't know any addresses yet
|
std::unique_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
|
||||||
boost::asio::deadline_timer * m_SubscriptionsUpdateTimer;
|
boost::asio::deadline_timer * m_SubscriptionsUpdateTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,6 +91,7 @@ namespace client
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
void Request ();
|
void Request ();
|
||||||
|
bool ProcessResponse (std::stringstream& s, bool isGzip = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
38
Base.cpp
38
Base.cpp
@ -314,6 +314,44 @@ namespace data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& s)
|
||||||
|
{
|
||||||
|
m_IsDirty = true;
|
||||||
|
uint8_t * out = new uint8_t[GZIP_CHUNK_SIZE];
|
||||||
|
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
||||||
|
m_Inflator.avail_in = inLen;
|
||||||
|
int ret;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_Inflator.next_out = out;
|
||||||
|
m_Inflator.avail_out = GZIP_CHUNK_SIZE;
|
||||||
|
ret = inflate (&m_Inflator, Z_NO_FLUSH);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Decompression error ", ret);
|
||||||
|
inflateEnd (&m_Inflator);
|
||||||
|
s.setstate(std::ios_base::failbit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out);
|
||||||
|
}
|
||||||
|
while (!m_Inflator.avail_out); // more data to read
|
||||||
|
delete[] out;
|
||||||
|
return ret == Z_STREAM_END || ret < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GzipInflator::Inflate (std::istream& in, std::ostream& out)
|
||||||
|
{
|
||||||
|
uint8_t * buf = new uint8_t[GZIP_CHUNK_SIZE];
|
||||||
|
while (!in.eof ())
|
||||||
|
{
|
||||||
|
in.read ((char *)buf, GZIP_CHUNK_SIZE);
|
||||||
|
Inflate (buf, in.gcount (), out);
|
||||||
|
}
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
GzipDeflator::GzipDeflator (): m_IsDirty (false)
|
GzipDeflator::GzipDeflator (): m_IsDirty (false)
|
||||||
{
|
{
|
||||||
memset (&m_Deflator, 0, sizeof (m_Deflator));
|
memset (&m_Deflator, 0, sizeof (m_Deflator));
|
||||||
|
7
Base.h
7
Base.h
@ -5,6 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -93,6 +94,7 @@ namespace data
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const size_t GZIP_CHUNK_SIZE = 16384;
|
||||||
class GzipInflator
|
class GzipInflator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -101,7 +103,10 @@ namespace data
|
|||||||
~GzipInflator ();
|
~GzipInflator ();
|
||||||
|
|
||||||
size_t Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
size_t Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
||||||
|
bool Inflate (const uint8_t * in, size_t inLen, std::ostream& s);
|
||||||
|
// return true when finshed or error, s failbit will be set in case of error
|
||||||
|
void Inflate (std::istream& in, std::ostream& out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
z_stream m_Inflator;
|
z_stream m_Inflator;
|
||||||
|
@ -37,6 +37,8 @@ namespace client
|
|||||||
m_SharedLocalDestination->Start ();
|
m_SharedLocalDestination->Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_AddressBook.Start ();
|
||||||
|
|
||||||
std::shared_ptr<ClientDestination> localDestination;
|
std::shared_ptr<ClientDestination> localDestination;
|
||||||
bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy);
|
bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy);
|
||||||
if (httproxy) {
|
if (httproxy) {
|
||||||
@ -94,25 +96,19 @@ namespace client
|
|||||||
m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort);
|
m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort);
|
||||||
m_BOBCommandChannel->Start ();
|
m_BOBCommandChannel->Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_AddressBook.Start ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientContext::Stop ()
|
void ClientContext::Stop ()
|
||||||
{
|
{
|
||||||
if (m_HttpProxy) {
|
LogPrint(eLogInfo, "Clients: stopping HTTP Proxy");
|
||||||
LogPrint(eLogInfo, "Clients: stopping HTTP Proxy");
|
m_HttpProxy->Stop();
|
||||||
m_HttpProxy->Stop();
|
delete m_HttpProxy;
|
||||||
delete m_HttpProxy;
|
m_HttpProxy = nullptr;
|
||||||
m_HttpProxy = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_SocksProxy) {
|
LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy");
|
||||||
LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy");
|
m_SocksProxy->Stop();
|
||||||
m_SocksProxy->Stop();
|
delete m_SocksProxy;
|
||||||
delete m_SocksProxy;
|
m_SocksProxy = nullptr;
|
||||||
m_SocksProxy = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& it: m_ClientTunnels)
|
for (auto& it: m_ClientTunnels)
|
||||||
{
|
{
|
||||||
|
17
Config.cpp
17
Config.cpp
@ -191,7 +191,7 @@ namespace config {
|
|||||||
| boost::program_options::command_line_style::allow_long_disguise;
|
| boost::program_options::command_line_style::allow_long_disguise;
|
||||||
style &= ~ boost::program_options::command_line_style::allow_guessing;
|
style &= ~ boost::program_options::command_line_style::allow_guessing;
|
||||||
store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options);
|
store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options);
|
||||||
} catch (boost::program_options::error e) {
|
} catch (boost::program_options::error& e) {
|
||||||
std::cerr << "args: " << e.what() << std::endl;
|
std::cerr << "args: " << e.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -204,19 +204,22 @@ namespace config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseConfig(const std::string& path) {
|
void ParseConfig(const std::string& path) {
|
||||||
if (path == "")
|
if (path == "") return;
|
||||||
return;
|
|
||||||
|
|
||||||
std::ifstream config(path, std::ios::in);
|
std::ifstream config(path, std::ios::in);
|
||||||
|
|
||||||
if (!config.is_open()) {
|
if (!config.is_open())
|
||||||
|
{
|
||||||
std::cerr << "missing/unreadable config file: " << path << std::endl;
|
std::cerr << "missing/unreadable config file: " << path << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try
|
||||||
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
|
{
|
||||||
} catch (boost::program_options::error e) {
|
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
|
||||||
|
}
|
||||||
|
catch (boost::program_options::error& e)
|
||||||
|
{
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
};
|
};
|
||||||
|
117
Destination.cpp
117
Destination.cpp
@ -18,7 +18,8 @@ namespace client
|
|||||||
const std::map<std::string, std::string> * params):
|
const std::map<std::string, std::string> * params):
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
||||||
m_Keys (keys), m_IsPublic (isPublic), m_PublishReplyToken (0),
|
m_Keys (keys), m_IsPublic (isPublic), m_PublishReplyToken (0),
|
||||||
m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service), m_CleanupTimer (m_Service)
|
m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service),
|
||||||
|
m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service)
|
||||||
{
|
{
|
||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
PersistTemporaryKeys ();
|
PersistTemporaryKeys ();
|
||||||
@ -140,7 +141,7 @@ namespace client
|
|||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Pool->SetLocalDestination (shared_from_this ());
|
m_Pool->SetLocalDestination (shared_from_this ());
|
||||||
m_Pool->SetActive (true);
|
m_Pool->SetActive (true);
|
||||||
m_Thread = new std::thread (std::bind (&ClientDestination::Run, this));
|
m_Thread = new std::thread (std::bind (&ClientDestination::Run, shared_from_this ()));
|
||||||
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (shared_from_this ()); // TODO:
|
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (shared_from_this ()); // TODO:
|
||||||
m_StreamingDestination->Start ();
|
m_StreamingDestination->Start ();
|
||||||
for (auto it: m_StreamingDestinationsByPorts)
|
for (auto it: m_StreamingDestinationsByPorts)
|
||||||
@ -148,7 +149,7 @@ namespace client
|
|||||||
|
|
||||||
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
|
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
|
||||||
m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer,
|
m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer,
|
||||||
this, std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +158,8 @@ namespace client
|
|||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
{
|
{
|
||||||
m_CleanupTimer.cancel ();
|
m_CleanupTimer.cancel ();
|
||||||
|
m_PublishConfirmationTimer.cancel ();
|
||||||
|
m_PublishVerificationTimer.cancel ();
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
m_StreamingDestination->Stop ();
|
m_StreamingDestination->Stop ();
|
||||||
m_StreamingDestination = nullptr;
|
m_StreamingDestination = nullptr;
|
||||||
@ -196,7 +199,7 @@ namespace client
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto ls = i2p::data::netdb.FindLeaseSet (ident);
|
auto ls = i2p::data::netdb.FindLeaseSet (ident);
|
||||||
if (ls)
|
if (ls && !ls->IsExpired ())
|
||||||
{
|
{
|
||||||
ls->PopulateLeases (); // since we don't store them in netdb
|
ls->PopulateLeases (); // since we don't store them in netdb
|
||||||
m_RemoteLeaseSets[ident] = ls;
|
m_RemoteLeaseSets[ident] = ls;
|
||||||
@ -227,21 +230,22 @@ namespace client
|
|||||||
} data;
|
} data;
|
||||||
memcpy (data.k, key, 32);
|
memcpy (data.k, key, 32);
|
||||||
memcpy (data.t, tag, 32);
|
memcpy (data.t, tag, 32);
|
||||||
m_Service.post ([this,data](void)
|
auto s = shared_from_this ();
|
||||||
|
m_Service.post ([s,data](void)
|
||||||
{
|
{
|
||||||
this->AddSessionKey (data.k, data.t);
|
s->AddSessionKey (data.k, data.t);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
void ClientDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
m_Service.post (std::bind (&ClientDestination::HandleGarlicMessage, this, msg));
|
m_Service.post (std::bind (&ClientDestination::HandleGarlicMessage, shared_from_this (), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
void ClientDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
m_Service.post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, this, msg));
|
m_Service.post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||||
@ -284,23 +288,33 @@ namespace client
|
|||||||
if (it != m_RemoteLeaseSets.end ())
|
if (it != m_RemoteLeaseSets.end ())
|
||||||
{
|
{
|
||||||
leaseSet = it->second;
|
leaseSet = it->second;
|
||||||
leaseSet->Update (buf + offset, len - offset);
|
if (leaseSet->IsNewer (buf + offset, len - offset))
|
||||||
if (leaseSet->IsValid ())
|
{
|
||||||
LogPrint (eLogDebug, "Remote LeaseSet updated");
|
leaseSet->Update (buf + offset, len - offset);
|
||||||
else
|
if (leaseSet->IsValid ())
|
||||||
{
|
LogPrint (eLogDebug, "Remote LeaseSet updated");
|
||||||
LogPrint (eLogDebug, "Remote LeaseSet update failed");
|
else
|
||||||
m_RemoteLeaseSets.erase (it);
|
{
|
||||||
leaseSet = nullptr;
|
LogPrint (eLogDebug, "Remote LeaseSet update failed");
|
||||||
|
m_RemoteLeaseSets.erase (it);
|
||||||
|
leaseSet = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogDebug, "Remote LeaseSet is older. Not updated");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset);
|
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset);
|
||||||
if (leaseSet->IsValid ())
|
if (leaseSet->IsValid ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "New remote LeaseSet added");
|
if (leaseSet->GetIdentHash () != GetIdentHash ())
|
||||||
m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet;
|
{
|
||||||
|
LogPrint (eLogDebug, "New remote LeaseSet added");
|
||||||
|
m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogDebug, "Own remote LeaseSet dropped");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -372,6 +386,10 @@ namespace client
|
|||||||
LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed");
|
LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed");
|
||||||
m_ExcludedFloodfills.clear ();
|
m_ExcludedFloodfills.clear ();
|
||||||
m_PublishReplyToken = 0;
|
m_PublishReplyToken = 0;
|
||||||
|
// schedule verification
|
||||||
|
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
|
||||||
|
m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer,
|
||||||
|
shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
|
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
|
||||||
@ -382,7 +400,10 @@ namespace client
|
|||||||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||||
UpdateLeaseSet ();
|
UpdateLeaseSet ();
|
||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
|
{
|
||||||
|
m_PublishVerificationTimer.cancel ();
|
||||||
Publish ();
|
Publish ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Publish ()
|
void ClientDestination::Publish ()
|
||||||
@ -403,7 +424,6 @@ namespace client
|
|||||||
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
|
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::set<i2p::data::IdentHash> excluded;
|
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
||||||
if (!floodfill)
|
if (!floodfill)
|
||||||
{
|
{
|
||||||
@ -417,7 +437,7 @@ namespace client
|
|||||||
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken));
|
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken));
|
||||||
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
||||||
m_PublishConfirmationTimer.async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer,
|
m_PublishConfirmationTimer.async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer,
|
||||||
this, std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
|
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,6 +454,33 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
RequestLeaseSet (GetIdentHash (),
|
||||||
|
[s](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||||
|
{
|
||||||
|
if (leaseSet)
|
||||||
|
{
|
||||||
|
if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet)
|
||||||
|
{
|
||||||
|
// we got latest LeasetSet
|
||||||
|
LogPrint (eLogDebug, "Destination: published LeaseSet verified");
|
||||||
|
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
||||||
|
s->m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet");
|
||||||
|
// we have to publish again
|
||||||
|
s->Publish ();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
uint32_t length = bufbe32toh (buf);
|
uint32_t length = bufbe32toh (buf);
|
||||||
@ -465,18 +512,24 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) {
|
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
|
||||||
assert(streamRequestComplete);
|
{
|
||||||
|
if (!streamRequestComplete)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto leaseSet = FindLeaseSet (dest);
|
auto leaseSet = FindLeaseSet (dest);
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
streamRequestComplete(CreateStream (leaseSet, port));
|
streamRequestComplete(CreateStream (leaseSet, port));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
auto s = shared_from_this ();
|
||||||
RequestDestination (dest,
|
RequestDestination (dest,
|
||||||
[this, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
|
[s, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
|
||||||
{
|
{
|
||||||
if (ls)
|
if (ls)
|
||||||
streamRequestComplete(CreateStream (ls, port));
|
streamRequestComplete(s->CreateStream (ls, port));
|
||||||
else
|
else
|
||||||
streamRequestComplete (nullptr);
|
streamRequestComplete (nullptr);
|
||||||
});
|
});
|
||||||
@ -557,7 +610,11 @@ namespace client
|
|||||||
{
|
{
|
||||||
auto it = s->m_LeaseSetRequests.find (dest);
|
auto it = s->m_LeaseSetRequests.find (dest);
|
||||||
if (it != s->m_LeaseSetRequests.end ())
|
if (it != s->m_LeaseSetRequests.end ())
|
||||||
s->m_LeaseSetRequests.erase (it);
|
{
|
||||||
|
auto requestComplete = it->second->requestComplete;
|
||||||
|
s->m_LeaseSetRequests.erase (it);
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,8 +632,8 @@ namespace client
|
|||||||
if (!SendLeaseSetRequest (dest, floodfill, request))
|
if (!SendLeaseSetRequest (dest, floodfill, request))
|
||||||
{
|
{
|
||||||
// request failed
|
// request failed
|
||||||
if (request->requestComplete) request->requestComplete (nullptr);
|
|
||||||
m_LeaseSetRequests.erase (dest);
|
m_LeaseSetRequests.erase (dest);
|
||||||
|
if (request->requestComplete) request->requestComplete (nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // duplicate
|
else // duplicate
|
||||||
@ -587,7 +644,10 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found");
|
LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found");
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
bool ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
||||||
@ -623,7 +683,7 @@ namespace client
|
|||||||
});
|
});
|
||||||
request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
|
request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
|
||||||
request->requestTimeoutTimer.async_wait (std::bind (&ClientDestination::HandleRequestTimoutTimer,
|
request->requestTimeoutTimer.async_wait (std::bind (&ClientDestination::HandleRequestTimoutTimer,
|
||||||
this, std::placeholders::_1, dest));
|
shared_from_this (), std::placeholders::_1, dest));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -655,8 +715,9 @@ namespace client
|
|||||||
|
|
||||||
if (done)
|
if (done)
|
||||||
{
|
{
|
||||||
if (it->second->requestComplete) it->second->requestComplete (nullptr);
|
auto requestComplete = it->second->requestComplete;
|
||||||
m_LeaseSetRequests.erase (it);
|
m_LeaseSetRequests.erase (it);
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@ namespace client
|
|||||||
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
|
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
|
||||||
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
||||||
const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
||||||
|
const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successfull publish
|
||||||
|
const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically
|
||||||
const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds
|
const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds
|
||||||
const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds
|
const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds
|
||||||
const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes
|
const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes
|
||||||
@ -116,6 +118,7 @@ namespace client
|
|||||||
void UpdateLeaseSet ();
|
void UpdateLeaseSet ();
|
||||||
void Publish ();
|
void Publish ();
|
||||||
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
||||||
|
void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
|
||||||
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
|
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
|
||||||
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
||||||
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
@ -148,7 +151,7 @@ namespace client
|
|||||||
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
||||||
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
||||||
|
|
||||||
boost::asio::deadline_timer m_PublishConfirmationTimer, m_CleanupTimer;
|
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_CleanupTimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
122
Family.cpp
Normal file
122
Family.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "util.h"
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Crypto.h"
|
||||||
|
#include "Family.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace data
|
||||||
|
{
|
||||||
|
Families::Families ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Families::~Families ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Families::LoadCertificate (const std::string& filename)
|
||||||
|
{
|
||||||
|
SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ());
|
||||||
|
int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
SSL * ssl = SSL_new (ctx);
|
||||||
|
X509 * cert = SSL_get_certificate (ssl);
|
||||||
|
if (cert)
|
||||||
|
{
|
||||||
|
std::shared_ptr<i2p::crypto::Verifier> verifier;
|
||||||
|
// extract issuer name
|
||||||
|
char name[100];
|
||||||
|
X509_NAME_oneline (X509_get_issuer_name(cert), name, 100);
|
||||||
|
char * family = strstr (name, ".family");
|
||||||
|
if (family) family[0] = 0;
|
||||||
|
auto pkey = X509_get_pubkey (cert);
|
||||||
|
int keyType = EVP_PKEY_type(pkey->type);
|
||||||
|
switch (keyType)
|
||||||
|
{
|
||||||
|
case EVP_PKEY_DSA:
|
||||||
|
// TODO:
|
||||||
|
break;
|
||||||
|
case EVP_PKEY_EC:
|
||||||
|
{
|
||||||
|
EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey);
|
||||||
|
if (ecKey)
|
||||||
|
{
|
||||||
|
auto group = EC_KEY_get0_group (ecKey);
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
int curve = EC_GROUP_get_curve_name (group);
|
||||||
|
if (curve == NID_X9_62_prime256v1)
|
||||||
|
{
|
||||||
|
uint8_t signingKey[64];
|
||||||
|
BIGNUM * x = BN_new(), * y = BN_new();
|
||||||
|
EC_POINT_get_affine_coordinates_GFp (group,
|
||||||
|
EC_KEY_get0_public_key (ecKey), x, y, NULL);
|
||||||
|
i2p::crypto::bn2buf (x, signingKey, 32);
|
||||||
|
i2p::crypto::bn2buf (y, signingKey + 32, 32);
|
||||||
|
BN_free (x); BN_free (y);
|
||||||
|
verifier = std::make_shared<i2p::crypto::ECDSAP256Verifier>(signingKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported");
|
||||||
|
}
|
||||||
|
EC_KEY_free (ecKey);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LogPrint (eLogWarning, "Family: Certificate key type ", keyType, " is not supported");
|
||||||
|
}
|
||||||
|
EVP_PKEY_free (pkey);
|
||||||
|
if (verifier)
|
||||||
|
m_SigningKeys[name] = verifier;
|
||||||
|
}
|
||||||
|
SSL_free (ssl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Family: Can't open certificate file ", filename);
|
||||||
|
SSL_CTX_free (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Families::LoadCertificates ()
|
||||||
|
{
|
||||||
|
boost::filesystem::path familyDir = i2p::util::filesystem::GetCertificatesDir() / "family";
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists (familyDir)) return;
|
||||||
|
int numCertificates = 0;
|
||||||
|
boost::filesystem::directory_iterator end; // empty
|
||||||
|
for (boost::filesystem::directory_iterator it (familyDir); it != end; ++it)
|
||||||
|
{
|
||||||
|
if (boost::filesystem::is_regular_file (it->status()) && it->path ().extension () == ".crt")
|
||||||
|
{
|
||||||
|
LoadCertificate (it->path ().string ());
|
||||||
|
numCertificates++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (numCertificates > 0)
|
||||||
|
LogPrint (eLogInfo, "Family: ", numCertificates, " certificates loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||||
|
const char * signature, const char * key)
|
||||||
|
{
|
||||||
|
uint8_t buf[50], signatureBuf[64];
|
||||||
|
size_t len = family.length (), signatureLen = strlen (signature);
|
||||||
|
memcpy (buf, family.c_str (), len);
|
||||||
|
memcpy (buf + len, (const uint8_t *)ident, 32);
|
||||||
|
len += 32;
|
||||||
|
Base64ToByteStream (signature, signatureLen, signatureBuf, 64);
|
||||||
|
auto it = m_SigningKeys.find (family);
|
||||||
|
if (it != m_SigningKeys.end ())
|
||||||
|
return it->second->Verify (buf, len, signatureBuf);
|
||||||
|
// TODO: process key
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
35
Family.h
Normal file
35
Family.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef FAMILY_H__
|
||||||
|
#define FAMILY_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include "Signature.h"
|
||||||
|
#include "Identity.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace data
|
||||||
|
{
|
||||||
|
class Families
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Families ();
|
||||||
|
~Families ();
|
||||||
|
void LoadCertificates ();
|
||||||
|
bool VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||||
|
const char * signature, const char * key = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void LoadCertificate (const std::string& filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::map<std::string, std::shared_ptr<i2p::crypto::Verifier> > m_SigningKeys;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -47,17 +47,22 @@ namespace garlic
|
|||||||
{
|
{
|
||||||
if (!m_SharedRoutingPath) return nullptr;
|
if (!m_SharedRoutingPath) return nullptr;
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
if (!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
|
if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
|
||||||
|
!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
|
||||||
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
|
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
|
||||||
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
|
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
|
||||||
m_SharedRoutingPath = nullptr;
|
m_SharedRoutingPath = nullptr;
|
||||||
|
if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++;
|
||||||
return m_SharedRoutingPath;
|
return m_SharedRoutingPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path)
|
void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path)
|
||||||
{
|
{
|
||||||
if (path && path->outboundTunnel && path->remoteLease)
|
if (path && path->outboundTunnel && path->remoteLease)
|
||||||
|
{
|
||||||
path->updateTime = i2p::util::GetSecondsSinceEpoch ();
|
path->updateTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
path->numTimesUsed = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
path = nullptr;
|
path = nullptr;
|
||||||
m_SharedRoutingPath = path;
|
m_SharedRoutingPath = path;
|
||||||
|
3
Garlic.h
3
Garlic.h
@ -44,6 +44,7 @@ namespace garlic
|
|||||||
const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds
|
const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds
|
||||||
const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
|
const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
|
||||||
const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds
|
const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds
|
||||||
|
const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used
|
||||||
|
|
||||||
struct SessionTag: public i2p::data::Tag<32>
|
struct SessionTag: public i2p::data::Tag<32>
|
||||||
{
|
{
|
||||||
@ -62,7 +63,9 @@ namespace garlic
|
|||||||
{
|
{
|
||||||
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
||||||
std::shared_ptr<const i2p::data::Lease> remoteLease;
|
std::shared_ptr<const i2p::data::Lease> remoteLease;
|
||||||
|
int rtt; // RTT
|
||||||
uint32_t updateTime; // seconds since epoch
|
uint32_t updateTime; // seconds since epoch
|
||||||
|
int numTimesUsed;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GarlicDestination;
|
class GarlicDestination;
|
||||||
|
@ -176,28 +176,39 @@ namespace proxy
|
|||||||
m_request.push_back('\r');
|
m_request.push_back('\r');
|
||||||
m_request.push_back('\n');
|
m_request.push_back('\n');
|
||||||
m_request.append("Connection: close\r\n");
|
m_request.append("Connection: close\r\n");
|
||||||
m_request.append(reinterpret_cast<const char *>(http_buff),len);
|
// TODO: temporary shortcut. Must be implemented properly
|
||||||
|
uint8_t * eol = nullptr;
|
||||||
|
bool isEndOfHeader = false;
|
||||||
|
while (!isEndOfHeader && len && (eol = (uint8_t *)memchr (http_buff, '\r', len)))
|
||||||
|
{
|
||||||
|
if (eol)
|
||||||
|
{
|
||||||
|
*eol = 0; eol++;
|
||||||
|
if (strncmp ((const char *)http_buff, "Referer", 7)) // strip out referer
|
||||||
|
{
|
||||||
|
if (!strncmp ((const char *)http_buff, "User-Agent", 10)) // replace UserAgent
|
||||||
|
m_request.append("User-Agent: MYOB/6.66 (AN/ON)");
|
||||||
|
else
|
||||||
|
m_request.append ((const char *)http_buff);
|
||||||
|
m_request.append ("\r\n");
|
||||||
|
}
|
||||||
|
isEndOfHeader = !http_buff[0];
|
||||||
|
auto l = eol - http_buff;
|
||||||
|
http_buff = eol;
|
||||||
|
len -= l;
|
||||||
|
if (len > 0) // \r
|
||||||
|
{
|
||||||
|
http_buff++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_request.append(reinterpret_cast<const char *>(http_buff),len);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTPProxyHandler::HandleData(uint8_t *http_buff, std::size_t len)
|
bool HTTPProxyHandler::HandleData(uint8_t *http_buff, std::size_t len)
|
||||||
{
|
{
|
||||||
// TODO: we should srtrip 'Referer' better, because it might be inside message body
|
|
||||||
/*assert(len); // This should always be called with a least a byte left to parse
|
|
||||||
|
|
||||||
// remove "Referer" from http requst
|
|
||||||
http_buff[len] = 0;
|
|
||||||
auto start = strstr((char *)http_buff, "\nReferer:");
|
|
||||||
if (start)
|
|
||||||
{
|
|
||||||
auto end = strchr (start + 1, '\n');
|
|
||||||
if (end)
|
|
||||||
{
|
|
||||||
strncpy(start, end, (char *)(http_buff + len) - end);
|
|
||||||
len -= (end - start);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
{
|
{
|
||||||
//TODO: fallback to finding HOst: header if needed
|
//TODO: fallback to finding HOst: header if needed
|
||||||
|
@ -114,10 +114,25 @@ namespace client
|
|||||||
void I2PTunnelConnection::StreamReceive ()
|
void I2PTunnelConnection::StreamReceive ()
|
||||||
{
|
{
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
|
{
|
||||||
std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
|
if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew ||
|
||||||
std::placeholders::_1, std::placeholders::_2),
|
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
|
||||||
I2P_TUNNEL_CONNECTION_MAX_IDLE);
|
{
|
||||||
|
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
|
||||||
|
std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
|
||||||
|
std::placeholders::_1, std::placeholders::_2),
|
||||||
|
I2P_TUNNEL_CONNECTION_MAX_IDLE);
|
||||||
|
}
|
||||||
|
else // closed by peer
|
||||||
|
{
|
||||||
|
// get remaning data
|
||||||
|
auto len = m_Stream->ReadSome (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE);
|
||||||
|
if (len > 0) // still some data
|
||||||
|
Write (m_StreamBuffer, len);
|
||||||
|
else // no more data
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PTunnelConnection::HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void I2PTunnelConnection::HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
@ -126,7 +141,12 @@ namespace client
|
|||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2PTunnel: stream read error: ", ecode.message ());
|
LogPrint (eLogError, "I2PTunnel: stream read error: ", ecode.message ());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
Terminate ();
|
{
|
||||||
|
if (bytes_transferred > 0)
|
||||||
|
Write (m_StreamBuffer, bytes_transferred); // postpone termination
|
||||||
|
else
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Write (m_StreamBuffer, bytes_transferred);
|
Write (m_StreamBuffer, bytes_transferred);
|
||||||
|
47
LeaseSet.cpp
47
LeaseSet.cpp
@ -42,10 +42,13 @@ namespace data
|
|||||||
auto signingKeyLen = localDestination->GetIdentity ()->GetSigningPublicKeyLen ();
|
auto signingKeyLen = localDestination->GetIdentity ()->GetSigningPublicKeyLen ();
|
||||||
memset (m_Buffer + m_BufferLen, 0, signingKeyLen);
|
memset (m_Buffer + m_BufferLen, 0, signingKeyLen);
|
||||||
m_BufferLen += signingKeyLen;
|
m_BufferLen += signingKeyLen;
|
||||||
auto tunnels = pool->GetInboundTunnels (5); // 5 tunnels maximum
|
int numTunnels = pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
|
||||||
|
if (numTunnels > 16) numTunnels = 16; // 16 tunnels maximum
|
||||||
|
auto tunnels = pool->GetInboundTunnels (numTunnels);
|
||||||
m_Buffer[m_BufferLen] = tunnels.size (); // num leases
|
m_Buffer[m_BufferLen] = tunnels.size (); // num leases
|
||||||
m_BufferLen++;
|
m_BufferLen++;
|
||||||
// leases
|
// leases
|
||||||
|
auto currentTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
for (auto it: tunnels)
|
for (auto it: tunnels)
|
||||||
{
|
{
|
||||||
memcpy (m_Buffer + m_BufferLen, it->GetNextIdentHash (), 32);
|
memcpy (m_Buffer + m_BufferLen, it->GetNextIdentHash (), 32);
|
||||||
@ -54,8 +57,9 @@ namespace data
|
|||||||
m_BufferLen += 4; // tunnel id
|
m_BufferLen += 4; // tunnel id
|
||||||
uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration
|
uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration
|
||||||
ts *= 1000; // in milliseconds
|
ts *= 1000; // in milliseconds
|
||||||
ts += rand () % 6; // + random milliseconds 0-5
|
|
||||||
if (ts > m_ExpirationTime) m_ExpirationTime = ts;
|
if (ts > m_ExpirationTime) m_ExpirationTime = ts;
|
||||||
|
// make sure leaseset is newer than previous, but adding some time to expiration date
|
||||||
|
ts += (currentTime - it->GetCreationTime ()*1000LL)*2/i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT; // up to 2 secs
|
||||||
htobe64buf (m_Buffer + m_BufferLen, ts);
|
htobe64buf (m_Buffer + m_BufferLen, ts);
|
||||||
m_BufferLen += 8; // end date
|
m_BufferLen += 8; // end date
|
||||||
}
|
}
|
||||||
@ -130,7 +134,7 @@ namespace data
|
|||||||
leases += 4; // tunnel ID
|
leases += 4; // tunnel ID
|
||||||
lease.endDate = bufbe64toh (leases);
|
lease.endDate = bufbe64toh (leases);
|
||||||
leases += 8; // end date
|
leases += 8; // end date
|
||||||
if (ts < lease.endDate)
|
if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD)
|
||||||
{
|
{
|
||||||
if (lease.endDate > m_ExpirationTime)
|
if (lease.endDate > m_ExpirationTime)
|
||||||
m_ExpirationTime = lease.endDate;
|
m_ExpirationTime = lease.endDate;
|
||||||
@ -157,6 +161,7 @@ namespace data
|
|||||||
m_IsValid = false;
|
m_IsValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_ExpirationTime += LEASE_ENDDATE_THRESHOLD;
|
||||||
// delete old leases
|
// delete old leases
|
||||||
if (m_StoreLeases)
|
if (m_StoreLeases)
|
||||||
{
|
{
|
||||||
@ -179,7 +184,35 @@ namespace data
|
|||||||
m_IsValid = false;
|
m_IsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const
|
||||||
|
{
|
||||||
|
if (!m_Identity) return 0;
|
||||||
|
size_t size = m_Identity->GetFullLen ();
|
||||||
|
if (size > len) return 0;
|
||||||
|
size += 256; // encryption key
|
||||||
|
size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
|
||||||
|
if (size > len) return 0;
|
||||||
|
uint8_t num = buf[size];
|
||||||
|
size++; // num
|
||||||
|
if (size + num*44 > len) return 0;
|
||||||
|
uint64_t timestamp= 0 ;
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
size += 36; // gateway (32) + tunnelId(4)
|
||||||
|
auto endDate = bufbe64toh (buf + size);
|
||||||
|
size += 8; // end date
|
||||||
|
if (!timestamp || endDate < timestamp)
|
||||||
|
timestamp = endDate;
|
||||||
|
}
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const
|
||||||
|
{
|
||||||
|
return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen);
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
|
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
|
||||||
{
|
{
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
@ -187,8 +220,10 @@ namespace data
|
|||||||
for (auto it: m_Leases)
|
for (auto it: m_Leases)
|
||||||
{
|
{
|
||||||
auto endDate = it->endDate;
|
auto endDate = it->endDate;
|
||||||
if (!withThreshold)
|
if (withThreshold)
|
||||||
endDate -= i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000;
|
endDate += LEASE_ENDDATE_THRESHOLD;
|
||||||
|
else
|
||||||
|
endDate -= LEASE_ENDDATE_THRESHOLD;
|
||||||
if (ts < endDate)
|
if (ts < endDate)
|
||||||
leases.push_back (it);
|
leases.push_back (it);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ namespace tunnel
|
|||||||
|
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
|
const int LEASE_ENDDATE_THRESHOLD = 31000; // in milliseconds
|
||||||
struct Lease
|
struct Lease
|
||||||
{
|
{
|
||||||
IdentHash tunnelGateway;
|
IdentHash tunnelGateway;
|
||||||
@ -46,6 +47,7 @@ namespace data
|
|||||||
LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool);
|
LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool);
|
||||||
~LeaseSet () { delete[] m_Buffer; };
|
~LeaseSet () { delete[] m_Buffer; };
|
||||||
void Update (const uint8_t * buf, size_t len);
|
void Update (const uint8_t * buf, size_t len);
|
||||||
|
bool IsNewer (const uint8_t * buf, size_t len) const;
|
||||||
void PopulateLeases (); // from buffer
|
void PopulateLeases (); // from buffer
|
||||||
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
|
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
|
||||||
|
|
||||||
@ -57,6 +59,8 @@ namespace data
|
|||||||
bool IsExpired () const;
|
bool IsExpired () const;
|
||||||
bool IsEmpty () const { return m_Leases.empty (); };
|
bool IsEmpty () const { return m_Leases.empty (); };
|
||||||
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
|
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
|
||||||
|
bool operator== (const LeaseSet& other) const
|
||||||
|
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); };
|
||||||
|
|
||||||
// implements RoutingDestination
|
// implements RoutingDestination
|
||||||
const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); };
|
const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); };
|
||||||
@ -66,6 +70,7 @@ namespace data
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
void ReadFromBuffer (bool readIdentity = true);
|
void ReadFromBuffer (bool readIdentity = true);
|
||||||
|
uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
139
NetDb.cpp
139
NetDb.cpp
@ -37,6 +37,7 @@ namespace data
|
|||||||
|
|
||||||
void NetDb::Start ()
|
void NetDb::Start ()
|
||||||
{
|
{
|
||||||
|
m_Families.LoadCertificates ();
|
||||||
Load ();
|
Load ();
|
||||||
if (m_RouterInfos.size () < 25) // reseed if # of router less than 50
|
if (m_RouterInfos.size () < 25) // reseed if # of router less than 50
|
||||||
Reseed ();
|
Reseed ();
|
||||||
@ -149,22 +150,30 @@ namespace data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
||||||
{
|
{
|
||||||
IdentityEx identity;
|
IdentityEx identity;
|
||||||
if (identity.FromBuffer (buf, len))
|
if (identity.FromBuffer (buf, len))
|
||||||
AddRouterInfo (identity.GetIdentHash (), buf, len);
|
return AddRouterInfo (identity.GetIdentHash (), buf, len);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
||||||
{
|
{
|
||||||
|
bool updated = true;
|
||||||
auto r = FindRouter (ident);
|
auto r = FindRouter (ident);
|
||||||
if (r)
|
if (r)
|
||||||
{
|
{
|
||||||
auto ts = r->GetTimestamp ();
|
if (r->IsNewer (buf, len))
|
||||||
r->Update (buf, len);
|
{
|
||||||
if (r->GetTimestamp () > ts)
|
r->Update (buf, len);
|
||||||
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
|
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
|
||||||
|
updated = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -182,27 +191,39 @@ namespace data
|
|||||||
m_Floodfills.push_back (r);
|
m_Floodfills.push_back (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
updated = false;
|
||||||
}
|
}
|
||||||
// take care about requested destination
|
// take care about requested destination
|
||||||
m_Requests.RequestComplete (ident, r);
|
m_Requests.RequestComplete (ident, r);
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len,
|
bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len,
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||||
{
|
{
|
||||||
|
bool updated = false;
|
||||||
if (!from) // unsolicited LS must be received directly
|
if (!from) // unsolicited LS must be received directly
|
||||||
{
|
{
|
||||||
auto it = m_LeaseSets.find(ident);
|
auto it = m_LeaseSets.find(ident);
|
||||||
if (it != m_LeaseSets.end ())
|
if (it != m_LeaseSets.end ())
|
||||||
{
|
{
|
||||||
it->second->Update (buf, len);
|
if (it->second->IsNewer (buf, len))
|
||||||
if (it->second->IsValid ())
|
|
||||||
LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64());
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64());
|
it->second->Update (buf, len);
|
||||||
m_LeaseSets.erase (it);
|
if (it->second->IsValid ())
|
||||||
}
|
{
|
||||||
|
LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64());
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64());
|
||||||
|
m_LeaseSets.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase64());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -211,11 +232,13 @@ namespace data
|
|||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64());
|
LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64());
|
||||||
m_LeaseSets[ident] = leaseSet;
|
m_LeaseSets[ident] = leaseSet;
|
||||||
|
updated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase64());
|
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase64());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RouterInfo> NetDb::FindRouter (const IdentHash& ident) const
|
std::shared_ptr<RouterInfo> NetDb::FindRouter (const IdentHash& ident) const
|
||||||
@ -326,10 +349,21 @@ namespace data
|
|||||||
it.second->SetUnreachable (true);
|
it.second->SetUnreachable (true);
|
||||||
total--;
|
total--;
|
||||||
}
|
}
|
||||||
} else if (total > 300) {
|
else if (total > 2500)
|
||||||
if (ts > it.second->GetTimestamp () + 30*3600*1000LL) { // 30 hours
|
{
|
||||||
it.second->SetUnreachable (true);
|
if (ts > it.second->GetTimestamp () + 12*3600*1000LL) // 12 hours
|
||||||
total--;
|
{
|
||||||
|
it.second->SetUnreachable (true);
|
||||||
|
total--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (total > 300)
|
||||||
|
{
|
||||||
|
if (ts > it.second->GetTimestamp () + 30*3600*1000LL) // 30 hours
|
||||||
|
{
|
||||||
|
it.second->SetUnreachable (true);
|
||||||
|
total--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (total > 120) {
|
} else if (total > 120) {
|
||||||
if (ts > it.second->GetTimestamp () + 72*3600*1000LL) { // 72 hours
|
if (ts > it.second->GetTimestamp () + 72*3600*1000LL) { // 72 hours
|
||||||
@ -418,37 +452,14 @@ namespace data
|
|||||||
LogPrint (eLogError, "NetDb: no outbound tunnels for DatabaseStore reply found");
|
LogPrint (eLogError, "NetDb: no outbound tunnels for DatabaseStore reply found");
|
||||||
}
|
}
|
||||||
offset += 32;
|
offset += 32;
|
||||||
|
|
||||||
if (context.IsFloodfill ())
|
|
||||||
{
|
|
||||||
// flood it
|
|
||||||
auto floodMsg = NewI2NPShortMessage ();
|
|
||||||
uint8_t * payload = floodMsg->GetPayload ();
|
|
||||||
memcpy (payload, buf, 33); // key + type
|
|
||||||
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token
|
|
||||||
auto msgLen = len - offset;
|
|
||||||
floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen;
|
|
||||||
if (floodMsg->len < floodMsg->maxLen)
|
|
||||||
{
|
|
||||||
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + offset, msgLen);
|
|
||||||
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
|
||||||
std::set<IdentHash> excluded;
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
auto floodfill = GetClosestFloodfill (ident, excluded);
|
|
||||||
if (floodfill)
|
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), floodMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint (eLogError, "Database store message is too long ", floodMsg->len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
size_t payloadOffset = offset;
|
||||||
|
|
||||||
|
bool updated = false;
|
||||||
if (buf[DATABASE_STORE_TYPE_OFFSET]) // type
|
if (buf[DATABASE_STORE_TYPE_OFFSET]) // type
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet");
|
LogPrint (eLogDebug, "NetDb: store request: LeaseSet");
|
||||||
AddLeaseSet (ident, buf + offset, len - offset, m->from);
|
updated = AddLeaseSet (ident, buf + offset, len - offset, m->from);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -463,7 +474,34 @@ namespace data
|
|||||||
uint8_t uncompressed[2048];
|
uint8_t uncompressed[2048];
|
||||||
size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048);
|
size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048);
|
||||||
if (uncompressedSize)
|
if (uncompressedSize)
|
||||||
AddRouterInfo (ident, uncompressed, uncompressedSize);
|
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyToken && context.IsFloodfill () && updated)
|
||||||
|
{
|
||||||
|
// flood updated
|
||||||
|
auto floodMsg = NewI2NPShortMessage ();
|
||||||
|
uint8_t * payload = floodMsg->GetPayload ();
|
||||||
|
memcpy (payload, buf, 33); // key + type
|
||||||
|
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token
|
||||||
|
auto msgLen = len - payloadOffset;
|
||||||
|
floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen;
|
||||||
|
if (floodMsg->len < floodMsg->maxLen)
|
||||||
|
{
|
||||||
|
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
|
||||||
|
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||||
|
std::set<IdentHash> excluded;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
auto floodfill = GetClosestFloodfill (ident, excluded);
|
||||||
|
if (floodfill)
|
||||||
|
transports.SendMessage (floodfill->GetIdentHash (), floodMsg);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Database store message is too long ", floodMsg->len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,7 +665,7 @@ namespace data
|
|||||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
|
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
|
||||||
{
|
{
|
||||||
auto leaseSet = FindLeaseSet (ident);
|
auto leaseSet = FindLeaseSet (ident);
|
||||||
if (leaseSet) // we don't send back our LeaseSets
|
if (leaseSet && !leaseSet->IsExpired ()) // we don't send back our LeaseSets
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found");
|
LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found");
|
||||||
replyMsg = CreateDatabaseStoreMsg (leaseSet);
|
replyMsg = CreateDatabaseStoreMsg (leaseSet);
|
||||||
@ -824,12 +862,15 @@ namespace data
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
|
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
|
||||||
const std::set<IdentHash>& excluded) const
|
const std::set<IdentHash>& excluded, bool closeThanUsOnly) const
|
||||||
{
|
{
|
||||||
std::shared_ptr<const RouterInfo> r;
|
std::shared_ptr<const RouterInfo> r;
|
||||||
XORMetric minMetric;
|
XORMetric minMetric;
|
||||||
IdentHash destKey = CreateRoutingKey (destination);
|
IdentHash destKey = CreateRoutingKey (destination);
|
||||||
minMetric.SetMax ();
|
if (closeThanUsOnly)
|
||||||
|
minMetric = destKey ^ i2p::context.GetIdentHash ();
|
||||||
|
else
|
||||||
|
minMetric.SetMax ();
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
for (auto it: m_Floodfills)
|
for (auto it: m_Floodfills)
|
||||||
{
|
{
|
||||||
|
11
NetDb.h
11
NetDb.h
@ -17,6 +17,7 @@
|
|||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
#include "Reseed.h"
|
#include "Reseed.h"
|
||||||
#include "NetDbRequests.h"
|
#include "NetDbRequests.h"
|
||||||
|
#include "Family.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -32,9 +33,9 @@ namespace data
|
|||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
void AddRouterInfo (const uint8_t * buf, int len);
|
bool AddRouterInfo (const uint8_t * buf, int len);
|
||||||
void AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
|
bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
|
||||||
void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
std::shared_ptr<RouterInfo> FindRouter (const IdentHash& ident) const;
|
std::shared_ptr<RouterInfo> FindRouter (const IdentHash& ident) const;
|
||||||
std::shared_ptr<LeaseSet> FindLeaseSet (const IdentHash& destination) const;
|
std::shared_ptr<LeaseSet> FindLeaseSet (const IdentHash& destination) const;
|
||||||
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
||||||
@ -50,7 +51,7 @@ namespace data
|
|||||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter () const;
|
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter () const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomIntroducer () const;
|
std::shared_ptr<const RouterInfo> GetRandomIntroducer () const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||||
std::set<IdentHash>& excluded) const;
|
std::set<IdentHash>& excluded) const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
@ -59,6 +60,7 @@ namespace data
|
|||||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
void Reseed ();
|
void Reseed ();
|
||||||
|
Families& GetFamilies () { return m_Families; };
|
||||||
|
|
||||||
// for web interface
|
// for web interface
|
||||||
int GetNumRouters () const { return m_RouterInfos.size (); };
|
int GetNumRouters () const { return m_RouterInfos.size (); };
|
||||||
@ -94,6 +96,7 @@ namespace data
|
|||||||
|
|
||||||
GzipInflator m_Inflator;
|
GzipInflator m_Inflator;
|
||||||
Reseeder * m_Reseeder;
|
Reseeder * m_Reseeder;
|
||||||
|
Families m_Families;
|
||||||
|
|
||||||
friend class NetDbRequests;
|
friend class NetDbRequests;
|
||||||
NetDbRequests m_Requests;
|
NetDbRequests m_Requests;
|
||||||
|
@ -26,15 +26,16 @@ namespace data
|
|||||||
static std::vector<std::string> httpsReseedHostList =
|
static std::vector<std::string> httpsReseedHostList =
|
||||||
{
|
{
|
||||||
"https://reseed.i2p-projekt.de/", // Only HTTPS
|
"https://reseed.i2p-projekt.de/", // Only HTTPS
|
||||||
"https://i2pseed.zarrenspry.info/", // Only HTTPS and SU3 (v3) support
|
//"https://i2pseed.zarrenspry.info/", // Only HTTPS and SU3 (v3) support
|
||||||
"https://i2p.mooo.com/netDb/",
|
"https://i2p.mooo.com/netDb/",
|
||||||
"https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required
|
"https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required
|
||||||
"https://us.reseed.i2p2.no:444/",
|
"https://us.reseed.i2p2.no:444/",
|
||||||
"https://uk.reseed.i2p2.no:444/",
|
"https://uk.reseed.i2p2.no:444/",
|
||||||
"https://www.torontocrypto.org:8443/"
|
"https://www.torontocrypto.org:8443/",
|
||||||
|
"https://i2p-0.manas.ca:8443/"
|
||||||
"https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support
|
"https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support
|
||||||
"https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support
|
"https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support
|
||||||
"https://ieb9oopo.mooo.com/" // Only HTTPS and SU3 (v3) support
|
"https://download.xxlspeed.com/" // Only HTTPS and SU3 (v3) support
|
||||||
};
|
};
|
||||||
|
|
||||||
Reseeder::Reseeder()
|
Reseeder::Reseeder()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "NetDb.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@ -262,11 +263,26 @@ namespace data
|
|||||||
if (!strcmp (key, "caps"))
|
if (!strcmp (key, "caps"))
|
||||||
ExtractCaps (value);
|
ExtractCaps (value);
|
||||||
// check netId
|
// check netId
|
||||||
if (!strcmp (key, "netId") && atoi (value) != I2PD_NET_ID)
|
else if (!strcmp (key, "netId") && atoi (value) != I2PD_NET_ID)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Unexpected netid=", value);
|
LogPrint (eLogError, "Unexpected netid=", value);
|
||||||
m_IsUnreachable = true;
|
m_IsUnreachable = true;
|
||||||
}
|
}
|
||||||
|
// family
|
||||||
|
else if (!strcmp (key, "family"))
|
||||||
|
{
|
||||||
|
m_Family = value;
|
||||||
|
boost::to_lower (m_Family);
|
||||||
|
}
|
||||||
|
else if (!strcmp (key, "family.sig"))
|
||||||
|
{
|
||||||
|
if (!netdb.GetFamilies ().VerifyFamily (m_Family, GetIdentHash (), value))
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "RouterInfo: family signature verification failed");
|
||||||
|
m_Family.clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,6 +475,14 @@ namespace data
|
|||||||
s.write (properties.str ().c_str (), properties.str ().size ());
|
s.write (properties.str ().c_str (), properties.str ().size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const
|
||||||
|
{
|
||||||
|
if (!m_RouterIdentity) return false;
|
||||||
|
size_t size = m_RouterIdentity->GetFullLen ();
|
||||||
|
if (size + 8 > len) return false;
|
||||||
|
return bufbe64toh (buf + size) > m_Timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
const uint8_t * RouterInfo::LoadBuffer ()
|
const uint8_t * RouterInfo::LoadBuffer ()
|
||||||
{
|
{
|
||||||
if (!m_Buffer)
|
if (!m_Buffer)
|
||||||
|
@ -157,7 +157,8 @@ namespace data
|
|||||||
|
|
||||||
void Update (const uint8_t * buf, int len);
|
void Update (const uint8_t * buf, int len);
|
||||||
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
|
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
|
||||||
|
bool IsNewer (const uint8_t * buf, size_t len) const;
|
||||||
|
|
||||||
// implements RoutingDestination
|
// implements RoutingDestination
|
||||||
const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); };
|
const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); };
|
||||||
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; };
|
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; };
|
||||||
@ -179,7 +180,7 @@ namespace data
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string m_FullPath;
|
std::string m_FullPath, m_Family;
|
||||||
std::shared_ptr<const IdentityEx> m_RouterIdentity;
|
std::shared_ptr<const IdentityEx> m_RouterIdentity;
|
||||||
uint8_t * m_Buffer;
|
uint8_t * m_Buffer;
|
||||||
size_t m_BufferLen;
|
size_t m_BufferLen;
|
||||||
|
@ -88,7 +88,7 @@ namespace stream
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogPrint (eLogDebug, "Streaming: Received seqn=", receivedSeqn);
|
LogPrint (eLogDebug, "Streaming: Received seqn=", receivedSeqn);
|
||||||
if (isSyn || receivedSeqn == m_LastReceivedSequenceNumber + 1)
|
if (receivedSeqn == m_LastReceivedSequenceNumber + 1)
|
||||||
{
|
{
|
||||||
// we have received next in sequence message
|
// we have received next in sequence message
|
||||||
ProcessPacket (packet);
|
ProcessPacket (packet);
|
||||||
@ -113,7 +113,9 @@ namespace stream
|
|||||||
if (!m_IsAckSendScheduled)
|
if (!m_IsAckSendScheduled)
|
||||||
{
|
{
|
||||||
m_IsAckSendScheduled = true;
|
m_IsAckSendScheduled = true;
|
||||||
m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ACK_SEND_TIMEOUT));
|
auto ackTimeout = m_RTT/10;
|
||||||
|
if (ackTimeout > ACK_SEND_TIMEOUT) ackTimeout = ACK_SEND_TIMEOUT;
|
||||||
|
m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout));
|
||||||
m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
|
m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
@ -274,7 +276,7 @@ namespace stream
|
|||||||
if (!seqn && m_RoutingSession) // first message confirmed
|
if (!seqn && m_RoutingSession) // first message confirmed
|
||||||
m_RoutingSession->SetSharedRoutingPath (
|
m_RoutingSession->SetSharedRoutingPath (
|
||||||
std::make_shared<i2p::garlic::GarlicRoutingPath> (
|
std::make_shared<i2p::garlic::GarlicRoutingPath> (
|
||||||
i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, 0}));
|
i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, m_RTT, 0, 0}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@ -605,6 +607,8 @@ namespace stream
|
|||||||
{
|
{
|
||||||
m_CurrentOutboundTunnel = routingPath->outboundTunnel;
|
m_CurrentOutboundTunnel = routingPath->outboundTunnel;
|
||||||
m_CurrentRemoteLease = routingPath->remoteLease;
|
m_CurrentRemoteLease = routingPath->remoteLease;
|
||||||
|
m_RTT = routingPath->rtt;
|
||||||
|
m_RTO = m_RTT*1.5; // TODO: implement it better
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -619,7 +623,7 @@ namespace stream
|
|||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
if (!m_CurrentRemoteLease || ts >= m_CurrentRemoteLease->endDate - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000)
|
if (!m_CurrentRemoteLease || ts >= m_CurrentRemoteLease->endDate - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000)
|
||||||
UpdateCurrentRemoteLease (true);
|
UpdateCurrentRemoteLease (true);
|
||||||
if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate)
|
if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD)
|
||||||
{
|
{
|
||||||
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||||
for (auto it: packets)
|
for (auto it: packets)
|
||||||
@ -769,6 +773,7 @@ namespace stream
|
|||||||
m_RemoteLeaseSet = nullptr;
|
m_RemoteLeaseSet = nullptr;
|
||||||
m_CurrentRemoteLease = nullptr;
|
m_CurrentRemoteLease = nullptr;
|
||||||
// re-request expired
|
// re-request expired
|
||||||
|
m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -201,7 +201,14 @@ namespace tunnel
|
|||||||
|
|
||||||
void TunnelPool::TestTunnels ()
|
void TunnelPool::TestTunnels ()
|
||||||
{
|
{
|
||||||
for (auto it: m_Tests)
|
decltype(m_Tests) tests;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_TestsMutex);
|
||||||
|
tests = m_Tests;
|
||||||
|
m_Tests.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it: tests)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed");
|
LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed");
|
||||||
// if test failed again with another tunnel we consider it failed
|
// if test failed again with another tunnel we consider it failed
|
||||||
@ -232,7 +239,7 @@ namespace tunnel
|
|||||||
it.second.second->SetState (eTunnelStateTestFailed);
|
it.second.second->SetState (eTunnelStateTestFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_Tests.clear ();
|
|
||||||
// new tests
|
// new tests
|
||||||
auto it1 = m_OutboundTunnels.begin ();
|
auto it1 = m_OutboundTunnels.begin ();
|
||||||
auto it2 = m_InboundTunnels.begin ();
|
auto it2 = m_InboundTunnels.begin ();
|
||||||
@ -253,7 +260,10 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
uint32_t msgID;
|
uint32_t msgID;
|
||||||
RAND_bytes ((uint8_t *)&msgID, 4);
|
RAND_bytes ((uint8_t *)&msgID, 4);
|
||||||
m_Tests[msgID] = std::make_pair (*it1, *it2);
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_TestsMutex);
|
||||||
|
m_Tests[msgID] = std::make_pair (*it1, *it2);
|
||||||
|
}
|
||||||
(*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
|
(*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (),
|
||||||
CreateDeliveryStatusMsg (msgID));
|
CreateDeliveryStatusMsg (msgID));
|
||||||
it1++; it2++;
|
it1++; it2++;
|
||||||
@ -276,16 +286,26 @@ namespace tunnel
|
|||||||
buf += 4;
|
buf += 4;
|
||||||
uint64_t timestamp = bufbe64toh (buf);
|
uint64_t timestamp = bufbe64toh (buf);
|
||||||
|
|
||||||
auto it = m_Tests.find (msgID);
|
decltype(m_Tests)::mapped_type test;
|
||||||
if (it != m_Tests.end ())
|
bool found = false;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_TestsMutex);
|
||||||
|
auto it = m_Tests.find (msgID);
|
||||||
|
if (it != m_Tests.end ())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
test = it->second;
|
||||||
|
m_Tests.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
{
|
{
|
||||||
// restore from test failed state if any
|
// restore from test failed state if any
|
||||||
if (it->second.first->GetState () == eTunnelStateTestFailed)
|
if (test.first->GetState () == eTunnelStateTestFailed)
|
||||||
it->second.first->SetState (eTunnelStateEstablished);
|
test.first->SetState (eTunnelStateEstablished);
|
||||||
if (it->second.second->GetState () == eTunnelStateTestFailed)
|
if (test.second->GetState () == eTunnelStateTestFailed)
|
||||||
it->second.second->SetState (eTunnelStateEstablished);
|
test.second->SetState (eTunnelStateEstablished);
|
||||||
LogPrint (eLogDebug, "Tunnels: test of ", it->first, " successful. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds");
|
LogPrint (eLogDebug, "Tunnels: test of ", msgID, " successful. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds");
|
||||||
m_Tests.erase (it);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,9 @@ namespace tunnel
|
|||||||
bool IsActive () const { return m_IsActive; };
|
bool IsActive () const { return m_IsActive; };
|
||||||
void SetActive (bool isActive) { m_IsActive = isActive; };
|
void SetActive (bool isActive) { m_IsActive = isActive; };
|
||||||
void DetachTunnels ();
|
void DetachTunnels ();
|
||||||
|
|
||||||
|
int GetNumInboundTunnels () const { return m_NumInboundTunnels; };
|
||||||
|
int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -74,6 +77,7 @@ namespace tunnel
|
|||||||
std::set<std::shared_ptr<InboundTunnel>, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
std::set<std::shared_ptr<InboundTunnel>, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
||||||
mutable std::mutex m_OutboundTunnelsMutex;
|
mutable std::mutex m_OutboundTunnelsMutex;
|
||||||
std::set<std::shared_ptr<OutboundTunnel>, TunnelCreationTimeCmp> m_OutboundTunnels;
|
std::set<std::shared_ptr<OutboundTunnel>, TunnelCreationTimeCmp> m_OutboundTunnels;
|
||||||
|
mutable std::mutex m_TestsMutex;
|
||||||
std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
|
std::map<uint32_t, std::pair<std::shared_ptr<OutboundTunnel>, std::shared_ptr<InboundTunnel> > > m_Tests;
|
||||||
bool m_IsActive;
|
bool m_IsActive;
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ set (LIBI2PD_SRC
|
|||||||
"${CMAKE_SOURCE_DIR}/Base.cpp"
|
"${CMAKE_SOURCE_DIR}/Base.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/util.cpp"
|
"${CMAKE_SOURCE_DIR}/util.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
||||||
|
"${CMAKE_SOURCE_DIR}/Family.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Signature.cpp"
|
"${CMAKE_SOURCE_DIR}/Signature.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/api.cpp"
|
"${CMAKE_SOURCE_DIR}/api.cpp"
|
||||||
)
|
)
|
||||||
|
13
contrib/certificates/family/i2p-dev.crt
Normal file
13
contrib/certificates/family/i2p-dev.crt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICCjCCAa2gAwIBAgIEfT9YJTAMBggqhkjOPQQDAgUAMHkxCzAJBgNVBAYTAlhY
|
||||||
|
MQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1v
|
||||||
|
dXMgTmV0d29yazEPMA0GA1UECxMGZmFtaWx5MR8wHQYDVQQDExZpMnAtZGV2LmZh
|
||||||
|
bWlseS5pMnAubmV0MB4XDTE1MTIwOTIxNDIzM1oXDTI1MTIwODIxNDIzM1oweTEL
|
||||||
|
MAkGA1UEBhMCWFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMV
|
||||||
|
STJQIEFub255bW91cyBOZXR3b3JrMQ8wDQYDVQQLEwZmYW1pbHkxHzAdBgNVBAMT
|
||||||
|
FmkycC1kZXYuZmFtaWx5LmkycC5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
|
||||||
|
AAR7FPSglYrxeSPzv74A1fTwjajZWV0TljqEMBS/56juZQB/7xOwrsHFHA0eEEF9
|
||||||
|
dTH64wx3lhV/9sh/stwPU2MToyEwHzAdBgNVHQ4EFgQUQh4uRP1aaX8TJX5dljrS
|
||||||
|
CeFNjcAwDAYIKoZIzj0EAwIFAANJADBGAiEAhXlEKGCjJ4urpi2db3OIMl9pB+9t
|
||||||
|
M+oVtAqBamWvVBICIQDBaIqfwLzFameO5ULgGRMysKQkL0O5mH6xo910YQV8jQ==
|
||||||
|
-----END CERTIFICATE-----
|
34
contrib/certificates/reseed/j_at_torontocrypto.org.crt
Normal file
34
contrib/certificates/reseed/j_at_torontocrypto.org.crt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
@ -1,32 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
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
|
|
||||||
fss8T6gOo19esb/KEMZGZE4pAApakWM=
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,21 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDgDCCAmgCCQCAKEkFUJcEezANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UEBhMC
|
|
||||||
Tk8xDTALBgNVBAgMBE9zbG8xDTALBgNVBAcMBE9zbG8xDDAKBgNVBAoMA0kyUDEM
|
|
||||||
MAoGA1UECwwDSTJQMRcwFQYDVQQDDA4xOTMuMTUwLjEyMS42NjEfMB0GCSqGSIb3
|
|
||||||
DQEJARYQbWVlaEBpMnBtYWlsLm9yZzAeFw0xMzA2MjcxODM2MjhaFw0yMDA2MjUx
|
|
||||||
ODM2MjhaMIGBMQswCQYDVQQGEwJOTzENMAsGA1UECAwET3NsbzENMAsGA1UEBwwE
|
|
||||||
T3NsbzEMMAoGA1UECgwDSTJQMQwwCgYDVQQLDANJMlAxFzAVBgNVBAMMDjE5My4x
|
|
||||||
NTAuMTIxLjY2MR8wHQYJKoZIhvcNAQkBFhBtZWVoQGkycG1haWwub3JnMIIBIjAN
|
|
||||||
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuBuFY4ZFvsbr5l1/s/GeUBLIWQLB
|
|
||||||
nqrRkonrwCyxgjSnnG1uz/Z5nf6QDUjiVnFKMXenLaDn4KCmEi4LjWQllhK9r6pj
|
|
||||||
BRkR7C0DTHq7WqfyvWnGSZZsOJDiH2vLlivV8N9oGdjxvv0N9No3AJcsmLYrxSLi
|
|
||||||
6/JF8xZ2HGuT/oWW6aWvpIOKpIqti865BJw5P5KgYAS24J8vHRFM3FA4dfLNTBA2
|
|
||||||
IGqPqYLQA+2zfOC4z01aArmcYnT1iJLT7krgKnr/BXdJfGQ2GjxkRSt8IwB6WmXA
|
|
||||||
byz6QdNYM/0eubi102/zpD/DrySTU2kc8xKjknGUqBJvVdsL+iLK98uJrQIDAQAB
|
|
||||||
MA0GCSqGSIb3DQEBBQUAA4IBAQCTimMu3X7+ztXxlIFhwGh42GfMjeBYT0NHOLAy
|
|
||||||
ZtQNRqhNvkl3jZ4ERPLxP99+bcAfCX0wgVpgD32OWEZopwveRyMImP8HfFr4NnZ+
|
|
||||||
edbM37fRYiVJv57kbi6O0rhEC7J5JF+fnCaZVLCuvYIrIXTdxTjvxuLhyan6Ej7V
|
|
||||||
7iGDJ8t16tpLVJgcXfRg+dvAa6aDOK6x3w78j0bvh6rhvpOd9sW/Nk3LBKP4Xgkx
|
|
||||||
PHkqm3hNfDIu8Hubeav9SA1kLVMS/uce52VyYMEDauObfC65ds0GRmCtYhZqMvj+
|
|
||||||
FFCbssLraVJE9Hi/ZKGu33jNngDCG+wG+nmleksMYE1yTSRt
|
|
||||||
-----END CERTIFICATE-----
|
|
19
contrib/certificates/ssl/download.xxlspeed.com.crt
Normal file
19
contrib/certificates/ssl/download.xxlspeed.com.crt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDLDCCArKgAwIBAgIJAMOgj4vE9qpcMAoGCCqGSM49BAMEMIHTMQswCQYDVQQG
|
||||||
|
EwJERTEeMBwGA1UECAwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYDVQQHDBVk
|
||||||
|
b3dubG9hZC54eGxzcGVlZC5jb20xHjAcBgNVBAoMFWRvd25sb2FkLnh4bHNwZWVk
|
||||||
|
LmNvbTEeMBwGA1UECwwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYDVQQDDBVk
|
||||||
|
b3dubG9hZC54eGxzcGVlZC5jb20xJDAiBgkqhkiG9w0BCQEWFWRvd25sb2FkLnh4
|
||||||
|
bHNwZWVkLmNvbTAeFw0xNTEyMzAxMTI4NDJaFw0yMTA2MjExMTI4NDJaMIHTMQsw
|
||||||
|
CQYDVQQGEwJERTEeMBwGA1UECAwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYD
|
||||||
|
VQQHDBVkb3dubG9hZC54eGxzcGVlZC5jb20xHjAcBgNVBAoMFWRvd25sb2FkLnh4
|
||||||
|
bHNwZWVkLmNvbTEeMBwGA1UECwwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYD
|
||||||
|
VQQDDBVkb3dubG9hZC54eGxzcGVlZC5jb20xJDAiBgkqhkiG9w0BCQEWFWRvd25s
|
||||||
|
b2FkLnh4bHNwZWVkLmNvbTB2MBAGByqGSM49AgEGBSuBBAAiA2IABFObW+pRshVD
|
||||||
|
gvMPvGdPGji2DAfdvkl3gvpyiQ0PUqxuTxwtBlwBo6cz2cMnkKdActuvE/VOTRG5
|
||||||
|
/z7CcvG7b0+qgrHDffg7C2wWlAN0dSjuoV2Av7VoN1vEU96TCtheSqNQME4wHQYD
|
||||||
|
VR0OBBYEFPbEZH9oidjadUfvsnsh23b1jZnVMB8GA1UdIwQYMBaAFPbEZH9oidja
|
||||||
|
dUfvsnsh23b1jZnVMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwQDaAAwZQIwT1py
|
||||||
|
AV2hLFL/5ZgwmybdaCBBUsj3cGYroXb/Z2BHLDYmH8enK0DhhWyPdN1a7eCsAjEA
|
||||||
|
oQRU7lhXrisckjA2911Q5mA8y2sFAN/PDPrUeU9PI5vDF/ezTi20zULMOqbU1uRz
|
||||||
|
-----END CERTIFICATE-----
|
@ -1,23 +1,23 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDvjCCAyegAwIBAgICZhcwDQYJKoZIhvcNAQEFBQAwdTELMAkGA1UEBhMCVVMx
|
MIIDvTCCAqWgAwIBAgIJAOeW0ejPrHimMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNV
|
||||||
DTALBgNVBAgMBG5vbmUxDTALBgNVBAcMBG5vbmUxDTALBgNVBAoMBG5vbmUxDTAL
|
BAYTAlVTMQ0wCwYDVQQIDARub25lMQ0wCwYDVQQHDARub25lMQ0wCwYDVQQKDARu
|
||||||
BgNVBAsMBG5vbmUxFTATBgNVBAMMDGkycC5tb29vLmNvbTETMBEGCSqGSIb3DQEJ
|
b25lMQ0wCwYDVQQLDARub25lMRUwEwYDVQQDDAxpMnAubW9vby5jb20xEzARBgkq
|
||||||
ARYEbm9uZTAeFw0xMTEwMjMyMTM2NDFaFw0xOTEwMjMyMTM2NDFaMGYxCzAJBgNV
|
hkiG9w0BCQEWBG5vbmUwHhcNMTUwMjA4MTczMzA5WhcNMTkwMzE5MTczMzA5WjB1
|
||||||
BAYTAlVTMQ0wCwYDVQQIDARub25lMQ0wCwYDVQQKDARub25lMQ0wCwYDVQQLDARu
|
MQswCQYDVQQGEwJVUzENMAsGA1UECAwEbm9uZTENMAsGA1UEBwwEbm9uZTENMAsG
|
||||||
b25lMRUwEwYDVQQDDAxpMnAubW9vby5jb20xEzARBgkqhkiG9w0BCQEWBG5vbmUw
|
A1UECgwEbm9uZTENMAsGA1UECwwEbm9uZTEVMBMGA1UEAwwMaTJwLm1vb28uY29t
|
||||||
ggGPMA0GCSqGSIb3DQEBAQUAA4IBfAAwggF3AoIBbgMG1O7HRVa7UoiKbQTmKy5m
|
MRMwEQYJKoZIhvcNAQkBFgRub25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||||
x79Na8vjD3etcOwfc4TSenQFvn+GbAWkJwKpM8uvOcgj1CxNeHWdSaeTFH1OwJsw
|
CgKCAQEAqxej7oRl9GOb8benIBCENrJXoow1iWhI9M+2nU0SaonrCDql5M2YMlwd
|
||||||
vl3leJ7clMdo3hpQDhPeGzBLyOiWwFHVn15YKa9xcM7S9Op5Q6rKBHUyyx1vGSz+
|
HzYUWtFbRjz2NinjB0fgFq9cfzHfr1Sc8k/OeGg1jvNfqt8wWo9tryQNjiHtDQUZ
|
||||||
/NBmkktpI6rcGFfP3ISRL0auR+db+adWv4TS6W8YiwQIVZNbSlKP6FNO9Mv1kxQZ
|
6lQ5T13I+lj0CBasowgbApKQfrYjvaeuTaVYTfP8IVA60hoUQ+sy9JN+Unsx3/0Y
|
||||||
KoHPn8vT/LtAh1fcI6ryBuy3F5oHfbGumIwsS5dpowryFxQzwg5vtMA7AMCMKyXv
|
PLLd98+bT27qYuBNRB1g/ifUTd9Wosj2PevGBlCxYDaUjmCG4Q8kcQr87KvM6RTu
|
||||||
hP/W6OuaaEP5MCIxkWjQs35gOYa8eF1dLoy3AD9yVVhoNrA8Bc5FnVFJ32Qv7agy
|
3AV61s/Wyy1j2YemlGG/ZhJ44YnlVMSu1vTjt9HInVf3lRRx/+RzbQO3lqeVC8LC
|
||||||
qRY85cXBA6hT/Qzs/wWwp7WrrnZuifaSv/u/Ayi5vX42/bf86PSM2IRNIESoA98A
|
Bq3KbSlfJVx4vHslfHwBFw9A4rmD1QIDAQABo1AwTjAdBgNVHQ4EFgQUsSUvX0ED
|
||||||
NFz4U2KGq9s1K2JbkQmnFy8IU0w7CMq6PvNEm/uNjSk6OE1rcCXML+EuX0zmXy8d
|
yivB67iksVwZ+b8vLtQwHwYDVR0jBBgwFoAUsSUvX0EDyivB67iksVwZ+b8vLtQw
|
||||||
PjRbLzC9csSg2CqMtQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
|
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAde4wts7Q8TylFEc38ftJ
|
||||||
Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUdjuOczdG
|
2f285fFIR7P1SSbBcHPK2eBwLEg0zJyFrCeiHuEpPrn+d5GqL2zOskjfcESGmDBT
|
||||||
hUpYzH0UXqKrOleT8GkwHwYDVR0jBBgwFoAU+SKWC49cM5sCodv89AFin3pkS0Yw
|
aFajj8jPBJj/AmpkdWJG6a1YKro5tu9wrlenGwHOHu2/Cl0IJvafxrOs2x4G+2Nl
|
||||||
DQYJKoZIhvcNAQEFBQADgYEAKYyWlDIStjjbn/ZzVScKR174I8whTbdqrX/vp9dr
|
5Hcw/FIy8mK7eIch4pACfi0zNMZ6KMCKfX9bxPrQo78WdBfVjbrIBlgyOQJ5NJEF
|
||||||
2hMv5m4F+aswX4Jr58WneKg2LvRaL6xEhoL7OAQ6aB/7xVSpDjIrrBLZd513NAam
|
JlWvS7Butv7eERi4I2huN5VRJSCFzjbuO+tjP3I8IB6WgdBmTeqq8ObtXRgahBuD
|
||||||
X6bOPYJ6IH7Vw9ClFY3AlfzsNlgRMXno7rySKKzhg24kusNwKDH2yCphZy4BgjMn
|
ZmkvqVSfIzK5JN4GjO8FOdCBomuwm9A92kgmAptwQwAHM9qCDJpH8L07/7poxlGb
|
||||||
y6A=
|
iA==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDvTCCAqWgAwIBAgIJAOeW0ejPrHimMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNV
|
|
||||||
BAYTAlVTMQ0wCwYDVQQIDARub25lMQ0wCwYDVQQHDARub25lMQ0wCwYDVQQKDARu
|
|
||||||
b25lMQ0wCwYDVQQLDARub25lMRUwEwYDVQQDDAxpMnAubW9vby5jb20xEzARBgkq
|
|
||||||
hkiG9w0BCQEWBG5vbmUwHhcNMTUwMjA4MTczMzA5WhcNMTkwMzE5MTczMzA5WjB1
|
|
||||||
MQswCQYDVQQGEwJVUzENMAsGA1UECAwEbm9uZTENMAsGA1UEBwwEbm9uZTENMAsG
|
|
||||||
A1UECgwEbm9uZTENMAsGA1UECwwEbm9uZTEVMBMGA1UEAwwMaTJwLm1vb28uY29t
|
|
||||||
MRMwEQYJKoZIhvcNAQkBFgRub25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
||||||
CgKCAQEAqxej7oRl9GOb8benIBCENrJXoow1iWhI9M+2nU0SaonrCDql5M2YMlwd
|
|
||||||
HzYUWtFbRjz2NinjB0fgFq9cfzHfr1Sc8k/OeGg1jvNfqt8wWo9tryQNjiHtDQUZ
|
|
||||||
6lQ5T13I+lj0CBasowgbApKQfrYjvaeuTaVYTfP8IVA60hoUQ+sy9JN+Unsx3/0Y
|
|
||||||
PLLd98+bT27qYuBNRB1g/ifUTd9Wosj2PevGBlCxYDaUjmCG4Q8kcQr87KvM6RTu
|
|
||||||
3AV61s/Wyy1j2YemlGG/ZhJ44YnlVMSu1vTjt9HInVf3lRRx/+RzbQO3lqeVC8LC
|
|
||||||
Bq3KbSlfJVx4vHslfHwBFw9A4rmD1QIDAQABo1AwTjAdBgNVHQ4EFgQUsSUvX0ED
|
|
||||||
yivB67iksVwZ+b8vLtQwHwYDVR0jBBgwFoAUsSUvX0EDyivB67iksVwZ+b8vLtQw
|
|
||||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAde4wts7Q8TylFEc38ftJ
|
|
||||||
2f285fFIR7P1SSbBcHPK2eBwLEg0zJyFrCeiHuEpPrn+d5GqL2zOskjfcESGmDBT
|
|
||||||
aFajj8jPBJj/AmpkdWJG6a1YKro5tu9wrlenGwHOHu2/Cl0IJvafxrOs2x4G+2Nl
|
|
||||||
5Hcw/FIy8mK7eIch4pACfi0zNMZ6KMCKfX9bxPrQo78WdBfVjbrIBlgyOQJ5NJEF
|
|
||||||
JlWvS7Butv7eERi4I2huN5VRJSCFzjbuO+tjP3I8IB6WgdBmTeqq8ObtXRgahBuD
|
|
||||||
ZmkvqVSfIzK5JN4GjO8FOdCBomuwm9A92kgmAptwQwAHM9qCDJpH8L07/7poxlGb
|
|
||||||
iA==
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,25 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIESzCCAzOgAwIBAgIJAKII1waVnWddMA0GCSqGSIb3DQEBCwUAMIG7MQswCQYD
|
|
||||||
VQQGEwJERTEaMBgGA1UECAwRaWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAcMEWll
|
|
||||||
Yjlvb3BvLm1vb28uY29tMRowGAYDVQQKDBFpZWI5b29wby5tb29vLmNvbTEaMBgG
|
|
||||||
A1UECwwRaWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAMMEWllYjlvb3BvLm1vb28u
|
|
||||||
Y29tMSAwHgYJKoZIhvcNAQkBFhFpZWI5b29wby5tb29vLmNvbTAeFw0xNDExMjIx
|
|
||||||
MzQzNThaFw0yMDA1MTQxMzQzNThaMIG7MQswCQYDVQQGEwJERTEaMBgGA1UECAwR
|
|
||||||
aWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAcMEWllYjlvb3BvLm1vb28uY29tMRow
|
|
||||||
GAYDVQQKDBFpZWI5b29wby5tb29vLmNvbTEaMBgGA1UECwwRaWViOW9vcG8ubW9v
|
|
||||||
by5jb20xGjAYBgNVBAMMEWllYjlvb3BvLm1vb28uY29tMSAwHgYJKoZIhvcNAQkB
|
|
||||||
FhFpZWI5b29wby5tb29vLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
|
||||||
ggEBAMhcnkSifOMw5bd66UlvYVsc42H22Nuy64qhtJHtggofrwBooF38kRCBVFL8
|
|
||||||
9Xjzr0xsSshvO6p7E+CEUtA8v55l5vNbUTAvGP9WmzeZyZuCFg9Heo3orNMbIK7m
|
|
||||||
ppwKhwh6tFEIEpUTz/+xF5NRt0+CqcS4aNHuH3JPwNugfTBuSa86GeSaqL7K4eEZ
|
|
||||||
bZXqQ16Onvi0yyMqRJDp/ijRFxr2eKGPWb55kuRSET9PxVhlgRKULZkr39Dh9q1c
|
|
||||||
wb9lAMLMRZIzPVnyvC9jWkIqSDl5bkAAto0n1Jkw92rRp6EVKgSLA/4vl9wTb6xf
|
|
||||||
WfT5cs7pykAE0WXBr9TqpS3okncCAwEAAaNQME4wHQYDVR0OBBYEFGeEOHhWiKwZ
|
|
||||||
TGbc7uuK3DD7YjYZMB8GA1UdIwQYMBaAFGeEOHhWiKwZTGbc7uuK3DD7YjYZMAwG
|
|
||||||
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAzRA/0OpJtCO4kQkTn/hux9
|
|
||||||
dRi9T6B54Xav5jG53iAPLTeMxsaLkvweh2pZ3kvEUrQhvW0JF8QBrHTsgxzb4Wd6
|
|
||||||
FNDHSgJbZv3uCjFtWeuUh+GTG1k9uwgNIEnx7J9Vp0JCi4ezi/HMNI7c+LjinM9f
|
|
||||||
hrAzclkeRPLYg645DkxckLyDUbrc9v1qWFoTpezXSBPO7n3Wk4sCytdoA1FkTdXh
|
|
||||||
RF4BWCl/3uOxcrn0TqoC9vCh8RcxnllOiOO5j4+PQ1Z6NkQ/5oRCK/jjaWc3Lr6/
|
|
||||||
FicOZJe29BVnrPGynqe0Ky1o+kTdXFflKowfr7g8dwn8k9YavjtGbl1ZSHeuMF8=
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,24 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEDzCCAvegAwIBAgIJAMsPNG1k0yV4MA0GCSqGSIb3DQEBCwUAMIGdMQswCQYD
|
|
||||||
VQQGEwJERTEVMBMGA1UECAwMbGluay5teDI0LmV1MRUwEwYDVQQHDAxsaW5rLm14
|
|
||||||
MjQuZXUxFTATBgNVBAoMDGxpbmsubXgyNC5ldTEVMBMGA1UECwwMbGluay5teDI0
|
|
||||||
LmV1MRUwEwYDVQQDDAxsaW5rLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDGxpbmsu
|
|
||||||
bXgyNC5ldTAeFw0xNDExMTkxOTE4NTRaFw0yMDA1MTExOTE4NTRaMIGdMQswCQYD
|
|
||||||
VQQGEwJERTEVMBMGA1UECAwMbGluay5teDI0LmV1MRUwEwYDVQQHDAxsaW5rLm14
|
|
||||||
MjQuZXUxFTATBgNVBAoMDGxpbmsubXgyNC5ldTEVMBMGA1UECwwMbGluay5teDI0
|
|
||||||
LmV1MRUwEwYDVQQDDAxsaW5rLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDGxpbmsu
|
|
||||||
bXgyNC5ldTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL8modDBRkyh
|
|
||||||
SHSm92pTfguO3F6n5ocsBJ4vaVoosYq3ILCsapjqmynMHZUef6gEB7+Gn5cKXsH2
|
|
||||||
JaKOeb8DHrOFCaxfj187x1QfZj1UNMQblx2T9q4th12tqp+k4JuLwgemr+2uAUpM
|
|
||||||
xx/uHRJXD0hf67+fHQFYNVfa+WvT46xlKGsWDQ0LBsA/z4YGnyeaV4PrS5nj3euA
|
|
||||||
IbdfDj7rJea3bfhSqYA1ZH1cquKlsXOOYO5cIcXsa5dxDWX51QS+i7+ocph+JN1X
|
|
||||||
dRh6ZirE9OXZVXwXXVRnJSYjgBlP/DQBdE7YkE1R3LyCVZsgxJaaLV/ujijOIK61
|
|
||||||
SqEhHvFNRe0CAwEAAaNQME4wHQYDVR0OBBYEFB6XRz6VZlrAE+3xL6AyKrkq+y2X
|
|
||||||
MB8GA1UdIwQYMBaAFB6XRz6VZlrAE+3xL6AyKrkq+y2XMAwGA1UdEwQFMAMBAf8w
|
|
||||||
DQYJKoZIhvcNAQELBQADggEBADhxBA5GHisDVf5a+1hIi7FBGBjJJLqzlaKh+bFB
|
|
||||||
gTCYfk3F4wYzndr1HpdCZSSYDtY3mXFNMWQCpwvwvy1DM+9AMRY68wKNXHa/WypW
|
|
||||||
zQSqTfEH8cdaIXUALB7pdWFVr3rx0f7/8I0Gj/ByUbJ94rzd22vduX5riY0Rag6B
|
|
||||||
dPtW0M9bJrC1AIjexzDcStupj9v/ceGYZQYC4zb2tZ7Ek/6q+vei8TxWZjku7Dl4
|
|
||||||
YRPXXufyB24uQ1hJVy2fSyIJ63tIRJoEFLBNaKDOB53i10xLWBcsJpXKY57AOQMn
|
|
||||||
flqW4HG8uGJ/o1WjhiOB9eI7T9toy08zNzt+kSI/blFIoek=
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,33 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
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
|
|
||||||
fWThMdwk1kTrWxLooiVrS5A1hXqADqE=
|
|
||||||
-----END CERTIFICATE-----
|
|
33
contrib/certificates/ssl/reseed.i2p.vzaws.com.crt
Normal file
33
contrib/certificates/ssl/reseed.i2p.vzaws.com.crt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
17
contrib/certificates/ssl/user.mx24.eu.crt
Normal file
17
contrib/certificates/ssl/user.mx24.eu.crt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICwDCCAkagAwIBAgIJAKXCoCBjd/C0MAoGCCqGSM49BAMEMIGdMQswCQYDVQQG
|
||||||
|
EwJERTEVMBMGA1UECAwMdXNlci5teDI0LmV1MRUwEwYDVQQHDAx1c2VyLm14MjQu
|
||||||
|
ZXUxFTATBgNVBAoMDHVzZXIubXgyNC5ldTEVMBMGA1UECwwMdXNlci5teDI0LmV1
|
||||||
|
MRUwEwYDVQQDDAx1c2VyLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDHVzZXIubXgy
|
||||||
|
NC5ldTAeFw0xNTA5MDMxNjMyNDVaFw0yMTAyMjMxNjMyNDVaMIGdMQswCQYDVQQG
|
||||||
|
EwJERTEVMBMGA1UECAwMdXNlci5teDI0LmV1MRUwEwYDVQQHDAx1c2VyLm14MjQu
|
||||||
|
ZXUxFTATBgNVBAoMDHVzZXIubXgyNC5ldTEVMBMGA1UECwwMdXNlci5teDI0LmV1
|
||||||
|
MRUwEwYDVQQDDAx1c2VyLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDHVzZXIubXgy
|
||||||
|
NC5ldTB2MBAGByqGSM49AgEGBSuBBAAiA2IABPlKs5fYTqVhIOMiR6U9U4TimxS3
|
||||||
|
P5NBDVzeeIAgbw5KBC8UImScZVt9g4V1wQe5kPs7TxA2BfanAPZ+ekQiRRvMVQxD
|
||||||
|
bSlRYupEWhq5BrJI6Lq/HDc7VJe9UUWffWKUoKNQME4wHQYDVR0OBBYEFBGJ0Yr+
|
||||||
|
PZXnrk5RafQEALUpAU6ZMB8GA1UdIwQYMBaAFBGJ0Yr+PZXnrk5RafQEALUpAU6Z
|
||||||
|
MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwQDaAAwZQIxAPcovePHMCosrAQNzS5i
|
||||||
|
VDUiyPNLOxHyRBm79yKXGl13LxysB6OK+2M7t8j8E/udBwIwXVVjxN6aSgXYTJ7d
|
||||||
|
p+Hg/2CuBMwf41/ENRcYQA+oGS9bU6A+7U9KJ1xTWWoqsUEs
|
||||||
|
-----END CERTIFICATE-----
|
@ -23,6 +23,13 @@ After successfull build i2pd could be installed with:
|
|||||||
```bash
|
```bash
|
||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
or you can just use 'make' once you have all dependacies (boost and openssl) installed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/PurpleI2P/i2pd.git
|
||||||
|
cd i2pd
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
Debian/Ubuntu
|
Debian/Ubuntu
|
||||||
-------------
|
-------------
|
||||||
|
@ -4,7 +4,8 @@ LIB_SRC = \
|
|||||||
Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \
|
Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \
|
||||||
SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
|
SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
|
||||||
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
|
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
|
||||||
Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp util.cpp api.cpp
|
Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \
|
||||||
|
util.cpp api.cpp
|
||||||
|
|
||||||
LIB_CLIENT_SRC = \
|
LIB_CLIENT_SRC = \
|
||||||
AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \
|
AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \
|
||||||
|
1
util.cpp
1
util.cpp
@ -81,6 +81,7 @@ namespace http
|
|||||||
if (colon != std::string::npos)
|
if (colon != std::string::npos)
|
||||||
{
|
{
|
||||||
std::string field = header.substr (0, colon);
|
std::string field = header.substr (0, colon);
|
||||||
|
boost::to_lower (field);
|
||||||
if (field == i2p::util::http::TRANSFER_ENCODING)
|
if (field == i2p::util::http::TRANSFER_ENCODING)
|
||||||
isChunked = (header.find ("chunked", colon + 1) != std::string::npos);
|
isChunked = (header.find ("chunked", colon + 1) != std::string::npos);
|
||||||
}
|
}
|
||||||
|
13
util.h
13
util.h
@ -12,12 +12,15 @@ namespace util
|
|||||||
{
|
{
|
||||||
namespace http
|
namespace http
|
||||||
{
|
{
|
||||||
const char ETAG[] = "ETag";
|
// in (lower case)
|
||||||
|
const char ETAG[] = "etag"; // ETag
|
||||||
|
const char LAST_MODIFIED[] = "last-modified"; // Last-Modified
|
||||||
|
const char TRANSFER_ENCODING[] = "transfer-encoding"; // Transfer-Encoding
|
||||||
|
const char CONTENT_ENCODING[] = "content-encoding"; // Content-Encoding
|
||||||
|
// out
|
||||||
const char IF_NONE_MATCH[] = "If-None-Match";
|
const char IF_NONE_MATCH[] = "If-None-Match";
|
||||||
const char IF_MODIFIED_SINCE[] = "If-Modified-Since";
|
const char IF_MODIFIED_SINCE[] = "If-Modified-Since";
|
||||||
const char LAST_MODIFIED[] = "Last-Modified";
|
|
||||||
const char TRANSFER_ENCODING[] = "Transfer-Encoding";
|
|
||||||
|
|
||||||
std::string GetHttpContent (std::istream& response);
|
std::string GetHttpContent (std::istream& response);
|
||||||
void MergeChunkedResponse (std::istream& response, std::ostream& merged);
|
void MergeChunkedResponse (std::istream& response, std::ostream& merged);
|
||||||
std::string urlDecode(const std::string& data);
|
std::string urlDecode(const std::string& data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user