Merge pull request #669 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2016-10-12 11:54:51 -04:00 committed by GitHub
commit 40456ebaae
28 changed files with 374 additions and 222 deletions

10
.gitignore vendored
View File

@ -14,7 +14,7 @@ netDb
autom4te.cache autom4te.cache
.deps .deps
stamp-h1 stamp-h1
Makefile #Makefile
config.h config.h
config.h.in~ config.h.in~
config.log config.log
@ -238,3 +238,11 @@ pip-log.txt
# Sphinx # Sphinx
docs/_build docs/_build
/androidIdea/ /androidIdea/
# emacs files
*~
*\#*
# gdb files
.gdb_history

View File

@ -6,6 +6,7 @@
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <boost/algorithm/string.hpp>
#include "Base.h" #include "Base.h"
#include "util.h" #include "util.h"
#include "Identity.h" #include "Identity.h"
@ -15,6 +16,7 @@
#include "NetDb.h" #include "NetDb.h"
#include "ClientContext.h" #include "ClientContext.h"
#include "AddressBook.h" #include "AddressBook.h"
#include "Config.h"
namespace i2p namespace i2p
{ {
@ -404,9 +406,21 @@ namespace client
m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, s)); m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, s));
} }
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead");
} }
else else if (!i2p::config::IsDefault("addressbook.subscriptions"))
LogPrint (eLogWarning, "Addressbook: subscriptions.txt not found in datadir"); {
// using config file items
std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs);
std::vector<std::string> subsList;
boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
for (size_t i = 0; i < subsList.size (); i++)
{
m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i]));
}
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
}
} }
else else
LogPrint (eLogError, "Addressbook: subscriptions already loaded"); LogPrint (eLogError, "Addressbook: subscriptions already loaded");
@ -511,10 +525,11 @@ namespace client
{ {
if (!m_IsLoaded) if (!m_IsLoaded)
{ {
// download it from http://i2p-projekt.i2p/hosts.txt // download it from default subscription
LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription."); LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
if (!m_DefaultSubscription) if (!m_DefaultSubscription)
m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, DEFAULT_SUBSCRIPTION_ADDRESS); m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
m_IsDownloading = true; m_IsDownloading = true;
std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription)); std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription));
load_hosts.detach(); // TODO: use join load_hosts.detach(); // TODO: use join

View File

