Browse Source

Merge branch 'openssl' into new-fs

Conflicts:
	AddressBook.cpp
	NetDb.cpp
	filelist.mk
pull/388/head
hagen 9 years ago
parent
commit
55315fca80
  1. 68
      AddressBook.cpp
  2. 3
      AddressBook.h
  3. 38
      Base.cpp
  4. 5
      Base.h
  5. 8
      ClientContext.cpp
  6. 15
      Config.cpp
  7. 95
      Destination.cpp
  8. 5
      Destination.h
  9. 122
      Family.cpp
  10. 35
      Family.h
  11. 7
      Garlic.cpp
  12. 3
      Garlic.h
  13. 43
      HTTPProxy.cpp
  14. 20
      I2PTunnel.cpp
  15. 45
      LeaseSet.cpp
  16. 5
      LeaseSet.h
  17. 113
      NetDb.cpp
  18. 11
      NetDb.h
  19. 7
      Reseed.cpp
  20. 26
      RouterInfo.cpp
  21. 3
      RouterInfo.h
  22. 13
      Streaming.cpp
  23. 36
      TunnelPool.cpp
  24. 4
      TunnelPool.h
  25. 1
      build/CMakeLists.txt
  26. 13
      contrib/certificates/family/i2p-dev.crt
  27. 34
      contrib/certificates/reseed/j_at_torontocrypto.org.crt
  28. 32
      contrib/certificates/reseed/matt_at_drollette.com.crt
  29. 21
      contrib/certificates/ssl/193.150.121.66.crt
  30. 19
      contrib/certificates/ssl/download.xxlspeed.com.crt
  31. 42
      contrib/certificates/ssl/i2p.mooo.com.crt
  32. 23
      contrib/certificates/ssl/i2p.mooo.com2.crt
  33. 25
      contrib/certificates/ssl/ieb9oopo.mooo.com.crt
  34. 24
      contrib/certificates/ssl/link.mx24.eu.crt
  35. 33
      contrib/certificates/ssl/netdb.rows.io.crt
  36. 33
      contrib/certificates/ssl/reseed.i2p.vzaws.com.crt
  37. 17
      contrib/certificates/ssl/user.mx24.eu.crt
  38. 7
      docs/build_notes_unix.md
  39. 3
      filelist.mk
  40. 1
      util.cpp
  41. 9
      util.h

68
AddressBook.cpp

@ -193,11 +193,7 @@ namespace client
delete m_Storage; delete m_Storage;
m_Storage = nullptr; m_Storage = nullptr;
} }
if (m_DefaultSubscription)
{
delete m_DefaultSubscription;
m_DefaultSubscription = nullptr; 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,7 +357,7 @@ 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,13 +386,25 @@ 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 ())
{
if (!m_IsLoaded)
{
// download it from http://i2p-projekt.i2p/hosts.txt
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 // pick random subscription
auto ind = rand () % m_Subscriptions.size(); auto ind = rand () % m_Subscriptions.size();
m_IsDownloading = true; m_IsDownloading = true;
m_Subscriptions[ind]->CheckSubscription (); m_Subscriptions[ind]->CheckSubscription ();
} }
}
else else
{ {
// try it again later // try it again later
@ -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;
}
} }
} }

3
AddressBook.h

@ -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

@ -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));

5
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,6 +103,9 @@ 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:

8
ClientContext.cpp

@ -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)
{ {

15
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); store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
} catch (boost::program_options::error e) { }
catch (boost::program_options::error& e)
{
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}; };

95
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,6 +288,8 @@ namespace client
if (it != m_RemoteLeaseSets.end ()) if (it != m_RemoteLeaseSets.end ())
{ {
leaseSet = it->second; leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset))
{
leaseSet->Update (buf + offset, len - offset); leaseSet->Update (buf + offset, len - offset);
if (leaseSet->IsValid ()) if (leaseSet->IsValid ())
LogPrint (eLogDebug, "Remote LeaseSet updated"); LogPrint (eLogDebug, "Remote LeaseSet updated");
@ -294,14 +300,22 @@ namespace client
leaseSet = nullptr; 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 ())
{
if (leaseSet->GetIdentHash () != GetIdentHash ())
{ {
LogPrint (eLogDebug, "New remote LeaseSet added"); LogPrint (eLogDebug, "New remote LeaseSet added");
m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet;
} }
else
LogPrint (eLogDebug, "Own remote LeaseSet dropped");
}
else else
{ {
LogPrint (eLogError, "New remote LeaseSet failed"); LogPrint (eLogError, "New remote LeaseSet failed");
@ -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,8 +400,11 @@ 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 ())
{
auto requestComplete = it->second->requestComplete;
s->m_LeaseSetRequests.erase (it); 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);
} }
} }
} }

