mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
commit
1e56d17d39
@ -18,7 +18,11 @@ namespace i2p
|
||||
{
|
||||
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_RETRY_TIMEOUT = 1; // in minutes
|
||||
const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)
|
||||
|
19
Config.cpp
19
Config.cpp
@ -27,6 +27,10 @@ namespace config {
|
||||
variables_map m_Options;
|
||||
|
||||
void Init() {
|
||||
bool nat = true;
|
||||
#ifdef MESHNET
|
||||
nat = false;
|
||||
#endif
|
||||
options_description general("General options");
|
||||
general.add_options()
|
||||
("help", "Show this message")
|
||||
@ -39,6 +43,8 @@ namespace config {
|
||||
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
|
||||
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
|
||||
("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
|
||||
("ifname", value<std::string>()->default_value(""), "network interface to bind to")
|
||||
("nat", value<bool>()->zero_tokens()->default_value(nat), "should we assume we are behind NAT?")
|
||||
("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")
|
||||
("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
|
||||
@ -47,6 +53,8 @@ namespace config {
|
||||
("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup")
|
||||
("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill")
|
||||
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in kbps or letters: L (32), O (256), P (2048), X (>9000)")
|
||||
("ntcp", value<bool>()->zero_tokens()->default_value(true), "enable ntcp transport")
|
||||
("ssu", value<bool>()->zero_tokens()->default_value(true), "enable ssu transport")
|
||||
#ifdef _WIN32
|
||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||
("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping")
|
||||
@ -128,7 +136,13 @@ namespace config {
|
||||
#endif
|
||||
"Enable or disable elgamal precomputation table")
|
||||
;
|
||||
|
||||
|
||||
options_description trust("Trust options");
|
||||
trust.add_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.hidden", value<bool>()->default_value(false), "should we hide our router from other routers?");
|
||||
|
||||
m_OptionsDesc
|
||||
.add(general)
|
||||
.add(limits)
|
||||
@ -139,7 +153,8 @@ namespace config {
|
||||
.add(bob)
|
||||
.add(i2cp)
|
||||
.add(i2pcontrol)
|
||||
.add(precomputation)
|
||||
.add(precomputation)
|
||||
.add(trust)
|
||||
;
|
||||
}
|
||||
|
||||
|
108
Daemon.cpp
108
Daemon.cpp
@ -22,6 +22,7 @@
|
||||
#include "I2PControl.h"
|
||||
#include "ClientContext.h"
|
||||
#include "Crypto.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef USE_UPNP
|
||||
#include "UPnP.h"
|
||||
@ -114,7 +115,7 @@ namespace i2p
|
||||
}
|
||||
i2p::log::Logger().Ready();
|
||||
|
||||
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
||||
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
||||
LogPrint(eLogDebug, "FS: main config file: ", config);
|
||||
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
||||
|
||||
@ -122,6 +123,43 @@ namespace i2p
|
||||
i2p::crypto::InitCrypto (precomputation);
|
||||
i2p::context.Init ();
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
#ifdef MESHNET
|
||||
// manual override for meshnet
|
||||
ipv4 = false;
|
||||
ipv6 = true;
|
||||
#endif
|
||||
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
if (nat)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: assuming be are behind NAT");
|
||||
// we are behind nat, try setting via host
|
||||
std::string host; i2p::config::GetOption("host", host);
|
||||
if (!i2p::config::IsDefault("host"))
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: setting address for incoming connections to ", host);
|
||||
i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are not behind nat
|
||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||
if (ifname.size())
|
||||
{
|
||||
// bind to interface, we have no NAT so set external address too
|
||||
auto addr = i2p::util::net::GetInterfaceAddress(ifname, ipv6);
|
||||
LogPrint(eLogInfo, "Daemon: bind to network interface ", ifname, " with public address ", addr);
|
||||
i2p::context.UpdateAddress(addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t port; i2p::config::GetOption("port", port);
|
||||
if (!i2p::config::IsDefault("port"))
|
||||
{
|
||||
@ -129,15 +167,7 @@ namespace i2p
|
||||
i2p::context.UpdatePort (port);
|
||||
}
|
||||
|
||||
std::string host; i2p::config::GetOption("host", host);
|
||||
if (!i2p::config::IsDefault("host"))
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: setting address for incoming connections to ", host);
|
||||
i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
|
||||
}
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
|
||||
bool transit; i2p::config::GetOption("notransit", transit);
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
@ -192,31 +222,62 @@ namespace i2p
|
||||
i2p::context.SetFamily (family);
|
||||
if (family.length () > 0)
|
||||
LogPrint(eLogInfo, "Daemon: family set to ", family);
|
||||
|
||||
return true;
|
||||
|
||||
bool trust; i2p::config::GetOption("trust.enabled", trust);
|
||||
if (trust)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: explicit trust enabled");
|
||||
std::string fam; i2p::config::GetOption("trust.family", fam);
|
||||
if (fam.length() > 0)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: setting restricted routes to use family ", fam);
|
||||
i2p::transport::transports.RestrictRoutes({fam});
|
||||
} else
|
||||
LogPrint(eLogError, "Daemon: no family specified for restricted routes");
|
||||
}
|
||||
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
|
||||
if (hidden)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: using hidden mode");
|
||||
i2p::data::netdb.SetHidden(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Daemon_Singleton::start()
|
||||
{
|
||||
bool http; i2p::config::GetOption("http.enabled", http);
|
||||
if (http) {
|
||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||
LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort);
|
||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||
d.httpServer->Start();
|
||||
}
|
||||
|
||||
LogPrint(eLogInfo, "Daemon: starting NetDB");
|
||||
i2p::data::netdb.Start();
|
||||
|
||||
#ifdef USE_UPNP
|
||||
LogPrint(eLogInfo, "Daemon: starting UPnP");
|
||||
d.m_UPnP.Start ();
|
||||
#endif
|
||||
#endif
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||
i2p::transport::transports.Start();
|
||||
if(!ssu) LogPrint(eLogDebug, "Daemon: ssu disabled");
|
||||
if(!ntcp) LogPrint(eLogDebug, "Daemon: ntcp disabled");
|
||||
i2p::transport::transports.Start(ntcp, ssu);
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU()) {
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
} else {
|
||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||
/** shut down netdb right away */
|
||||
i2p::data::netdb.Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool http; i2p::config::GetOption("http.enabled", http);
|
||||
if (http) {
|
||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||
LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort);
|
||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||
d.httpServer->Start();
|
||||
}
|
||||
|
||||
|
||||
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
||||
i2p::tunnel::tunnels.Start();
|
||||
|
||||
@ -232,6 +293,7 @@ namespace i2p
|
||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||
d.m_I2PControlService->Start ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ namespace client
|
||||
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
|
||||
if (msgID == m_PublishReplyToken)
|
||||
{
|
||||
LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed");
|
||||
LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed for ", GetIdentHash().ToBase32());
|
||||
m_ExcludedFloodfills.clear ();
|
||||
m_PublishReplyToken = 0;
|
||||
// schedule verification
|
||||
@ -459,19 +459,16 @@ namespace client
|
||||
// "this" added due to bug in gcc 4.7-4.8
|
||||
[s,this](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||
{
|
||||
if (leaseSet)
|
||||
if (leaseSet && s->m_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 (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||
return;
|
||||
}
|
||||
// we got latest LeasetSet
|
||||
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32());
|
||||
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
||||
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||
return;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet");
|
||||
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32());
|
||||
// we have to publish again
|
||||
s->Publish ();
|
||||
});
|
||||
|
6
HTTP.cpp
6
HTTP.cpp
@ -72,7 +72,11 @@ namespace http {
|
||||
bool URL::parse(const std::string& url) {
|
||||
std::size_t pos_p = 0; /* < current parse position */
|
||||
std::size_t pos_c = 0; /* < work position */
|
||||
if (url.at(0) != '/') {
|
||||
if (url.at(0) == '/' && url.find("/http://") == 0) {
|
||||
/* special case for i2p.rocks inproxy */
|
||||
pos_p ++;
|
||||
}
|
||||
if(url.at(0) != '/' || pos_p > 0) {
|
||||
/* schema */
|
||||
pos_c = url.find("://");
|
||||
if (pos_c != std::string::npos) {
|
||||
|
25
I2CP.cpp
25
I2CP.cpp
@ -424,13 +424,24 @@ namespace client
|
||||
if (m_Destination)
|
||||
{
|
||||
i2p::data::IdentityEx identity;
|
||||
offset += identity.FromBuffer (buf + offset, len - offset);
|
||||
uint32_t payloadLen = bufbe32toh (buf + offset);
|
||||
offset += 4;
|
||||
uint32_t nonce = bufbe32toh (buf + offset + payloadLen);
|
||||
if (m_IsSendAccepted)
|
||||
SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted
|
||||
m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce);
|
||||
size_t identsize = identity.FromBuffer (buf + offset, len - offset);
|
||||
if (identsize)
|
||||
{
|
||||
offset += identsize;
|
||||
uint32_t payloadLen = bufbe32toh (buf + offset);
|
||||
if (payloadLen + offset <= len)
|
||||
{
|
||||
offset += 4;
|
||||
uint32_t nonce = bufbe32toh (buf + offset + payloadLen);
|
||||
if (m_IsSendAccepted)
|
||||
SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted
|
||||
m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce);
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: cannot send message, too big");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: invalid identity");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Transports.h"
|
||||
#include "Garlic.h"
|
||||
#include "I2NPProtocol.h"
|
||||
#include "version.h"
|
||||
|
||||
using namespace i2p::transport;
|
||||
|
||||
@ -101,7 +102,7 @@ namespace i2p
|
||||
{
|
||||
RAND_bytes ((uint8_t *)&msgID, 4);
|
||||
htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
|
||||
htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, 2); // netID = 2
|
||||
htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, I2PD_NET_ID);
|
||||
}
|
||||
m->len += DELIVERY_STATUS_SIZE;
|
||||
m->FillI2NPMessageHeader (eI2NPDeliveryStatus);
|
||||
|
@ -190,7 +190,7 @@ namespace data
|
||||
|
||||
bool LeaseSet::IsExpired () const
|
||||
{
|
||||
if (IsEmpty ()) return true;
|
||||
if (m_StoreLeases && IsEmpty ()) return true;
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
return ts > m_ExpirationTime;
|
||||
}
|
||||
|
5
Makefile
5
Makefile
@ -11,6 +11,7 @@ include filelist.mk
|
||||
|
||||
USE_AESNI := yes
|
||||
USE_STATIC := no
|
||||
USE_MESHNET := no
|
||||
USE_UPNP := no
|
||||
|
||||
ifeq ($(UNAME),Darwin)
|
||||
@ -31,6 +32,10 @@ else # win32 mingw
|
||||
include Makefile.mingw
|
||||
endif
|
||||
|
||||
ifeq ($(USE_MESHNET),yes)
|
||||
CXXFLAGS += -DMESHNET
|
||||
endif
|
||||
|
||||
all: mk_obj_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD)
|
||||
|
||||
mk_obj_dir:
|
||||
|
@ -760,30 +760,46 @@ namespace transport
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (auto address: addresses)
|
||||
{
|
||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP && address->host.is_v4 ())
|
||||
{
|
||||
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service,
|
||||
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession>(*this);
|
||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this,
|
||||
conn, std::placeholders::_1));
|
||||
|
||||
if (context.SupportsV6 ())
|
||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
{
|
||||
if (address->host.is_v4())
|
||||
{
|
||||
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
||||
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
||||
m_NTCPV6Acceptor->listen ();
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening V6 TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession> (*this);
|
||||
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6,
|
||||
this, conn, std::placeholders::_1));
|
||||
try
|
||||
{
|
||||
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service,
|
||||
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
||||
} catch ( std::exception & ex ) {
|
||||
/** fail to bind ip4 */
|
||||
LogPrint(eLogError, "NTCP: Failed to bind to ip4 port ",address->port, ex.what());
|
||||
continue;
|
||||
}
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession>(*this);
|
||||
m_NTCPAcceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAccept, this,
|
||||
conn, std::placeholders::_1));
|
||||
}
|
||||
else if (address->host.is_v6() && context.SupportsV6 ())
|
||||
{
|
||||
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
|
||||
try
|
||||
{
|
||||
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||
|
||||
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
||||
m_NTCPV6Acceptor->listen ();
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening V6 TCP port ", address->port);
|
||||
auto conn = std::make_shared<NTCPSession> (*this);
|
||||
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6,
|
||||
this, conn, std::placeholders::_1));
|
||||
} catch ( std::exception & ex ) {
|
||||
LogPrint(eLogError, "NTCP: failed to bind to ip6 port ", address->port);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -795,9 +811,11 @@ namespace transport
|
||||
if (m_IsRunning)
|
||||
{
|
||||
m_IsRunning = false;
|
||||
delete m_NTCPAcceptor;
|
||||
if (m_NTCPAcceptor)
|
||||
delete m_NTCPAcceptor;
|
||||
m_NTCPAcceptor = nullptr;
|
||||
delete m_NTCPV6Acceptor;
|
||||
if (m_NTCPV6Acceptor)
|
||||
delete m_NTCPV6Acceptor;
|
||||
m_NTCPV6Acceptor = nullptr;
|
||||
|
||||
m_Service.stop ();
|
||||
|
@ -144,7 +144,10 @@ namespace transport
|
||||
void RemoveNTCPSession (std::shared_ptr<NTCPSession> session);
|
||||
std::shared_ptr<NTCPSession> FindNTCPSession (const i2p::data::IdentHash& ident);
|
||||
void Connect (const boost::asio::ip::address& address, int port, std::shared_ptr<NTCPSession> conn);
|
||||
|
||||
|
||||
bool IsBoundV4() const { return m_NTCPAcceptor != nullptr; };
|
||||
bool IsBoundV6() const { return m_NTCPV6Acceptor != nullptr; };
|
||||
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
void Ban (const boost::asio::ip::address& addr);
|
||||
|
||||
|
73
NetDb.cpp
73
NetDb.cpp
@ -24,7 +24,7 @@ namespace data
|
||||
{
|
||||
NetDb netdb;
|
||||
|
||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat")
|
||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_HiddenMode(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ namespace data
|
||||
}
|
||||
m_LeaseSets.clear();
|
||||
m_Requests.Stop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::Run ()
|
||||
@ -121,8 +121,12 @@ namespace data
|
||||
ManageLookupResponses ();
|
||||
}
|
||||
lastSave = ts;
|
||||
}
|
||||
if (ts - lastPublish >= 2400) // publish every 40 minutes
|
||||
}
|
||||
|
||||
// if we're in hidden mode don't publish or explore
|
||||
// if (m_HiddenMode) continue;
|
||||
|
||||
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL) // publish
|
||||
{
|
||||
Publish ();
|
||||
lastPublish = ts;
|
||||
@ -161,6 +165,11 @@ namespace data
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetDb::SetHidden(bool hide) {
|
||||
// TODO: remove reachable addresses from router info
|
||||
m_HiddenMode = hide;
|
||||
}
|
||||
|
||||
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
||||
{
|
||||
bool updated = true;
|
||||
@ -174,10 +183,8 @@ namespace data
|
||||
// TODO: check if floodfill has been changed
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
|
||||
updated = false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -217,29 +224,29 @@ namespace data
|
||||
it->second->Update (buf, len);
|
||||
if (it->second->IsValid ())
|
||||
{
|
||||
LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64());
|
||||
LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32());
|
||||
updated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64());
|
||||
LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32());
|
||||
m_LeaseSets.erase (it);
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase64());
|
||||
LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto leaseSet = std::make_shared<LeaseSet> (buf, len, false); // we don't need leases in netdb
|
||||
if (leaseSet->IsValid ())
|
||||
{
|
||||
LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64());
|
||||
LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32());
|
||||
m_LeaseSets[ident] = leaseSet;
|
||||
updated = true;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase64());
|
||||
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32());
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
@ -461,7 +468,7 @@ namespace data
|
||||
bool updated = false;
|
||||
if (buf[DATABASE_STORE_TYPE_OFFSET]) // type
|
||||
{
|
||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet");
|
||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32());
|
||||
updated = AddLeaseSet (ident, buf + offset, len - offset, m->from);
|
||||
}
|
||||
else
|
||||
@ -487,7 +494,7 @@ namespace data
|
||||
uint8_t * payload = floodMsg->GetPayload ();
|
||||
memcpy (payload, buf, 33); // key + type
|
||||
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token
|
||||
auto msgLen = len - payloadOffset;
|
||||
size_t msgLen = len - payloadOffset;
|
||||
floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen;
|
||||
if (floodMsg->len < floodMsg->maxLen)
|
||||
{
|
||||
@ -501,16 +508,18 @@ namespace data
|
||||
auto floodfill = GetClosestFloodfill (ident, excluded);
|
||||
if (floodfill)
|
||||
{
|
||||
transports.SendMessage (floodfill->GetIdentHash (), CopyI2NPMessage(floodMsg));
|
||||
excluded.insert (floodfill->GetIdentHash ());
|
||||
auto h = floodfill->GetIdentHash();
|
||||
LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64());
|
||||
transports.SendMessage (h, CopyI2NPMessage(floodMsg));
|
||||
excluded.insert (h);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Database store message is too long ", floodMsg->len);
|
||||
}
|
||||
LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len);
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg)
|
||||
@ -615,13 +624,16 @@ namespace data
|
||||
int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48);
|
||||
key[l] = 0;
|
||||
uint8_t flag = buf[64];
|
||||
|
||||
IdentHash replyIdent(buf + 32);
|
||||
|
||||
LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " recieved flags=", (int)flag);
|
||||
uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK;
|
||||
const uint8_t * excluded = buf + 65;
|
||||
uint32_t replyTunnelID = 0;
|
||||
if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel
|
||||
{
|
||||
replyTunnelID = bufbe32toh (buf + 64);
|
||||
replyTunnelID = bufbe32toh (buf + 65);
|
||||
excluded += 4;
|
||||
}
|
||||
uint16_t numExcluded = bufbe16toh (excluded);
|
||||
@ -673,7 +685,12 @@ namespace data
|
||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
|
||||
{
|
||||
auto leaseSet = FindLeaseSet (ident);
|
||||
if (leaseSet && !leaseSet->IsExpired ()) // we don't send back our LeaseSets
|
||||
if (!leaseSet)
|
||||
{
|
||||
// no lease set found
|
||||
LogPrint(eLogDebug, "NetDb: requested LeaseSet not found for ", ident.ToBase32());
|
||||
}
|
||||
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
|
||||
{
|
||||
LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found");
|
||||
replyMsg = CreateDatabaseStoreMsg (leaseSet);
|
||||
@ -730,12 +747,12 @@ namespace data
|
||||
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
|
||||
if (outbound)
|
||||
outbound->SendTunnelDataMsg (buf+32, replyTunnelID, replyMsg);
|
||||
outbound->SendTunnelDataMsg (replyIdent, replyTunnelID, replyMsg);
|
||||
else
|
||||
transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg));
|
||||
transports.SendMessage (replyIdent, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg));
|
||||
}
|
||||
else
|
||||
transports.SendMessage (buf+32, replyMsg);
|
||||
transports.SendMessage (replyIdent, replyMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -862,7 +879,7 @@ namespace data
|
||||
{
|
||||
if (m_RouterInfos.empty())
|
||||
return 0;
|
||||
uint32_t ind = rand () % m_RouterInfos.size ();
|
||||
uint32_t ind = rand () % m_RouterInfos.size ();
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
@ -966,6 +983,14 @@ namespace data
|
||||
return res;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily(const std::string & fam) const {
|
||||
return GetRandomRouter(
|
||||
[fam](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
return router->IsFamily(fam);
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetClosestNonFloodfill (const IdentHash& destination,
|
||||
const std::set<IdentHash>& excluded) const
|
||||
{
|
||||
|
17
NetDb.h
17
NetDb.h
@ -31,6 +31,12 @@ namespace data
|
||||
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
|
||||
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90*60; // 1.5 hours
|
||||
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27*60*60; // 27 hours
|
||||
|
||||
#ifdef MESHNET
|
||||
const int NETDB_PUBLISH_INTERVAL = 60;
|
||||
#else
|
||||
const int NETDB_PUBLISH_INTERVAL = 60*40;
|
||||
#endif
|
||||
|
||||
class NetDb
|
||||
{
|
||||
@ -64,10 +70,14 @@ namespace data
|
||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
||||
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||
|
||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
||||
/** set hidden mode, aka don't publish our RI to netdb and don't explore */
|
||||
void SetHidden(bool hide);
|
||||
|
||||
void Reseed ();
|
||||
Families& GetFamilies () { return m_Families; };
|
||||
|
||||
@ -88,8 +98,8 @@ namespace data
|
||||
void ManageRequests ();
|
||||
void ManageLookupResponses ();
|
||||
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
||||
|
||||
private:
|
||||
|
||||
@ -113,6 +123,9 @@ namespace data
|
||||
NetDbRequests m_Requests;
|
||||
|
||||
std::map<IdentHash, std::pair<std::vector<IdentHash>, uint64_t> > m_LookupResponses; // ident->(closest FFs, timestamp)
|
||||
|
||||
/** true if in hidden mode */
|
||||
bool m_HiddenMode;
|
||||
};
|
||||
|
||||
extern NetDb netdb;
|
||||
|
22
Reseed.cpp
22
Reseed.cpp
@ -20,20 +20,26 @@ namespace i2p
|
||||
{
|
||||
namespace data
|
||||
{
|
||||
static std::vector<std::string> httpsReseedHostList =
|
||||
static std::vector<std::string> httpsReseedHostList =
|
||||
{
|
||||
#ifdef MESHNET
|
||||
// meshnet i2p reseeds
|
||||
"https://reseed.i2p.rocks:8443/"
|
||||
#else
|
||||
// mainline i2p reseeds
|
||||
"https://reseed.i2p-projekt.de/", // Only HTTPS
|
||||
"https://i2p.mooo.com/netDb/",
|
||||
"https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required
|
||||
"https://i2p.mooo.com/netDb/",
|
||||
"https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required
|
||||
"https://us.reseed.i2p2.no:444/",
|
||||
"https://uk.reseed.i2p2.no:444/",
|
||||
"https://uk.reseed.i2p2.no:444/",
|
||||
"https://i2p.manas.ca:8443/",
|
||||
"https://i2p-0.manas.ca:8443/",
|
||||
"https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support
|
||||
"https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support
|
||||
"https://download.xxlspeed.com/" // Only HTTPS and SU3 (v3) support
|
||||
"https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support
|
||||
"https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support
|
||||
"https://download.xxlspeed.com/" // Only HTTPS and SU3 (v3) support
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
Reseeder::Reseeder()
|
||||
{
|
||||
}
|
||||
|
@ -290,7 +290,11 @@ namespace data
|
||||
|
||||
if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers))
|
||||
SetUnreachable (true);
|
||||
}
|
||||
}
|
||||
|
||||
bool RouterInfo::IsFamily(const std::string & fam) const {
|
||||
return m_Family == fam;
|
||||
}
|
||||
|
||||
void RouterInfo::ExtractCaps (const char * value)
|
||||
{
|
||||
|
@ -171,6 +171,9 @@ namespace data
|
||||
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
|
||||
bool IsNewer (const uint8_t * buf, size_t len) const;
|
||||
|
||||
/** return true if we are in a router family and the signature is valid */
|
||||
bool IsFamily(const std::string & fam) const;
|
||||
|
||||
// implements RoutingDestination
|
||||
const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); };
|
||||
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; };
|
||||
|
3
SAM.cpp
3
SAM.cpp
@ -56,7 +56,8 @@ namespace client
|
||||
if (m_Session)
|
||||
{
|
||||
m_Session->DelSocket (shared_from_this ());
|
||||
m_Session->localDestination->StopAcceptingStreams ();
|
||||
if (m_Session->localDestination)
|
||||
m_Session->localDestination->StopAcceptingStreams ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
32
SSU.cpp
32
SSU.cpp
@ -10,12 +10,31 @@ namespace i2p
|
||||
{
|
||||
namespace transport
|
||||
{
|
||||
SSUServer::SSUServer (int port): m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr),
|
||||
|
||||
SSUServer::SSUServer (const boost::asio::ip::address & addr, int port):
|
||||
m_OnlyV6(true), m_IsRunning(false),
|
||||
m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr),
|
||||
m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService),
|
||||
m_EndpointV6 (addr, port),
|
||||
m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversService),
|
||||
m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service)
|
||||
{
|
||||
m_SocketV6.open (boost::asio::ip::udp::v6());
|
||||
m_SocketV6.set_option (boost::asio::ip::v6_only (true));
|
||||
m_SocketV6.set_option (boost::asio::socket_base::receive_buffer_size (65535));
|
||||
m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (65535));
|
||||
m_SocketV6.bind (m_EndpointV6);
|
||||
}
|
||||
|
||||
SSUServer::SSUServer (int port):
|
||||
m_OnlyV6(false), m_IsRunning(false),
|
||||
m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr),
|
||||
m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService),
|
||||
m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port),
|
||||
m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversService),
|
||||
m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service)
|
||||
{
|
||||
|
||||
m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (65535));
|
||||
m_Socket.set_option (boost::asio::socket_base::send_buffer_size (65535));
|
||||
if (context.SupportsV6 ())
|
||||
@ -35,13 +54,16 @@ namespace transport
|
||||
void SSUServer::Start ()
|
||||
{
|
||||
m_IsRunning = true;
|
||||
m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this));
|
||||
m_Thread = new std::thread (std::bind (&SSUServer::Run, this));
|
||||
m_ReceiversService.post (std::bind (&SSUServer::Receive, this));
|
||||
m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this));
|
||||
if (!m_OnlyV6)
|
||||
{
|
||||
m_Thread = new std::thread (std::bind (&SSUServer::Run, this));
|
||||
m_ReceiversService.post (std::bind (&SSUServer::Receive, this));
|
||||
}
|
||||
if (context.SupportsV6 ())
|
||||
{
|
||||
m_ThreadV6 = new std::thread (std::bind (&SSUServer::RunV6, this));
|
||||
m_ReceiversService.post (std::bind (&SSUServer::ReceiveV6, this));
|
||||
m_ReceiversService.post (std::bind (&SSUServer::ReceiveV6, this));
|
||||
}
|
||||
SchedulePeerTestsCleanupTimer ();
|
||||
ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers
|
||||
|
6
SSU.h
6
SSU.h
@ -37,6 +37,7 @@ namespace transport
|
||||
public:
|
||||
|
||||
SSUServer (int port);
|
||||
SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor
|
||||
~SSUServer ();
|
||||
void Start ();
|
||||
void Stop ();
|
||||
@ -62,7 +63,7 @@ namespace transport
|
||||
std::shared_ptr<SSUSession> GetPeerTestSession (uint32_t nonce);
|
||||
void UpdatePeerTest (uint32_t nonce, PeerTestParticipant role);
|
||||
void RemovePeerTest (uint32_t nonce);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
@ -93,8 +94,9 @@ namespace transport
|
||||
uint64_t creationTime;
|
||||
PeerTestParticipant role;
|
||||
std::shared_ptr<SSUSession> session; // for Bob to Alice
|
||||
};
|
||||
};
|
||||
|
||||
bool m_OnlyV6;
|
||||
bool m_IsRunning;
|
||||
std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread;
|
||||
boost::asio::io_service m_Service, m_ServiceV6, m_ReceiversService;
|
||||
|
@ -18,7 +18,11 @@ namespace transport
|
||||
{
|
||||
|
||||
const size_t SSU_MTU_V4 = 1484;
|
||||
#ifdef MESHNET
|
||||
const size_t SSU_MTU_V6 = 1286;
|
||||
#else
|
||||
const size_t SSU_MTU_V6 = 1472;
|
||||
#endif
|
||||
const size_t IPV4_HEADER_SIZE = 20;
|
||||
const size_t IPV6_HEADER_SIZE = 40;
|
||||
const size_t UDP_HEADER_SIZE = 8;
|
||||
|
@ -20,14 +20,14 @@ namespace transport
|
||||
if (router)
|
||||
{
|
||||
// we are client
|
||||
auto address = router->GetSSUAddress ();
|
||||
auto address = router->GetSSUAddress (false);
|
||||
if (address) m_IntroKey = address->key;
|
||||
m_Data.AdjustPacketSize (router); // mtu
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are server
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress ();
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false);
|
||||
if (address) m_IntroKey = address->key;
|
||||
}
|
||||
m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
@ -108,7 +108,7 @@ namespace transport
|
||||
else
|
||||
{
|
||||
// try own intro key
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress ();
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false);
|
||||
if (!address)
|
||||
{
|
||||
LogPrint (eLogInfo, "SSU is not supported");
|
||||
@ -366,7 +366,7 @@ namespace transport
|
||||
|
||||
void SSUSession::SendRelayRequest (const i2p::data::RouterInfo::Introducer& introducer, uint32_t nonce)
|
||||
{
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress ();
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false);
|
||||
if (!address)
|
||||
{
|
||||
LogPrint (eLogInfo, "SSU is not supported");
|
||||
@ -1079,7 +1079,7 @@ namespace transport
|
||||
{
|
||||
// we are Alice
|
||||
LogPrint (eLogDebug, "SSU: sending peer test");
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress ();
|
||||
auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false);
|
||||
if (!address)
|
||||
{
|
||||
LogPrint (eLogInfo, "SSU is not supported. Can't send peer test");
|
||||
|
112
Transports.cpp
112
Transports.cpp
@ -46,7 +46,7 @@ namespace transport
|
||||
int num;
|
||||
while ((num = m_QueueSize - m_Queue.size ()) > 0)
|
||||
CreateDHKeysPairs (num);
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
m_Acquired.wait (l); // wait for element gets aquired
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@ namespace transport
|
||||
{
|
||||
auto pair = std::make_shared<i2p::crypto::DHKeys> ();
|
||||
pair->GenerateKeys ();
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
m_Queue.push (pair);
|
||||
}
|
||||
}
|
||||
@ -69,7 +69,7 @@ namespace transport
|
||||
std::shared_ptr<i2p::crypto::DHKeys> DHKeysPairSupplier::Acquire ()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
if (!m_Queue.empty ())
|
||||
{
|
||||
auto pair = m_Queue.front ();
|
||||
@ -86,7 +86,7 @@ namespace transport
|
||||
|
||||
void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||
m_Queue.push (pair);
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ namespace transport
|
||||
Stop ();
|
||||
}
|
||||
|
||||
void Transports::Start ()
|
||||
void Transports::Start (bool enableNTCP, bool enableSSU)
|
||||
{
|
||||
m_DHKeysPairSupplier.Start ();
|
||||
m_IsRunning = true;
|
||||
@ -114,19 +114,36 @@ namespace transport
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (auto address : addresses)
|
||||
{
|
||||
if (!m_NTCPServer)
|
||||
{
|
||||
if (!m_NTCPServer && enableNTCP)
|
||||
{
|
||||
m_NTCPServer = new NTCPServer ();
|
||||
m_NTCPServer->Start ();
|
||||
if (!(m_NTCPServer->IsBoundV6() || m_NTCPServer->IsBoundV4())) {
|
||||
/** failed to bind to NTCP */
|
||||
LogPrint(eLogError, "Transports: failed to bind to TCP");
|
||||
m_NTCPServer->Stop();
|
||||
delete m_NTCPServer;
|
||||
m_NTCPServer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (address->transportStyle == RouterInfo::eTransportSSU && address->host.is_v4 ())
|
||||
if (address->transportStyle == RouterInfo::eTransportSSU)
|
||||
{
|
||||
if (!m_SSUServer)
|
||||
{
|
||||
m_SSUServer = new SSUServer (address->port);
|
||||
if (!m_SSUServer && enableSSU)
|
||||
{
|
||||
if (address->host.is_v4())
|
||||
m_SSUServer = new SSUServer (address->port);
|
||||
else
|
||||
m_SSUServer = new SSUServer (address->host, address->port);
|
||||
LogPrint (eLogInfo, "Transports: Start listening UDP port ", address->port);
|
||||
m_SSUServer->Start ();
|
||||
try {
|
||||
m_SSUServer->Start ();
|
||||
} catch ( std::exception & ex ) {
|
||||
LogPrint(eLogError, "Transports: Failed to bind to UDP port", address->port);
|
||||
delete m_SSUServer;
|
||||
m_SSUServer = nullptr;
|
||||
continue;
|
||||
}
|
||||
DetectExternalIP ();
|
||||
}
|
||||
else
|
||||
@ -206,7 +223,7 @@ namespace transport
|
||||
|
||||
void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
SendMessages (ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > {msg });
|
||||
SendMessages (ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > {msg });
|
||||
}
|
||||
|
||||
void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs)
|
||||
@ -231,7 +248,7 @@ namespace transport
|
||||
{
|
||||
auto r = netdb.FindRouter (ident);
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
|
||||
i2p::util::GetSecondsSinceEpoch (), {} })).first;
|
||||
}
|
||||
@ -288,7 +305,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Transports: NTCP address is not present for ", i2p::data::GetIdentHashAbbreviation (ident), ", trying SSU");
|
||||
LogPrint (eLogDebug, "Transports: NTCP address is not present for ", i2p::data::GetIdentHashAbbreviation (ident), ", trying SSU");
|
||||
}
|
||||
if (peer.numAttempts == 1)// SSU
|
||||
{
|
||||
@ -320,7 +337,7 @@ namespace transport
|
||||
}
|
||||
LogPrint (eLogError, "Transports: No NTCP or SSU addresses available");
|
||||
peer.Done ();
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (ident);
|
||||
return false;
|
||||
}
|
||||
@ -352,7 +369,7 @@ namespace transport
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Transports: RouterInfo not found, Failed to send messages");
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it);
|
||||
}
|
||||
}
|
||||
@ -396,7 +413,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
LogPrint (eLogError, "Transports: Unable to resolve NTCP address: ", ecode.message ());
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it1);
|
||||
}
|
||||
}
|
||||
@ -438,7 +455,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
LogPrint (eLogError, "Transports: Unable to resolve SSU address: ", ecode.message ());
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it1);
|
||||
}
|
||||
}
|
||||
@ -446,7 +463,7 @@ namespace transport
|
||||
void Transports::CloseSession (std::shared_ptr<const i2p::data::RouterInfo> router)
|
||||
{
|
||||
if (!router) return;
|
||||
m_Service.post (std::bind (&Transports::PostCloseSession, this, router));
|
||||
m_Service.post (std::bind (&Transports::PostCloseSession, this, router));
|
||||
}
|
||||
|
||||
void Transports::PostCloseSession (std::shared_ptr<const i2p::data::RouterInfo> router)
|
||||
@ -469,18 +486,21 @@ namespace transport
|
||||
{
|
||||
if (m_SSUServer)
|
||||
{
|
||||
#ifndef MESHNET
|
||||
i2p::context.SetStatus (eRouterStatusTesting);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
auto router = i2p::data::netdb.GetRandomPeerTestRouter ();
|
||||
if (router && router->IsSSU (!context.SupportsV6 ()))
|
||||
m_SSUServer->CreateSession (router, true); // peer test
|
||||
if (router && router->IsSSU (!context.SupportsV6 ()))
|
||||
m_SSUServer->CreateSession (router, true); // peer test
|
||||
else
|
||||
{
|
||||
// if not peer test capable routers found pick any
|
||||
router = i2p::data::netdb.GetRandomRouter ();
|
||||
if (router && router->IsSSU ())
|
||||
m_SSUServer->CreateSession (router); // no peer test
|
||||
m_SSUServer->CreateSession (router); // no peer test
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -503,7 +523,7 @@ namespace transport
|
||||
statusChanged = true;
|
||||
i2p::context.SetStatus (eRouterStatusTesting); // first time only
|
||||
}
|
||||
m_SSUServer->CreateSession (router, true); // peer test
|
||||
m_SSUServer->CreateSession (router, true); // peer test
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -522,7 +542,7 @@ namespace transport
|
||||
void Transports::PeerConnected (std::shared_ptr<TransportSession> session)
|
||||
{
|
||||
m_Service.post([session, this]()
|
||||
{
|
||||
{
|
||||
auto remoteIdentity = session->GetRemoteIdentity ();
|
||||
if (!remoteIdentity) return;
|
||||
auto ident = remoteIdentity->GetIdentHash ();
|
||||
@ -535,7 +555,7 @@ namespace transport
|
||||
// check if first message is our DatabaseStore (publishing)
|
||||
auto firstMsg = it->second.delayedMessages[0];
|
||||
if (firstMsg && firstMsg->GetTypeID () == eI2NPDatabaseStore &&
|
||||
i2p::data::IdentHash(firstMsg->GetPayload () + DATABASE_STORE_KEY_OFFSET) == i2p::context.GetIdentHash ())
|
||||
i2p::data::IdentHash(firstMsg->GetPayload () + DATABASE_STORE_KEY_OFFSET) == i2p::context.GetIdentHash ())
|
||||
sendDatabaseStore = false; // we have it in the list already
|
||||
}
|
||||
if (sendDatabaseStore)
|
||||
@ -547,7 +567,7 @@ namespace transport
|
||||
else // incoming connection
|
||||
{
|
||||
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} }));
|
||||
}
|
||||
});
|
||||
@ -556,7 +576,7 @@ namespace transport
|
||||
void Transports::PeerDisconnected (std::shared_ptr<TransportSession> session)
|
||||
{
|
||||
m_Service.post([session, this]()
|
||||
{
|
||||
{
|
||||
auto remoteIdentity = session->GetRemoteIdentity ();
|
||||
if (!remoteIdentity) return;
|
||||
auto ident = remoteIdentity->GetIdentHash ();
|
||||
@ -570,7 +590,7 @@ namespace transport
|
||||
ConnectToPeer (ident, it->second);
|
||||
else
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it);
|
||||
}
|
||||
}
|
||||
@ -595,14 +615,20 @@ namespace transport
|
||||
if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
|
||||
{
|
||||
LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds");
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
auto profile = i2p::data::GetRouterProfile(it->first);
|
||||
if (profile)
|
||||
{
|
||||
profile->TunnelNonReplied();
|
||||
profile->Save();
|
||||
}
|
||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||
it = m_Peers.erase (it);
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
UpdateBandwidth (); // TODO: use separate timer(s) for it
|
||||
if (i2p::context.GetStatus () == eRouterStatusTesting) // if still testing, repeat peer test
|
||||
if (i2p::context.GetStatus () == eRouterStatusTesting) // if still testing, repeat peer test
|
||||
DetectExternalIP ();
|
||||
m_PeerCleanupTimer.expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT));
|
||||
m_PeerCleanupTimer.async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
||||
@ -617,6 +643,30 @@ namespace transport
|
||||
std::advance (it, rand () % m_Peers.size ());
|
||||
return it != m_Peers.end () ? it->second.router : nullptr;
|
||||
}
|
||||
void Transports::RestrictRoutes(std::vector<std::string> families)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_FamilyMutex);
|
||||
m_TrustedFamilies.clear();
|
||||
for ( auto fam : families )
|
||||
m_TrustedFamilies.push_back(fam);
|
||||
}
|
||||
|
||||
bool Transports::RoutesRestricted() const {
|
||||
std::lock_guard<std::mutex> lock(m_FamilyMutex);
|
||||
return m_TrustedFamilies.size() > 0;
|
||||
}
|
||||
|
||||
/** XXX: if routes are not restricted this dies */
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer() const {
|
||||
std::string fam;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_FamilyMutex);
|
||||
// TODO: random family (?)
|
||||
fam = m_TrustedFamilies[0];
|
||||
}
|
||||
boost::to_lower(fam);
|
||||
return i2p::data::netdb.GetRandomRouterInFamily(fam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
16
Transports.h
16
Transports.h
@ -73,8 +73,11 @@ namespace transport
|
||||
Transports ();
|
||||
~Transports ();
|
||||
|
||||
void Start ();
|
||||
void Start (bool enableNTCP=true, bool enableSSU=true);
|
||||
void Stop ();
|
||||
|
||||
bool IsBoundNTCP() const { return m_NTCPServer != nullptr; }
|
||||
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
||||
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
std::shared_ptr<i2p::crypto::DHKeys> GetNextDHKeysPair ();
|
||||
@ -98,6 +101,13 @@ namespace transport
|
||||
size_t GetNumPeers () const { return m_Peers.size (); };
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer () const;
|
||||
|
||||
/** get a trusted first hop for restricted routes */
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
|
||||
/** do we want to use restricted routes? */
|
||||
bool RoutesRestricted() const;
|
||||
/** restrict routes to use only these router families for first hops */
|
||||
void RestrictRoutes(std::vector<std::string> families);
|
||||
|
||||
void PeerTest ();
|
||||
|
||||
private:
|
||||
@ -140,6 +150,10 @@ namespace transport
|
||||
uint64_t m_LastInBandwidthUpdateBytes, m_LastOutBandwidthUpdateBytes;
|
||||
uint64_t m_LastBandwidthUpdateTime;
|
||||
|
||||
/** which router families to trust for first hops */
|
||||
std::vector<std::string> m_TrustedFamilies;
|
||||
mutable std::mutex m_FamilyMutex;
|
||||
|
||||
public:
|
||||
|
||||
// for HTTP only
|
||||
|
@ -443,7 +443,7 @@ namespace tunnel
|
||||
if (msg)
|
||||
{
|
||||
uint32_t prevTunnelID = 0, tunnelID = 0;
|
||||
std::shared_ptr<TunnelBase> prevTunnel;
|
||||
std::shared_ptr<TunnelBase> prevTunnel;
|
||||
do
|
||||
{
|
||||
std::shared_ptr<TunnelBase> tunnel;
|
||||
@ -458,7 +458,7 @@ namespace tunnel
|
||||
tunnel = prevTunnel;
|
||||
else if (prevTunnel)
|
||||
prevTunnel->FlushTunnelDataMsgs ();
|
||||
|
||||
|
||||
if (!tunnel)
|
||||
tunnel = GetTunnel (tunnelID);
|
||||
if (tunnel)
|
||||
@ -468,8 +468,9 @@ namespace tunnel
|
||||
else // tunnel gateway assumed
|
||||
HandleTunnelGatewayMsg (tunnel, msg);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Tunnel: tunnel with id ", tunnelID, " not found");
|
||||
else
|
||||
LogPrint (eLogWarning, "Tunnel: tunnel not found, tunnelID=", tunnelID, " previousTunnelID=", prevTunnelID, " type=", (int)typeID);
|
||||
|
||||
break;
|
||||
}
|
||||
case eI2NPVariableTunnelBuild:
|
||||
|
2
Tunnel.h
2
Tunnel.h
@ -224,7 +224,7 @@ namespace tunnel
|
||||
std::list<std::shared_ptr<TunnelPool>> m_Pools;
|
||||
std::shared_ptr<TunnelPool> m_ExploratoryPool;
|
||||
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
|
||||
|
||||
|
||||
// some stats
|
||||
int m_NumSuccesiveTunnelCreations, m_NumFailedTunnelCreations;
|
||||
|
||||
|
@ -205,7 +205,7 @@ namespace tunnel
|
||||
if (it->second.fragmentNum == msg.nextFragmentNum)
|
||||
{
|
||||
LogPrint (eLogWarning, "TunnelMessage: Out-of-sequence fragment ", (int)it->second.fragmentNum, " of message ", msgID, " found");
|
||||
auto size = it->second.data->GetLength ();
|
||||
size_t size = it->second.data->GetLength ();
|
||||
if (msg.data->len + size > msg.data->maxLen)
|
||||
{
|
||||
LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough");
|
||||
@ -235,7 +235,7 @@ namespace tunnel
|
||||
LogPrint (eLogInfo, "TunnelMessage: message expired");
|
||||
return;
|
||||
}
|
||||
auto typeID = msg.data->GetTypeID ();
|
||||
uint8_t typeID = msg.data->GetTypeID ();
|
||||
LogPrint (eLogDebug, "TunnelMessage: handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID);
|
||||
// catch RI or reply with new list of routers
|
||||
if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) &&
|
||||
|
@ -49,7 +49,7 @@ namespace tunnel
|
||||
|
||||
// create fragments
|
||||
std::shared_ptr<I2NPMessage> msg = block.data;
|
||||
auto fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
|
||||
size_t fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
|
||||
if (fullMsgLen <= m_RemainingSize)
|
||||
{
|
||||
// message fits. First and last fragment
|
||||
@ -66,10 +66,10 @@ namespace tunnel
|
||||
{
|
||||
if (!messageCreated) // check if we should complete previous message
|
||||
{
|
||||
auto numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||
size_t numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||
// length of bytes don't fit full tunnel message
|
||||
// every follow-on fragment adds 7 bytes
|
||||
auto nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||
size_t nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||
if (!nonFit || nonFit > m_RemainingSize)
|
||||
{
|
||||
CompleteCurrentTunnelDataMessage ();
|
||||
|
@ -322,7 +322,7 @@ namespace tunnel
|
||||
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop);
|
||||
|
||||
if (!hop || hop->GetProfile ()->IsBad ())
|
||||
hop = i2p::data::netdb.GetRandomRouter ();
|
||||
hop = i2p::data::netdb.GetRandomRouter (prevHop);
|
||||
return hop;
|
||||
}
|
||||
|
||||
@ -330,20 +330,17 @@ namespace tunnel
|
||||
{
|
||||
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
||||
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
||||
if (numHops <= 0) return true; // peers is empty
|
||||
auto prevHop = i2p::context.GetSharedRouterInfo ();
|
||||
if (i2p::transport::transports.GetNumPeers () > 25)
|
||||
if (numHops <= 0) return true;
|
||||
auto prevHop = i2p::context.GetSharedRouterInfo();
|
||||
if(i2p::transport::transports.RoutesRestricted())
|
||||
{
|
||||
auto r = i2p::transport::transports.GetRandomPeer ();
|
||||
if (r && !r->GetProfile ()->IsBad ())
|
||||
{
|
||||
prevHop = r;
|
||||
peers.push_back (r->GetRouterIdentity ());
|
||||
numHops--;
|
||||
}
|
||||
/** if routes are restricted prepend trusted first hop */
|
||||
auto hop = i2p::transport::transports.GetRestrictedPeer();
|
||||
if(!hop) return false;
|
||||
peers.push_back(hop->GetRouterIdentity());
|
||||
prevHop = hop;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numHops; i++)
|
||||
for(int i = 0; i < numHops; i++ )
|
||||
{
|
||||
auto hop = SelectNextHop (prevHop);
|
||||
if (!hop)
|
||||
@ -353,7 +350,7 @@ namespace tunnel
|
||||
}
|
||||
prevHop = hop;
|
||||
peers.push_back (hop->GetRouterIdentity ());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ option(WITH_STATIC "Static build" OFF)
|
||||
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||
option(WITH_PCH "Use precompiled header" OFF)
|
||||
option(WITH_GUI "Include GUI (currently MS Windows only)" ON)
|
||||
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
||||
|
||||
# paths
|
||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
||||
@ -90,6 +91,10 @@ set (DAEMON_SRC
|
||||
"${CMAKE_SOURCE_DIR}/UPnP.cpp"
|
||||
)
|
||||
|
||||
if (WITH_MESHNET)
|
||||
add_definitions(-DMESHNET)
|
||||
endif ()
|
||||
|
||||
if (WITH_UPNP)
|
||||
add_definitions(-DUSE_UPNP)
|
||||
if (NOT MSVC AND NOT MSYS)
|
||||
@ -296,6 +301,14 @@ link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib ${ZLIB_ROOT}/lib)
|
||||
# load includes
|
||||
include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
|
||||
|
||||
|
||||
# warn if for meshnet
|
||||
if (WITH_MESHNET)
|
||||
message(STATUS "Building for testnet")
|
||||
message(WARNING "This build will NOT work on mainline i2p")
|
||||
endif()
|
||||
|
||||
|
||||
# show summary
|
||||
message(STATUS "---------------------------------------")
|
||||
message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
|
||||
@ -311,6 +324,7 @@ message(STATUS " BINARY : ${WITH_BINARY}")
|
||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||
message(STATUS " PCH : ${WITH_PCH}")
|
||||
message(STATUS " MESHNET : ${WITH_MESHNET}")
|
||||
message(STATUS "---------------------------------------")
|
||||
|
||||
#Handle paths nicely
|
||||
|
47
util.cpp
47
util.cpp
@ -413,7 +413,52 @@ namespace net
|
||||
return GetMTUUnix(localAddress, fallback);
|
||||
#endif
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6)
|
||||
{
|
||||
#ifdef WIN32
|
||||
LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
|
||||
return boost::asio::ip::from_string("127.0.0.1");
|
||||
#else
|
||||
int af = (ipv6 ? AF_INET6 : AF_INET);
|
||||
ifaddrs * addrs = nullptr;
|
||||
if(getifaddrs(&addrs) == 0)
|
||||
{
|
||||
// got ifaddrs
|
||||
ifaddrs * cur = addrs;
|
||||
while(cur)
|
||||
{
|
||||
std::string cur_ifname(cur->ifa_name);
|
||||
if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
|
||||
{
|
||||
// match
|
||||
char * addr = new char[INET6_ADDRSTRLEN];
|
||||
bzero(addr, INET6_ADDRSTRLEN);
|
||||
if(af == AF_INET)
|
||||
inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
|
||||
else
|
||||
inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN);
|
||||
freeifaddrs(addrs);
|
||||
std::string cur_ifaddr(addr);
|
||||
return boost::asio::ip::address::from_string(cur_ifaddr);
|
||||
}
|
||||
cur = cur->ifa_next;
|
||||
}
|
||||
}
|
||||
if(addrs) freeifaddrs(addrs);
|
||||
std::string fallback;
|
||||
if(ipv6) {
|
||||
fallback = "::";
|
||||
LogPrint(eLogWarning, "NetIface: cannot find ipv6 address for interface ", ifname);
|
||||
} else {
|
||||
fallback = "127.0.0.1";
|
||||
LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
|
||||
}
|
||||
return boost::asio::ip::address::from_string(fallback);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // util
|
||||
|
1
util.h
1
util.h
@ -66,6 +66,7 @@ namespace util
|
||||
namespace net
|
||||
{
|
||||
int GetMTU (const boost::asio::ip::address& localAddress);
|
||||
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,12 @@
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||
#define VERSION I2PD_VERSION
|
||||
|
||||
#ifdef MESHNET
|
||||
#define I2PD_NET_ID 3
|
||||
#else
|
||||
#define I2PD_NET_ID 2
|
||||
#endif
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
|
Loading…
Reference in New Issue
Block a user