@ -18,11 +18,6 @@ namespace i2p
{ {
namespace client namespace client
{ {
#ifdef MESHNET
const char DEFAULT_SUBSCRIPTION_ADDRESS[] = "http://i42ofzetmgicvui5sshinfckpijix2udewbam4sjo6x5fbukltia.b32.i2p/hosts.txt";
#else
const char DEFAULT_SUBSCRIPTION_ADDRESS[] = "http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt";
#endif
const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes
const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes
const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)

22
BOB.cpp
View File

@ -437,8 +437,11 @@ namespace client
void BOBCommandSession::GetkeysCommandHandler (const char * operand, size_t len) void BOBCommandSession::GetkeysCommandHandler (const char * operand, size_t len)
{ {
LogPrint (eLogDebug, "BOB: getkeys"); LogPrint (eLogDebug, "BOB: getkeys");
SendReplyOK (m_Keys.ToBase64 ().c_str ()); if (m_Keys.GetPublic ()) // keys are set ?
} SendReplyOK (m_Keys.ToBase64 ().c_str ());
else
SendReplyError ("keys are not set");
}
void BOBCommandSession::GetdestCommandHandler (const char * operand, size_t len) void BOBCommandSession::GetdestCommandHandler (const char * operand, size_t len)
{ {
@ -501,12 +504,12 @@ namespace client
{ {
LogPrint (eLogDebug, "BOB: lookup ", operand); LogPrint (eLogDebug, "BOB: lookup ", operand);
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
if (!context.GetAddressBook ().GetIdentHash (operand, ident) || !m_CurrentDestination) if (!context.GetAddressBook ().GetIdentHash (operand, ident))
{ {
SendReplyError ("Address Not found"); SendReplyError ("Address Not found");
return; return;
} }
auto localDestination = m_CurrentDestination->GetLocalDestination (); auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination ();
auto leaseSet = localDestination->FindLeaseSet (ident); auto leaseSet = localDestination->FindLeaseSet (ident);
if (leaseSet) if (leaseSet)
SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ().c_str ()); SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ().c_str ());
@ -568,10 +571,15 @@ namespace client
{ {
std::stringstream s; std::stringstream s;
s << "DATA"; s << " NICKNAME: "; s << m_Nickname; s << "DATA"; s << " NICKNAME: "; s << m_Nickname;
if (m_CurrentDestination->GetLocalDestination ()->IsReady ()) if (m_CurrentDestination)
s << " STARTING: false RUNNING: true STOPPING: false"; {
if (m_CurrentDestination->GetLocalDestination ()->IsReady ())
s << " STARTING: false RUNNING: true STOPPING: false";
else
s << " STARTING: true RUNNING: false STOPPING: false";
}
else else
s << " STARTING: true RUNNING: false STOPPING: false"; s << " STARTING: false RUNNING: false STOPPING: false";
s << " KEYS: true"; s << " QUIET: "; s << (m_IsQuiet ? "true":"false"); s << " KEYS: true"; s << " QUIET: "; s << (m_IsQuiet ? "true":"false");
if (m_InPort) if (m_InPort)
{ {

View File

@ -49,6 +49,7 @@ namespace config {
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)") ("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
("ipv4", value<bool>()->zero_tokens()->default_value(true), "Enable communication through ipv4") ("ipv4", value<bool>()->zero_tokens()->default_value(true), "Enable communication through ipv4")
("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6") ("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
("daemon", value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start") ("daemon", value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start")
("service", value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'") ("service", value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'")
("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup") ("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup")
@ -150,6 +151,7 @@ namespace config {
options_description reseed("Reseed options"); options_description reseed("Reseed options");
reseed.add_options() reseed.add_options()
("reseed.verify", value<bool>()->default_value(false), "Verify .su3 signature")
("reseed.file", value<std::string>()->default_value(""), "Path to .su3 file") ("reseed.file", value<std::string>()->default_value(""), "Path to .su3 file")
#ifdef MESHNET #ifdef MESHNET
("reseed.urls", value<std::string>()->default_value("https://reseed.i2p.rocks:8443/"), "Reseed URLs, separated by comma") ("reseed.urls", value<std::string>()->default_value("https://reseed.i2p.rocks:8443/"), "Reseed URLs, separated by comma")
@ -163,19 +165,27 @@ namespace config {
"https://i2p.manas.ca:8443/," "https://i2p.manas.ca:8443/,"
"https://i2p-0.manas.ca:8443/," "https://i2p-0.manas.ca:8443/,"
"https://reseed.i2p.vzaws.com:8443/," "https://reseed.i2p.vzaws.com:8443/,"
"https://user.mx24.eu/,"
"https://download.xxlspeed.com/," "https://download.xxlspeed.com/,"
"https://reseed-ru.lngserv.ru/" "https://reseed-ru.lngserv.ru/,"
"https://reseed.atomike.ninja/"
), "Reseed URLs, separated by comma") ), "Reseed URLs, separated by comma")
#endif #endif
; ;
options_description addressbook("AddressBook options");
addressbook.add_options()
("addressbook.defaulturl", value<std::string>()->default_value(
"http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt"
), "AddressBook subscription URL for initial setup")
("addressbook.subscriptions", value<std::string>()->default_value(""),
"AddressBook subscriptions URLs, separated by comma");
options_description trust("Trust options"); options_description trust("Trust options");
trust.add_options() trust.add_options()
("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options") ("trust.enabled", value<bool>()->default_value(false), "enable explicit trust options")
("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops") ("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops")
("trust.hidden", value<bool>()->default_value(false), "should we hide our router from other routers?"); ("trust.hidden", value<bool>()->default_value(false), "should we hide our router from other routers?");
m_OptionsDesc m_OptionsDesc
.add(general) .add(general)
.add(limits) .add(limits)
@ -189,6 +199,7 @@ namespace config {
.add(upnp) .add(upnp)
.add(precomputation) .add(precomputation)
.add(reseed) .add(reseed)
.add(addressbook)
.add(trust) .add(trust)
; ;
} }

View File

@ -12,8 +12,10 @@ namespace i2p
namespace datagram namespace datagram
{ {
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner): DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner):
m_Owner (owner.get()), m_Receiver (nullptr) m_Owner (owner.get()),
m_Receiver (nullptr)
{ {
m_Identity.FromBase64 (owner->GetIdentity()->ToBase64());
} }
DatagramDestination::~DatagramDestination () DatagramDestination::~DatagramDestination ()
@ -24,16 +26,16 @@ namespace datagram
void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort)
{ {
auto owner = m_Owner; auto owner = m_Owner;
auto i = owner->GetIdentity(); std::vector<uint8_t> v(MAX_DATAGRAM_SIZE);
uint8_t buf[MAX_DATAGRAM_SIZE]; uint8_t * buf = v.data();
auto identityLen = i->ToBuffer (buf, MAX_DATAGRAM_SIZE); auto identityLen = m_Identity.ToBuffer (buf, MAX_DATAGRAM_SIZE);
uint8_t * signature = buf + identityLen; uint8_t * signature = buf + identityLen;
auto signatureLen = i->GetSignatureLen (); auto signatureLen = m_Identity.GetSignatureLen ();
uint8_t * buf1 = signature + signatureLen; uint8_t * buf1 = signature + signatureLen;
size_t headerLen = identityLen + signatureLen; size_t headerLen = identityLen + signatureLen;
memcpy (buf1, payload, len); memcpy (buf1, payload, len);
if (i->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) if (m_Identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
{ {
uint8_t hash[32]; uint8_t hash[32];
SHA256(buf1, len, hash); SHA256(buf1, len, hash);
@ -48,7 +50,7 @@ namespace datagram
} }
void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len)
{ {
i2p::data::IdentityEx identity; i2p::data::IdentityEx identity;
size_t identityLen = identity.FromBuffer (buf, len); size_t identityLen = identity.FromBuffer (buf, len);
@ -93,7 +95,7 @@ namespace datagram
uint8_t uncompressed[MAX_DATAGRAM_SIZE]; uint8_t uncompressed[MAX_DATAGRAM_SIZE];
size_t uncompressedLen = m_Inflator.Inflate (buf, len, uncompressed, MAX_DATAGRAM_SIZE); size_t uncompressedLen = m_Inflator.Inflate (buf, len, uncompressed, MAX_DATAGRAM_SIZE);
if (uncompressedLen) if (uncompressedLen)
HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen);
} }
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort)
@ -121,7 +123,7 @@ namespace datagram
if (m_Sessions.empty ()) return; if (m_Sessions.empty ()) return;
auto now = i2p::util::GetMillisecondsSinceEpoch(); auto now = i2p::util::GetMillisecondsSinceEpoch();
LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); LogPrint(eLogDebug, "DatagramDestination: clean up sessions");
std::lock_guard<std::mutex> lock(m_SessionsMutex); std::unique_lock<std::mutex> lock(m_SessionsMutex);
// for each session ... // for each session ...
for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) for (auto it = m_Sessions.begin (); it != m_Sessions.end (); )
{ {
@ -270,13 +272,16 @@ namespace datagram
bool DatagramSession::ShouldUpdateRoutingPath() const bool DatagramSession::ShouldUpdateRoutingPath() const
{ {
bool dead = m_RoutingSession == nullptr || m_RoutingSession->GetSharedRoutingPath () == nullptr;
auto now = i2p::util::GetMillisecondsSinceEpoch (); auto now = i2p::util::GetMillisecondsSinceEpoch ();
// we need to rotate paths becuase the routing path is too old // we need to rotate paths becuase the routing path is too old
if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true; // if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true;
// too fast switching paths
if (now - m_LastPathChange < DATAGRAM_SESSION_PATH_MIN_LIFETIME ) return false;
// our path looks dead so we need to rotate paths // our path looks dead so we need to rotate paths
if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return true; if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return !dead;
// if we have a routing session and routing path we don't need to switch paths // if we have a routing session and routing path we don't need to switch paths
return m_RoutingSession != nullptr && m_RoutingSession->GetSharedRoutingPath () != nullptr; return dead;
} }
@ -291,7 +296,7 @@ namespace datagram
if(currentLease) // if we have a lease return true if it's about to expire otherwise return false if(currentLease) // if we have a lease return true if it's about to expire otherwise return false
return currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); return currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE );
// we have no current lease, we should switch // we have no current lease, we should switch
return true; return currentLease == nullptr;
} }
std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetNextRoutingPath() std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetNextRoutingPath()

View File

@ -22,14 +22,15 @@ namespace datagram
// milliseconds for max session idle time // milliseconds for max session idle time
const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000; const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000;
// milliseconds for how long we try sticking to a dead routing path before trying to switch // milliseconds for how long we try sticking to a dead routing path before trying to switch
const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 5000; const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 10 * 1000;
// milliseconds interval a routing path is used before switching // milliseconds interval a routing path is used before switching
const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 60 * 1000; const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 20 * 60 * 1000;
// milliseconds before lease expire should we try switching leases // milliseconds before lease expire should we try switching leases
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 10 * 1000; const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 10 * 1000;
// milliseconds fudge factor for leases handover // milliseconds fudge factor for leases handover
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
// milliseconds minimum time between path switches
const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
class DatagramSession class DatagramSession
{ {
@ -133,13 +134,14 @@ namespace datagram
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort);
void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */ /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
Receiver FindReceiver(uint16_t port); Receiver FindReceiver(uint16_t port);
private: private:
i2p::client::ClientDestination * m_Owner; i2p::client::ClientDestination * m_Owner;
i2p::data::IdentityEx m_Identity;
Receiver m_Receiver; // default Receiver m_Receiver; // default
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, std::shared_ptr<DatagramSession> > m_Sessions; std::map<i2p::data::IdentHash, std::shared_ptr<DatagramSession> > m_Sessions;

View File

@ -171,28 +171,35 @@ namespace client
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
{ {
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex); std::shared_ptr<i2p::data::LeaseSet> remoteLS;
auto it = m_RemoteLeaseSets.find (ident);
if (it != m_RemoteLeaseSets.end ())
{ {
if (!it->second->IsExpired ()) std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (ident);
if (it != m_RemoteLeaseSets.end ())
remoteLS = it->second;
}
if (remoteLS)
{
if (!remoteLS->IsExpired ())
{ {
if (it->second->ExpiresSoon()) if (remoteLS->ExpiresSoon())
{ {
LogPrint(eLogDebug, "Destination: Lease Set expires soon, updating before expire"); LogPrint(eLogDebug, "Destination: Lease Set expires soon, updating before expire");
// update now before expiration for smooth handover // update now before expiration for smooth handover
RequestDestination(ident, [this, ident] (std::shared_ptr<i2p::data::LeaseSet> ls) { auto s = shared_from_this ();
RequestDestination(ident, [s, ident] (std::shared_ptr<i2p::data::LeaseSet> ls) {
if(ls && !ls->IsExpired()) if(ls && !ls->IsExpired())
{ {
ls->PopulateLeases(); ls->PopulateLeases();
{ {
std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex); std::lock_guard<std::mutex> _lock(s->m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ident] = ls; s->m_RemoteLeaseSets[ident] = ls;
} }
} }
}); });
} }
return it->second; return remoteLS;
} }
else else
LogPrint (eLogWarning, "Destination: remote LeaseSet expired"); LogPrint (eLogWarning, "Destination: remote LeaseSet expired");
@ -203,15 +210,13 @@ namespace client
if (ls && !ls->IsExpired ()) if (ls && !ls->IsExpired ())
{ {
ls->PopulateLeases (); // since we don't store them in netdb ls->PopulateLeases (); // since we don't store them in netdb
{ std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex);
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex); m_RemoteLeaseSets[ident] = ls;
m_RemoteLeaseSets[ident] = ls;
}
return ls; return ls;
} }
} }
return nullptr; return nullptr;
} }
std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSet () std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSet ()
{ {

View File

@ -66,12 +66,19 @@ namespace client
memcpy (buf + 4, payload, len); memcpy (buf + 4, payload, len);
msg->len += len + 4; msg->len += len + 4;
msg->FillI2NPMessageHeader (eI2NPData); msg->FillI2NPMessageHeader (eI2NPData);
auto s = GetSharedFromThis ();
auto remote = FindLeaseSet (ident); auto remote = FindLeaseSet (ident);
if (remote) if (remote)
GetService ().post (std::bind (&I2CPDestination::SendMsg, GetSharedFromThis (), msg, remote)); {
GetService ().post (
[s, msg, remote, nonce]()
{
bool sent = s->SendMsg (msg, remote);
s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure);
});
}
else else
{ {
auto s = GetSharedFromThis ();
RequestDestination (ident, RequestDestination (ident,
[s, msg, nonce](std::shared_ptr<i2p::data::LeaseSet> ls) [s, msg, nonce](std::shared_ptr<i2p::data::LeaseSet> ls)
{ {

View File

@ -102,7 +102,7 @@ namespace i2p
{ {
RAND_bytes ((uint8_t *)&msgID, 4); RAND_bytes ((uint8_t *)&msgID, 4);
htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID); htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, I2PD_NET_ID); htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::context.GetNetID ());
} }
m->len += DELIVERY_STATUS_SIZE; m->len += DELIVERY_STATUS_SIZE;
m->FillI2NPMessageHeader (eI2NPDeliveryStatus); m->FillI2NPMessageHeader (eI2NPDeliveryStatus);

View File

@ -559,23 +559,23 @@ namespace client
} }
/** create new udp session */ /** create new udp session */
boost::asio::ip::udp::endpoint ep(m_LocalAddress, 0); boost::asio::ip::udp::endpoint ep(m_LocalAddress, 0);
m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort)); m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort));
return m_Sessions.back(); return m_Sessions.back();
} }
UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination, const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to,
uint16_t ourPort, uint16_t theirPort) : uint16_t ourPort, uint16_t theirPort) :
m_Destination(localDestination->GetDatagramDestination()), m_Destination(localDestination->GetDatagramDestination()),
m_Service(localDestination->GetService()), m_Service(localDestination->GetService()),
IPSocket(localDestination->GetService(), localEndpoint), IPSocket(localDestination->GetService(), localEndpoint),
Identity(to),
SendEndpoint(endpoint), SendEndpoint(endpoint),
LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LastActivity(i2p::util::GetMillisecondsSinceEpoch()),
LocalPort(ourPort), LocalPort(ourPort),
RemotePort(theirPort) RemotePort(theirPort)
{ {
memcpy(Identity, to->data(), 32);
Receive(); Receive();
} }
@ -592,13 +592,7 @@ namespace client
{ {
LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint);
LastActivity = i2p::util::GetMillisecondsSinceEpoch(); LastActivity = i2p::util::GetMillisecondsSinceEpoch();
uint8_t * data = new uint8_t[len]; m_Destination->SendDatagramTo(m_Buffer, len, Identity, 0, 0);
memcpy(data, m_Buffer, len);
m_Service.post([&,len, data] () {
m_Destination->SendDatagramTo(data, len, Identity, 0, 0);
delete [] data;
});
Receive(); Receive();
} else { } else {
LogPrint(eLogError, "UDPSession: ", ecode.message()); LogPrint(eLogError, "UDPSession: ", ecode.message());
@ -727,7 +721,7 @@ namespace client
if(m_Session) delete m_Session; if(m_Session) delete m_Session;
boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0);
m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, m_RemoteIdent, LocalPort, RemotePort);
} }
void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)