5
Destination.h

@ -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

@ -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

@ -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

7
Garlic.cpp

@ -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

@ -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;

43
HTTPProxy.cpp

@ -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");
// 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); 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

20
I2PTunnel.cpp

@ -114,11 +114,26 @@ namespace client
void I2PTunnelConnection::StreamReceive () void I2PTunnelConnection::StreamReceive ()
{ {
if (m_Stream) if (m_Stream)
{
if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew ||
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
{
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2), std::placeholders::_1, std::placeholders::_2),
I2P_TUNNEL_CONNECTION_MAX_IDLE); 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,8 +141,13 @@ 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)
{
if (bytes_transferred > 0)
Write (m_StreamBuffer, bytes_transferred); // postpone termination
else
Terminate (); Terminate ();
} }
}
else else
Write (m_StreamBuffer, bytes_transferred); Write (m_StreamBuffer, bytes_transferred);
} }

45
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)
{ {
@ -180,6 +185,34 @@ namespace data
} }
} }
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);
} }

5
LeaseSet.h

@ -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:

113
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,24 +150,32 @@ 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); r->Update (buf, len);
if (r->GetTimestamp () > ts)
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
} }
else else
{
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
updated = false;
}
}
else
{ {
r = std::make_shared<RouterInfo> (buf, len); r = std::make_shared<RouterInfo> (buf, len);
if (!r->IsUnreachable ()) if (!r->IsUnreachable ())
@ -182,28 +191,40 @@ 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 ())
{
if (it->second->IsNewer (buf, len))
{ {
it->second->Update (buf, len); it->second->Update (buf, len);
if (it->second->IsValid ()) if (it->second->IsValid ())
{
LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64()); LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64());
updated = true;
}
else else
{ {
LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64()); LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64());
m_LeaseSets.erase (it); m_LeaseSets.erase (it);
} }
} }
else
LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase64());
}
else else
{ {
auto leaseSet = std::make_shared<LeaseSet> (buf, len, false); // we don't need leases in netdb auto leaseSet = std::make_shared<LeaseSet> (buf, len, false); // we don't need leases in netdb
@ -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,11 +349,22 @@ 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 {
if (ts > it.second->GetTimestamp () + 12*3600*1000LL) // 12 hours
{
it.second->SetUnreachable (true);
total--;
}
}
else if (total > 300)
{
if (ts > it.second->GetTimestamp () + 30*3600*1000LL) // 30 hours
{
it.second->SetUnreachable (true); it.second->SetUnreachable (true);
total--; 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
it.second->SetUnreachable (true); it.second->SetUnreachable (true);
@ -418,19 +452,43 @@ 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;
}
size_t payloadOffset = offset;
bool updated = false;
if (buf[DATABASE_STORE_TYPE_OFFSET]) // type
{
LogPrint (eLogDebug, "NetDb: store request: LeaseSet");
updated = AddLeaseSet (ident, buf + offset, len - offset, m->from);
}
else
{
LogPrint (eLogDebug, "NetDb: store request: RouterInfo");
size_t size = bufbe16toh (buf + offset);
offset += 2;
if (size > 2048 || size > len - offset)
{
LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size);
return;
}
uint8_t uncompressed[2048];
size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048);
if (uncompressedSize)
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
}
if (context.IsFloodfill ()) if (replyToken && context.IsFloodfill () && updated)
{ {
// flood it // flood updated
auto floodMsg = NewI2NPShortMessage (); auto floodMsg = NewI2NPShortMessage ();
uint8_t * payload = floodMsg->GetPayload (); uint8_t * payload = floodMsg->GetPayload ();
memcpy (payload, buf, 33); // key + type memcpy (payload, buf, 33); // key + type
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token
auto msgLen = len - offset; auto msgLen = len - payloadOffset;
floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen;
if (floodMsg->len < floodMsg->maxLen) if (floodMsg->len < floodMsg->maxLen)
{ {
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + offset, msgLen); memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
std::set<IdentHash> excluded; std::set<IdentHash> excluded;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
@ -438,32 +496,12 @@ namespace data
auto floodfill = GetClosestFloodfill (ident, excluded); auto floodfill = GetClosestFloodfill (ident, excluded);
if (floodfill) if (floodfill)
transports.SendMessage (floodfill->GetIdentHash (), floodMsg); transports.SendMessage (floodfill->GetIdentHash (), floodMsg);
}
}
else else
LogPrint (eLogError, "Database store message is too long ", floodMsg->len); break;
}
} }
if (buf[DATABASE_STORE_TYPE_OFFSET]) // type
{
LogPrint (eLogDebug, "NetDb: store request: LeaseSet");
AddLeaseSet (ident, buf + offset, len - offset, m->from);
} }
else else
{ LogPrint (eLogError, "Database store message is too long ", floodMsg->len);
LogPrint (eLogDebug, "NetDb: store request: RouterInfo");
size_t size = bufbe16toh (buf + offset);
offset += 2;
if (size > 2048 || size > len - offset)
{
LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size);
return;
}
uint8_t uncompressed[2048];
size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048);
if (uncompressedSize)
AddRouterInfo (ident, uncompressed, uncompressedSize);
} }
} }
@ -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,11 +862,14 @@ 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);
if (closeThanUsOnly)
minMetric = destKey ^ i2p::context.GetIdentHash ();
else
minMetric.SetMax (); 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