View File

@ -155,7 +155,7 @@ namespace client
UDPSession(boost::asio::ip::udp::endpoint localEndpoint, UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination, const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
uint16_t ourPort, uint16_t theirPort); uint16_t ourPort, uint16_t theirPort);
void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void HandleReceived(const boost::system::error_code & ecode, std::size_t len);
void Receive(); void Receive();

View File

@ -35,11 +35,12 @@ namespace data
} }
IdentityEx::IdentityEx (): IdentityEx::IdentityEx ():
m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
} }
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type) IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type):
m_IsVerifierCreated (false)
{ {
memcpy (m_StandardIdentity.publicKey, publicKey, sizeof (m_StandardIdentity.publicKey)); memcpy (m_StandardIdentity.publicKey, publicKey, sizeof (m_StandardIdentity.publicKey));
if (type != SIGNING_KEY_TYPE_DSA_SHA1) if (type != SIGNING_KEY_TYPE_DSA_SHA1)
@ -135,19 +136,19 @@ namespace data
} }
IdentityEx::IdentityEx (const uint8_t * buf, size_t len): IdentityEx::IdentityEx (const uint8_t * buf, size_t len):
m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
FromBuffer (buf, len); FromBuffer (buf, len);
} }
IdentityEx::IdentityEx (const IdentityEx& other): IdentityEx::IdentityEx (const IdentityEx& other):
m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
*this = other; *this = other;
} }
IdentityEx::IdentityEx (const Identity& standard): IdentityEx::IdentityEx (const Identity& standard):
m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
*this = standard; *this = standard;
} }
@ -173,6 +174,7 @@ namespace data
m_ExtendedBuffer = nullptr; m_ExtendedBuffer = nullptr;
m_Verifier = nullptr; m_Verifier = nullptr;
m_IsVerifierCreated = false;
return *this; return *this;
} }
@ -187,6 +189,7 @@ namespace data
m_ExtendedLen = 0; m_ExtendedLen = 0;
m_Verifier = nullptr; m_Verifier = nullptr;
m_IsVerifierCreated = false;
return *this; return *this;
} }
@ -373,8 +376,17 @@ namespace data
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
{ {
if (!m_Verifier || !verifier) if (!m_Verifier)
m_Verifier.reset (verifier); {
auto created = m_IsVerifierCreated.exchange (true);
if (!created)
m_Verifier.reset (verifier);
else
{
delete verifier;
while (!m_Verifier) ; // spin lock
}
}
else else
delete verifier; delete verifier;
} }
@ -382,7 +394,8 @@ namespace data
void IdentityEx::DropVerifier () const void IdentityEx::DropVerifier () const
{ {
// TODO: potential race condition with Verify // TODO: potential race condition with Verify
m_Verifier = nullptr; m_IsVerifierCreated = false;
m_Verifier = nullptr;
} }
PrivateKeys& PrivateKeys::operator=(const Keys& keys) PrivateKeys& PrivateKeys::operator=(const Keys& keys)
@ -457,8 +470,8 @@ namespace data
void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{ {
if (!m_Signer) if (!m_Signer)
CreateSigner(); CreateSigner();
m_Signer->Sign (buf, len, signature); m_Signer->Sign (buf, len, signature);
} }
void PrivateKeys::CreateSigner () const void PrivateKeys::CreateSigner () const