@ -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;

7
Reseed.cpp

@ -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()

26
RouterInfo.cpp

@ -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)

3
RouterInfo.h

@ -157,6 +157,7 @@ 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 (); };
@ -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;

13
Streaming.cpp

@ -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

36
TunnelPool.cpp

@ -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);
{
std::unique_lock<std::mutex> l(m_TestsMutex);
m_Tests[msgID] = std::make_pair (*it1, *it2); 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,17 +286,27 @@ namespace tunnel
buf += 4; buf += 4;
uint64_t timestamp = bufbe64toh (buf); uint64_t timestamp = bufbe64toh (buf);
decltype(m_Tests)::mapped_type test;
bool found = false;
{
std::unique_lock<std::mutex> l(m_TestsMutex);
auto it = m_Tests.find (msgID); auto it = m_Tests.find (msgID);
if (it != m_Tests.end ()) if (it != m_Tests.end ())
{ {
// restore from test failed state if any found = true;
if (it->second.first->GetState () == eTunnelStateTestFailed) test = it->second;
it->second.first->SetState (eTunnelStateEstablished);
if (it->second.second->GetState () == eTunnelStateTestFailed)
it->second.second->SetState (eTunnelStateEstablished);
LogPrint (eLogDebug, "Tunnels: test of ", it->first, " successful. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds");
m_Tests.erase (it); m_Tests.erase (it);
} }
}
if (found)
{
// restore from test failed state if any
if (test.first->GetState () == eTunnelStateTestFailed)
test.first->SetState (eTunnelStateEstablished);
if (test.second->GetState () == eTunnelStateTestFailed)
test.second->SetState (eTunnelStateEstablished);
LogPrint (eLogDebug, "Tunnels: test of ", msgID, " successful. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds");
}
else else
{ {
if (m_LocalDestination) if (m_LocalDestination)

4
TunnelPool.h

@ -54,6 +54,9 @@ namespace tunnel
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:
void CreateInboundTunnel (); void CreateInboundTunnel ();
@ -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;

1
build/CMakeLists.txt

@ -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

@ -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

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

32
contrib/certificates/reseed/matt_at_drollette.com.crt

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIEB52rdjANBgkqhkiG9w0BAQ0FADByMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEbMBkGA1UEAwwSbWF0dEBkcm9sbGV0
dGUuY29tMB4XDTE0MDcyMTEzMjYxM1oXDTI0MDcyMDEzMjYxM1owcjELMAkGA1UE
BhMCWFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFu
b255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGzAZBgNVBAMMEm1hdHRAZHJv
bGxldHRlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL5M9wKT
csNLg4EA3fW7LleTQdrm3stPnoUvFmsNZHGgsKt1Nc1qCNis3kr2QEY+4Z398U7r
7xGEQFa7D/9SPHf6n1uVXc9DIcmwBtEB0FPB1XPFp2h00ZXIv24yiLN3GQT1woAM
yEbBWsUgn8K/iMBeA5dU2vPwAbGO/0ibD62frgGdYqU2EeiJ/U6vBmKxvC+q2noL
gnyfQJEJANXgf+Cw/gBaS6yn5ZsYcenLNenID2TQKQ6Q/NxYrDYRdWdId29iwldt
dmNSmASv8C7g9d/isZkpmtYNkE4J4m0W9wKziOoyvLSMo8ec67QmCKaPaYKTHTjx
aUuja02+mnlV4DSdZo6nPkSdokRY0+5e6q7+dIPefu8ealGEAE5oedEfl5iM5Fnz
phTR+ePodBK3sB+bMi1NMppbWugpFpdqs1hg2KNKSSG8C4/eTqf2nnlDiVvvFANc
imt6tk0pZcKqveRiDSgI8mTzTcrNgVClsCLoInY5Vab7onZjY9bGijPQ2i1P6+qu
5G6LiLFW7xFq2BcX1DnTztcJ8Yu9NYHhR21J6u7Dr8YHntes3mnth1F0BX3FVA1s
9SaE9/pNhdqap9owpEhNoE1Ke3LorVLL8jyQsqgRHx8VdhWdi9Ao0mzzeI9HYX0j
nZ7uXK5DqGG74K6eWoS9jZSDJLj3IBkIr3B/AgMBAAGjITAfMB0GA1UdDgQWBBTK
YjH+9Jv82Zqi86r95/1sXUCOnDANBgkqhkiG9w0BAQ0FAAOCAgEAsDyl3dS/5pR1
iDN0zE70HN1Sjv55c5um6N39rgz8JSObbAMihhpjRXPR6yl0PdfVcswdCuEaaykp
ppPNY5ObqZIdqI92XOaOhSA3AkZwZffbwaoXFYiawq1aQG1HP7oxXzWwbnbPOxgz
6ThNP5DJan53Mk8TAhxoJkEJxVlMwIiC+QEgqDNYrP8oNOR2J1EXgzsHheEKObyP
xTwRYFqZU/7BQlFeB0LG1LIy9zXAHlb/XIor10w6ChPDW7DiDwGq3zDJw1d8eiUn
RoPRmFjTqn+3rGaEkk+vUFHoWo7cLCEIC3+P9wlY4Kel+ldXMmuJ+BZ1glFXeO3L
VO85n7iVIyBbwo7RLtNaBvrRQIEG3ld5UOKklLlWwhrX/FXksEhdFvmuF9sbiYNr
cg81sbwZlX7Gi7VicXkykFFXwRRr3UblDtfeevouxk4nMVzcDsmzGeAZKQBvcxHa
Pzc70YwnVRqTc87c0bEwPoxK1Vb26+DILyDjKb/AkTw/rwj6vcJZP2ad+hpiz5Ka
nlbY2cI3JJb0TQiDiOIk+xFqC5oHUTSEmfqA6sA5o/RqdwDpkfpgI5mCwhYzDSLD
jfS+263ylhanl7oz0sM+GtH63owVbYJAFT2EozT9siTIErvJESL4Z80yUQG63d/7
fss8T6gOo19esb/KEMZGZE4pAApakWM=
-----END CERTIFICATE-----

21
contrib/certificates/ssl/193.150.121.66.crt

@ -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

@ -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-----

42
contrib/certificates/ssl/i2p.mooo.com.crt

@ -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-----

23
contrib/certificates/ssl/i2p.mooo.com2.crt

@ -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-----

25
contrib/certificates/ssl/ieb9oopo.mooo.com.crt

@ -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-----

24
contrib/certificates/ssl/link.mx24.eu.crt

@ -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-----

33
contrib/certificates/ssl/netdb.rows.io.crt

@ -1,33 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFszCCA52gAwIBAgIRALWZzF745GPT8GVUcZ0RMg0wCwYJKoZIhvcNAQELMG0x
CzAJBgNVBAYTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAK
BgNVBAsTA0kyUDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMRYwFAYDVQQDEw1u
ZXRkYi5yb3dzLmlvMB4XDTE0MTIyMDE2NDIwNVoXDTE2MTIxOTE2NDIwNVowbTEL
MAkGA1UEBhMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoG
A1UECxMDSTJQMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxFjAUBgNVBAMTDW5l
dGRiLnJvd3MuaW8wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCTZyJF
Im9pnc7OO5DfQy4SuotUztO5BJX7xniTqD4fKLQQXzZFeT4XHrkDste8TsTzUfxt
CWDEBH3af5cpnwWMT28rlRw2DlPr+LnAgt7VjFXdhFZr1N5VfNlTI1K3OiZ/DRlB
92CoTypyx4ebNfLtZfh+TPLOdg5UqROpHIrybsUj2IaG3IpGHJK8FuH79b/X5oVI
FlDZJs5QsJEARzq2QMJd6fnNqkCBSSjNpeL7TtDar9EKa6+O7s351kH8MVFNSogB
F0Hqu8LYaRC1L1JCz5lsOYKepp3MMIOdDOhy+FTd8NuNZXYkUTdTNI4dB6w4Z6o+
xlnHEPpezIAAlPXLiupvlEi0om69/TMS+pLDBLAOlCZ2YaXS18UrSbmYYlekg40J
nEeALt8ZdsU/is7Q6SJZ3UltFIPCuMD+ixvaIvakkhNiqEWPxdg0XxAK1ZJYFup+
2aVtPLQIzWePkG/VbdA5cxQKNtRwOgvCoKIE29nUbxuq2PCmMhLAfXHeieSzP5c7
Q8A23qX94hwCIePj1YA9uNtStjECfVS1wjyXV4M1tTFUdSJv4aVtFjtya7PY+6SG
Srz11SqBWSqyJ/C14Su0QY/HquglzMRnkJ49Scwb+79hl7kPslO1iIgPLE5S2fIW
ZwJ/4AgGb6BZT8XPEYYANEA5y7KGanYNo8KdYwIDAQABo1IwUDAOBgNVHQ8BAf8E
BAMCAKQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAYBgNV
HREEETAPgg1uZXRkYi5yb3dzLmlvMAsGCSqGSIb3DQEBCwOCAgEAMjQSHPR/p9If
mJA1y489D1NB2CxfwO+CgAIs9HA7OsdneQBZTldMgBHoQGifkpD1uSl8DHoZqnJ8
wo5YWcT1rYkP+V1jGfZj92VvfQL0/R4G4hWdQwYY0CcXN8ixS36UDQVSFKb4zvNG
j9iIN57WToEmxp5noHguKrpViwhXCMCpAXr3ZIv/Fd+QACNEXuvdZgbtwfOTPLKh
ZlkUPgVHiQopeQnZhZCT3aLZ5lndrUtWlQYiGN/OolVyRie+ysuxjRR4L5brt4Rz
hrwFBswbQZlgxJ3Nod9/wEdEJWP4+X69ggzOkBB+PgpOFpuDlJxNTcPA/WFIlsm0
CzCv/o8Vg+MMWFPMwEZrk6UQXXACr1AEF+MUnZq3o5JaLvHoUcikewbZPcTCNvDp
nqT1RN9vq/MGdlRfPJkF028IXPz7T9DXXPXhJvv+FAfnOkREeUYpzBIftyYf92ol
l63z0FooVUTKWYPvFFgl5ShNnINTMVXPCZp8j7myLGSLOAFFwiaL1OtvftgxXfzC
B7Qj42SNhFUrHmO9fH3H2ptm/iW/Xe5eqgeb6MVGQ/eQJpdp0AvpDa50/AYNt1Iq
CcMKmBgzUezrIN24XXW/LZwazlc7I8e5RzgbEgXEDBZu21TApTKlmOqEYle8294W
fWThMdwk1kTrWxLooiVrS5A1hXqADqE=
-----END CERTIFICATE-----

33
contrib/certificates/ssl/reseed.i2p.vzaws.com.crt

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

17
contrib/certificates/ssl/user.mx24.eu.crt

@ -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-----

7
docs/build_notes_unix.md

@ -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
------------- -------------

3
filelist.mk

@ -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

@ -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);
} }

9
util.h

@ -12,11 +12,14 @@ 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);

Loading…
Cancel
Save