View File

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <memory> #include <memory>
#include <atomic>
#include "Base.h" #include "Base.h"
#include "Signature.h" #include "Signature.h"
@ -104,6 +105,7 @@ namespace data
Identity m_StandardIdentity; Identity m_StandardIdentity;
IdentHash m_IdentHash; IdentHash m_IdentHash;
mutable std::unique_ptr<i2p::crypto::Verifier> m_Verifier; mutable std::unique_ptr<i2p::crypto::Verifier> m_Verifier;
mutable std::atomic_bool m_IsVerifierCreated; // make sure we don't create twice
size_t m_ExtendedLen; size_t m_ExtendedLen;
uint8_t * m_ExtendedBuffer; uint8_t * m_ExtendedBuffer;
}; };

View File

@ -37,11 +37,17 @@ ifeq ($(USE_WIN32_APP), yes)
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif endif
# don't change following line to ifeq ($(USE_AESNI),yes) !!!
ifeq ($(USE_AESNI),1) ifeq ($(USE_AESNI),1)
CPU_FLAGS = -maes -DAESNI CPU_FLAGS = -maes -DAESNI
else else
CPU_FLAGS = -msse CPU_FLAGS = -msse
endif endif
ifeq ($(USE_ASLR),yes)
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va \
-Wl,--dynamicbase,--export-all-symbols
endif
obj/%.o : %.rc obj/%.o : %.rc
$(WINDRES) -i $< -o $@ $(WINDRES) -i $< -o $@

View File

@ -1,21 +1,26 @@
i2pd i2pd
==== ====
i2pd is a full-featured C++ implementation of i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client.
[I2P](https://geti2p.net/en/about/intro) client.
I2P (Invisible Internet Project) is anonymous network which works on top of I2P (Invisible Internet Protocol) is a universal anonymous network layer.
public Internet. Privacy and anonymity are achieved by strong encryption and All communications over I2P are anonymous and end-to-end encrypted, participants
bouncing your traffic through thousands of I2P nodes all around the world. don't reveal their real IP addresses.
We are building network which helps people to communicate and share information I2P client is a software used for building and using anonymous I2P
networks. Such networks are commonly used for anonymous peer-to-peer
applications (filesharing, cryptocurrencies) and anonymous client-server
applications (websites, instant messengers, chat-servers).
I2P allows people from all around the world to communicate and share information
without restrictions. without restrictions.
* [Website](http://i2pd.website) * [Website](http://i2pd.website)
* [Documentation](https://i2pd.readthedocs.io/en/latest/) * [Documentation](https://i2pd.readthedocs.io/en/latest/)
* [Wiki](https://github.com/PurpleI2P/i2pd/wiki) * [Wiki](https://github.com/PurpleI2P/i2pd/wiki)
* [Tickets/Issues](https://github.com/PurpleI2P/i2pd/issues) * [Tickets/Issues](https://github.com/PurpleI2P/i2pd/issues)
* [Twitter](https://twitter.com/i2porignal) * [Specifications](https://geti2p.net/spec)
* [Twitter](https://twitter.com/hashtag/i2pd)
Installing Installing
---------- ----------

View File

@ -131,52 +131,64 @@ namespace data
s.read (signerID, signerIDLength); // signerID s.read (signerID, signerIDLength); // signerID
signerID[signerIDLength] = 0; signerID[signerIDLength] = 0;
//try to verify signature bool verify; i2p::config::GetOption("reseed.verify", verify);
auto it = m_SigningKeys.find (signerID); if (verify)
if (it != m_SigningKeys.end ()) {
{ //try to verify signature
// TODO: implement all signature types auto it = m_SigningKeys.find (signerID);
if (signatureType == SIGNING_KEY_TYPE_RSA_SHA512_4096) if (it != m_SigningKeys.end ())
{ {
size_t pos = s.tellg (); // TODO: implement all signature types
size_t tbsLen = pos + contentLength; if (signatureType == SIGNING_KEY_TYPE_RSA_SHA512_4096)
uint8_t * tbs = new uint8_t[tbsLen];
s.seekg (0, std::ios::beg);
s.read ((char *)tbs, tbsLen);
uint8_t * signature = new uint8_t[signatureLength];
s.read ((char *)signature, signatureLength);
// RSA-raw
{ {
// calculate digest size_t pos = s.tellg ();
uint8_t digest[64]; size_t tbsLen = pos + contentLength;
SHA512 (tbs, tbsLen, digest); uint8_t * tbs = new uint8_t[tbsLen];
// encrypt signature s.seekg (0, std::ios::beg);
BN_CTX * bnctx = BN_CTX_new (); s.read ((char *)tbs, tbsLen);
BIGNUM * s = BN_new (), * n = BN_new (); uint8_t * signature = new uint8_t[signatureLength];
BN_bin2bn (signature, signatureLength, s); s.read ((char *)signature, signatureLength);
BN_bin2bn (it->second, i2p::crypto::RSASHA5124096_KEY_LENGTH, n); // RSA-raw
BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n {
uint8_t * enSigBuf = new uint8_t[signatureLength]; // calculate digest
i2p::crypto::bn2buf (s, enSigBuf, signatureLength); uint8_t digest[64];
// digest is right aligned SHA512 (tbs, tbsLen, digest);
// we can't use RSA_verify due wrong padding in SU3 // encrypt signature
if (memcmp (enSigBuf + (signatureLength - 64), digest, 64)) BN_CTX * bnctx = BN_CTX_new ();
LogPrint (eLogWarning, "Reseed: SU3 signature verification failed"); BIGNUM * s = BN_new (), * n = BN_new ();
delete[] enSigBuf; BN_bin2bn (signature, signatureLength, s);
BN_free (s); BN_free (n); BN_bin2bn (it->second, i2p::crypto::RSASHA5124096_KEY_LENGTH, n);
BN_CTX_free (bnctx); BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n
} uint8_t * enSigBuf = new uint8_t[signatureLength];
i2p::crypto::bn2buf (s, enSigBuf, signatureLength);
// digest is right aligned
// we can't use RSA_verify due wrong padding in SU3
if (memcmp (enSigBuf + (signatureLength - 64), digest, 64))
LogPrint (eLogWarning, "Reseed: SU3 signature verification failed");
else
verify = false; // verified
delete[] enSigBuf;
BN_free (s); BN_free (n);
BN_CTX_free (bnctx);
}
delete[] signature; delete[] signature;
delete[] tbs; delete[] tbs;
s.seekg (pos, std::ios::beg); s.seekg (pos, std::ios::beg);
}
else
LogPrint (eLogWarning, "Reseed: Signature type ", signatureType, " is not supported");
} }
else else
LogPrint (eLogWarning, "Reseed: Signature type ", signatureType, " is not supported"); LogPrint (eLogWarning, "Reseed: Certificate for ", signerID, " not loaded");
} }
else
LogPrint (eLogWarning, "Reseed: Certificate for ", signerID, " not loaded"); if (verify) // not verified
{
LogPrint (eLogError, "Reseed: SU3 verification failed");
return 0;
}
// handle content // handle content
int numFiles = 0; int numFiles = 0;
size_t contentPos = s.tellg (); size_t contentPos = s.tellg ();

View File

@ -18,7 +18,8 @@ namespace i2p
RouterContext::RouterContext (): RouterContext::RouterContext ():
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
m_StartupTime (0), m_Status (eRouterStatusOK), m_Error (eRouterErrorNone) m_StartupTime (0), m_Status (eRouterStatusOK), m_Error (eRouterErrorNone),
m_NetID (I2PD_NET_ID)
{ {
} }
@ -76,7 +77,8 @@ namespace i2p
} }
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
routerInfo.SetProperty ("netId", std::to_string (I2PD_NET_ID)); i2p::config::GetOption("netid", m_NetID);
routerInfo.SetProperty ("netId", std::to_string (m_NetID));
routerInfo.SetProperty ("router.version", I2P_VERSION); routerInfo.SetProperty ("router.version", I2P_VERSION);
routerInfo.CreateBuffer (m_Keys); routerInfo.CreateBuffer (m_Keys);
m_RouterInfo.SetRouterIdentity (GetIdentity ()); m_RouterInfo.SetRouterIdentity (GetIdentity ());

View File

@ -58,7 +58,9 @@ namespace i2p
void SetStatus (RouterStatus status); void SetStatus (RouterStatus status);
RouterError GetError () const { return m_Error; }; RouterError GetError () const { return m_Error; };
void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; }; void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; };
int GetNetID () const { return m_NetID; };
void SetNetID (int netID) { m_NetID = netID; };
void UpdatePort (int port); // called from Daemon void UpdatePort (int port); // called from Daemon
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer); bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
@ -117,6 +119,7 @@ namespace i2p
uint32_t m_BandwidthLimit; // allowed bandwidth uint32_t m_BandwidthLimit; // allowed bandwidth
RouterStatus m_Status; RouterStatus m_Status;
RouterError m_Error; RouterError m_Error;
int m_NetID;
std::mutex m_GarlicMutex; std::mutex m_GarlicMutex;
}; };

View File

@ -13,6 +13,7 @@
#include "Timestamp.h" #include "Timestamp.h"
#include "Log.h" #include "Log.h"
#include "NetDb.h" #include "NetDb.h"
#include "RouterContext.h"
#include "RouterInfo.h" #include "RouterInfo.h"
namespace i2p namespace i2p
@ -286,7 +287,7 @@ namespace data
if (!strcmp (key, "caps")) if (!strcmp (key, "caps"))
ExtractCaps (value); ExtractCaps (value);
// check netId // check netId
else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != I2PD_NET_ID) else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ())
{ {
LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value);
m_IsUnreachable = true; m_IsUnreachable = true;
@ -771,7 +772,11 @@ namespace data
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const
{ {
#if (BOOST_VERSION >= 105300)
auto addresses = boost::atomic_load (&m_Addresses);
#else
auto addresses = m_Addresses; auto addresses = m_Addresses;
#endif
for (const auto& address : *addresses) for (const auto& address : *addresses)
{ {
if (address->transportStyle == s) if (address->transportStyle == s)

137
Tag.h
View File

@ -1,3 +1,6 @@
#ifndef TAG_H__
#define TAG_H__
/* /*
* Copyright (c) 2013-2016, The PurpleI2P Project * Copyright (c) 2013-2016, The PurpleI2P Project
* *
@ -6,92 +9,80 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifndef TAG_H__ #include <boost/static_assert.hpp>
#define TAG_H__ #include <string.h>
#include <string.h> /* memcpy */
#include "Base.h" #include "Base.h"
namespace i2p { namespace i2p {
namespace data { namespace data {
template<int sz>
class Tag template<size_t sz>
class Tag
{
BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
public:
Tag () = default;
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
uint8_t * operator()() { return m_Buf; }
const uint8_t * operator()() const { return m_Buf; }
operator uint8_t * () { return m_Buf; }
operator const uint8_t * () const { return m_Buf; }
const uint8_t * data() const { return m_Buf; }
const uint64_t * GetLL () const { return ll; }
bool IsZero () const
{ {
public: for (size_t i = 0; i < sz/8; ++i)
if (ll[i]) return false;
return true;
}
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }; void Fill(uint8_t c)
Tag (const Tag<sz>& ) = default; {
#ifndef _WIN32 // FIXME!!! msvs 2013 can't compile it memset(m_Buf, c, sz);
Tag (Tag<sz>&& ) = default; }
#endif
Tag () = default;
Tag<sz>& operator= (const Tag<sz>& ) = default;
#ifndef _WIN32
Tag<sz>& operator= (Tag<sz>&& ) = default;
#endif
uint8_t * operator()() { return m_Buf; };
const uint8_t * operator()() const { return m_Buf; };
operator uint8_t * () { return m_Buf; };
operator const uint8_t * () const { return m_Buf; };
const uint64_t * GetLL () const { return ll; };
bool operator== (const Tag<sz>& other) const { return !memcmp (m_Buf, other.m_Buf, sz); };
bool operator< (const Tag<sz>& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; };
bool IsZero () const
{
for (int i = 0; i < sz/8; i++)
if (ll[i]) return false;
return true;
}
const uint8_t * data() const { return m_Buf; }
/** fill with a value */
void Fill(uint8_t c)
{
memset(m_Buf, c, sz);
}
std::string ToBase64 () const std::string ToBase64 () const
{ {
char str[sz*2]; char str[sz*2];
int l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2); size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
str[l] = 0; return std::string (str, str + l);
return std::string (str); }
}
std::string ToBase32 () const std::string ToBase32 () const
{ {
char str[sz*2]; char str[sz*2];
int l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2); size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
str[l] = 0; return std::string (str, str + l);
return std::string (str); }
}
void FromBase32 (const std::string& s) void FromBase32 (const std::string& s)
{ {
i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
} }
void FromBase64 (const std::string& s) void FromBase64 (const std::string& s)
{ {
i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
} }
private: private:
union // 8 bytes alignment union // 8 bytes aligned
{ {
uint8_t m_Buf[sz]; uint8_t m_Buf[sz];
uint64_t ll[sz/8]; uint64_t ll[sz/8];
};
}; };
};
} // data } // data
} // i2p } // i2p

View File

@ -142,9 +142,9 @@ install:
- if not defined msvc ( - if not defined msvc (
C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy bash pacman pacman-mirrors msys2-runtime msys2-runtime-devel cmake" C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -Sy bash pacman pacman-mirrors msys2-runtime msys2-runtime-devel cmake"
&& if "%x64%" == "1" ( && if "%x64%" == "1" (
C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc mingw-w64-x86_64-extra-cmake-modules"
) else ( ) else (
C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-openssl mingw-w64-i686-boost mingw-w64-i686-miniupnpc" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-openssl mingw-w64-i686-boost mingw-w64-i686-miniupnpc mingw-w64-i686-extra-cmake-modules"
) )
) )
cache: cache:

View File

@ -16,7 +16,8 @@ option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_PCH "Use precompiled header" OFF) option(WITH_PCH "Use precompiled header" OFF)
option(WITH_GUI "Include GUI (currently MS Windows only)" ON) option(WITH_GUI "Include GUI (currently MS Windows only)" ON)
option(WITH_MESHNET "Build for cjdns test network" OFF) option(WITH_MESHNET "Build for cjdns test network" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer (linux only)" OFF) option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
# paths # paths
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ) set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
@ -190,10 +191,22 @@ if (WITH_ADDRSANITIZER)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer" )
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address" ) set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address" )
else () else ()
error ("MSVC does not support address sanitizer option") message( SEND_ERROR "MSVC does not support address sanitizer option")
endif() endif()
endif() endif()
if (WITH_THREADSANITIZER)
if (WITH_ADDRSANITIZER)
message( FATAL_ERROR "thread sanitizer option cannot be combined with address sanitizer")
elseif (NOT MSVC)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread" )
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread" )
else ()
message( SEND_ERROR "MSVC does not support address sanitizer option")
endif()
endif()
# libraries # libraries
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826 # TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
# use imported Threads::Threads instead # use imported Threads::Threads instead
@ -347,6 +360,7 @@ message(STATUS " UPnP : ${WITH_UPNP}")
message(STATUS " PCH : ${WITH_PCH}") message(STATUS " PCH : ${WITH_PCH}")
message(STATUS " MESHNET : ${WITH_MESHNET}") message(STATUS " MESHNET : ${WITH_MESHNET}")
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THEADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS "---------------------------------------") message(STATUS "---------------------------------------")
#Handle paths nicely #Handle paths nicely

View File

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF5TCCA82gAwIBAgIRANFIiHpTaRY2Z30TQOiuqFcwDQYJKoZIhvcNAQELBQAw
cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM
EGF0b21pa2VAbWFpbC5pMnAwHhcNMTYwODAyMTQyNDEyWhcNMjYwODAyMTQyNDEy
WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD
VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE
AwwQYXRvbWlrZUBtYWlsLmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggIBAMLRmxclaAvm405JLHNNiniUi0aZaBoLJ+afwn2LGfTDUhTD5Y8lW6V9o90n
eTNOCaiid7bWpVBkA1M4gZ9TdUnP0POa99jXZbj4PHFRl1l8k4Ap12PUO3hgwtH7
7j7j+UPaIuE2y+U7hJbmyQ0v7r8yjGWSTtSqs+exNhyr4Mh7DvacZySZ+oqQdXYA
vnfDpBX1dKlN1Nb4XloG0uE1OK1YfJoC+p+v8qXjKagIdZgThdmsWcQ82EGI+Q9u
VfrE4m3CNwJy0X86wMNYqHej88wBHnJMmTm+cZtFLVmZsRqnuLAQL1wrfCbGSltR
zhVQHTysLwMz9+llTXtzMf+R2kcEAYWiPc5IRVU+LvkN/610r5fuHW+OcQ9ZgRVn
PMqlv5PDG2ZxdIOAQQsOd7fH0r5q3MhqlVstVE45Rl33uA+M7wjJK2cvnOoSioxp
szn2GIZliXQXo4dJczgfN2U4PLBGRBGmrB1R2S1YsG6CrSJuMCX14VKJP69Nfm8a
EDA5GKNke+ZpXCszPLaNMB70LVFQc9FmMhsOgLIIoJBgd61uMgokMJJMLaWN0RaK
w1ZduxYGUmg2T2pi/clIkVzZmlcHKViUn0sMcKD+ibEPOvQIB/3HPEEt6iIkanc/
da5IFzikkaykt/Tu6o8rreeEu65HkIxFaCHegSXLHSyxj00BAgMBAAGjejB4MA4G
A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD
VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQYXRvbWlrZUBtYWlsLmkycDAbBgNVHSME
FDASgBBhdG9taWtlQG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQAA0MdWfN/N
1q5CdJqDyw4JQwzdYkA27Wr02qIcmwnqjcCEDPl4uDTyqN9gbEpJ48AcsdXRa6GE
lLh/qJ67I6YDe63LuhndzRULNgxGHVMGS8kBJIssQehb2rOFnbUTp0gMR+0QpXXe
omase4kL90c9uuYX1vXaO/ADssY2/QX49prwJO+UY/jGhcX4YheFI/teA85u6Qko
ero437Shqhl0kbdK+eBkOFf9a7mGxpMT73KE1jFS6433W4fFOkybQ1dcS0qStaUM
3qKC0EQCbAl1seAp3AGuG46swHZB0rZ1WCKVAr5yqCWSWMYO+fL6FosNg9z/VDVh
g6FFfoGrv19yaVFa9AvQsk1ATZ+bwtHProNx2Xet9pnAI30dT16+C5wCctoR6RVf
iOHl6CGqadjOycbMDVvOfJhypNDgWW3gBaCfXiAocJTLpR7hKNZ2bnvcP2xyXH1j
Qz/kiMJoZ3+TV1yC/x/maAHsUIQHqqd6ZRj7x5MgJq0UBdITo2ZQVfXYI0ZGIeNm
fMu+P5448+NdpASa9QoqS8kPFeUaHJMzMFHBKhrr8lTJeZ82hKBXt5jD3Tbef5Ck
n5auKu2D0IjvrzsdIpNMQAhuBPT06TW/LzN/MvardZcaLcBmcutefw6Z7RsedHvj
cGpnw4a2u9sHZIUNHzoGq32+7UWXsBI5Ow==
-----END CERTIFICATE-----

View File

@ -87,7 +87,19 @@ You should be able to run ./i2pd . If you need to start from the new
shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as
it adds`/minw32/bin` to the PATH. it adds`/minw32/bin` to the PATH.
### UPnP
You can install it through the MSYS2
and build with USE_UPNP key.
```bash
pacman -S mingw-w64-i686-miniupnpc
make USE_UPNP=yes
```
or
```bash
pacman -S mingw-w64-x86_64-miniupnpc
make USE_UPNP=yes
```
Using Visual Studio Using Visual Studio
------------------- -------------------
@ -160,20 +172,7 @@ port. You'd want to have include headers around to build i2pd with
support for this. Unpack client source code in a sibling folder, support for this. Unpack client source code in a sibling folder,
e.g. C:\dev\miniupnpc . You may want to remove version number from e.g. C:\dev\miniupnpc . You may want to remove version number from
folder name included in downloaded archive. folder name included in downloaded archive.
You can also install it through the MSYS2
and build with USE_UPNP key.
```bash
pacman -S mingw-w64-i686-miniupnpc
make USE_UPNP=yes
```
or
```bash
pacman -S mingw-x86_64-miniupnpc
make USE_UPNP=yes
```
### Creating Visual Studio project ### Creating Visual Studio project
Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options. Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options.

View File

@ -25,6 +25,7 @@ If you are upgrading your very old router (< 2.3.0) see also [this](config_opts_
* --floodfill - Router will be floodfill. false by default * --floodfill - Router will be floodfill. false by default
* --bandwidth= - Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000) * --bandwidth= - Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)
* --family= - Name of a family, router belongs to * --family= - Name of a family, router belongs to
* --netid= - Network ID, router belongs to. Main I2P is 2.
Windows-specific options: Windows-specific options:
@ -72,8 +73,11 @@ All options below still possible in cmdline, but better write it in config file:
* --upnp.name= - Name i2pd appears in UPnP forwardings list. I2Pd by default * --upnp.name= - Name i2pd appears in UPnP forwardings list. I2Pd by default
* --precomputation.elgamal= - Use ElGamal precomputated tables. false for x64 and true for other platforms by default * --precomputation.elgamal= - Use ElGamal precomputated tables. false for x64 and true for other platforms by default
* --reseed.file - Full path to SU3 file to reseed from * --reseed.verify= - Request SU3 signature verification
* --reseed.urls - Reseed URLs, separated by comma * --reseed.file= - Full path to SU3 file to reseed from
* --reseed.urls= - Reseed URLs, separated by comma
* --addressbook.defaulturl= - AddressBook subscription URL for initial setup
* --addressbook.subscriptions= - AddressBook subscriptions URLs, separated by comma
* --limits.transittunnels= - Override maximum number of transit tunnels. 2500 by default * --limits.transittunnels= - Override maximum number of transit tunnels. 2500 by default

View File

@ -92,8 +92,18 @@ ipv6 = false
# name = I2Pd # name = I2Pd
[reseed] [reseed]
## Path to reseed .su3 file (if ) ## URLs to request reseed data from, separated by comma
# file = ## Default: "mainline" I2P Network reseeds
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
## Path to reseed data file (.su3) for manual reseeding
# file = /path/to/i2pseeds.su3
[addressbook]
## AddressBook subscription URL for initial setup
## Default: inr.i2p at "mainline" I2P Network
# defaulturl = http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt
## Optional subscriptions URLs, separated by comma
# subscriptions = http://inr.i2p/export/alive-hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
[http] [http]
## Uncomment and set to 'false' to disable Web Console ## Uncomment and set to 'false' to disable Web Console

View File

@ -32,7 +32,9 @@ Contents:
build_requirements build_requirements
build_notes_unix build_notes_unix
build_notes_windows build_notes_windows
build_notes_cross
build_notes_android build_notes_android
build_notes_ios
configuration configuration
family family
usage usage