mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-26 20:34:15 +00:00
commit
31ff1372ae
@ -330,8 +330,7 @@ namespace client
|
||||
LoadHostsFromStream (f);
|
||||
m_IsLoaded = true;
|
||||
}
|
||||
// load local
|
||||
m_Storage->LoadLocal (m_Addresses);
|
||||
LoadLocal ();
|
||||
}
|
||||
|
||||
void AddressBook::LoadHostsFromStream (std::istream& f)
|
||||
@ -395,6 +394,40 @@ namespace client
|
||||
LogPrint (eLogError, "Addressbook: subscriptions already loaded");
|
||||
}
|
||||
|
||||
void AddressBook::LoadLocal ()
|
||||
{
|
||||
std::map<std::string, i2p::data::IdentHash> localAddresses;
|
||||
m_Storage->LoadLocal (localAddresses);
|
||||
for (auto it: localAddresses)
|
||||
{
|
||||
auto dot = it.first.find ('.');
|
||||
if (dot != std::string::npos)
|
||||
{
|
||||
auto domain = it.first.substr (dot + 1);
|
||||
auto it1 = m_Addresses.find (domain); // find domain in our addressbook
|
||||
if (it1 != m_Addresses.end ())
|
||||
{
|
||||
auto dest = context.FindLocalDestination (it1->second);
|
||||
if (dest)
|
||||
{
|
||||
// address is ours
|
||||
std::shared_ptr<AddressResolver> resolver;
|
||||
auto it2 = m_Resolvers.find (it1->second);
|
||||
if (it2 != m_Resolvers.end ())
|
||||
resolver = it2->second; // resolver exists
|
||||
else
|
||||
{
|
||||
// create new resolver
|
||||
resolver = std::make_shared<AddressResolver>(dest);
|
||||
m_Resolvers.insert (std::make_pair(it1->second, resolver));
|
||||
}
|
||||
resolver->AddAddress (it.first, it.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AddressBook::GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified)
|
||||
{
|
||||
if (m_Storage)
|
||||
@ -653,6 +686,50 @@ namespace client
|
||||
m_Book.LoadHostsFromStream (s);
|
||||
return true;
|
||||
}
|
||||
|
||||
AddressResolver::AddressResolver (std::shared_ptr<ClientDestination> destination):
|
||||
m_LocalDestination (destination)
|
||||
{
|
||||
if (m_LocalDestination)
|
||||
{
|
||||
auto datagram = m_LocalDestination->GetDatagramDestination ();
|
||||
if (!datagram)
|
||||
datagram = m_LocalDestination->CreateDatagramDestination ();
|
||||
datagram->SetReceiver (std::bind (&AddressResolver::HandleRequest, this,
|
||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5),
|
||||
ADDRESS_RESOLVER_DATAGRAM_PORT);
|
||||
}
|
||||
}
|
||||
|
||||
void AddressResolver::HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < 9 || len < buf[8] + 9U)
|
||||
{
|
||||
LogPrint (eLogError, "Address request is too short ", len);
|
||||
return;
|
||||
}
|
||||
// read requested address
|
||||
uint8_t l = buf[8];
|
||||
char address[255];
|
||||
memcpy (address, buf + 9, l);
|
||||
address[l] = 0;
|
||||
// send response
|
||||
uint8_t response[40];
|
||||
memset (response, 0, 4); // reserved
|
||||
memcpy (response + 4, buf + 4, 4); // nonce
|
||||
auto it = m_LocalAddresses.find (address); // address lookup
|
||||
if (it != m_LocalAddresses.end ())
|
||||
memcpy (response + 8, it->second, 32); // ident
|
||||
else
|
||||
memset (response + 8, 0, 32); // not found
|
||||
m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 40, from.GetIdentHash (), toPort, fromPort);
|
||||
}
|
||||
|
||||
void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident)
|
||||
{
|
||||
m_LocalAddresses[name] = ident;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "Base.h"
|
||||
#include "Identity.h"
|
||||
#include "Log.h"
|
||||
#include "Destination.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -23,7 +24,7 @@ namespace client
|
||||
const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)
|
||||
const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes
|
||||
const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second
|
||||
|
||||
|
||||
inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); }
|
||||
|
||||
class AddressBookStorage // interface for storage
|
||||
@ -45,6 +46,7 @@ namespace client
|
||||
};
|
||||
|
||||
class AddressBookSubscription;
|
||||
class AddressResolver;
|
||||
class AddressBook
|
||||
{
|
||||
public:
|
||||
@ -74,13 +76,15 @@ namespace client
|
||||
|
||||
void LoadHosts ();
|
||||
void LoadSubscriptions ();
|
||||
void LoadLocal ();
|
||||
|
||||
void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode);
|
||||
|
||||
private:
|
||||
|
||||
std::mutex m_AddressBookMutex;
|
||||
std::map<std::string, i2p::data::IdentHash> m_Addresses, m_LocalAddresses;
|
||||
std::map<std::string, i2p::data::IdentHash> m_Addresses;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver
|
||||
AddressBookStorage * m_Storage;
|
||||
volatile bool m_IsLoaded, m_IsDownloading;
|
||||
std::vector<AddressBookSubscription *> m_Subscriptions;
|
||||
@ -106,6 +110,24 @@ namespace client
|
||||
std::string m_Link, m_Etag, m_LastModified;
|
||||
// m_Etag must be surrounded by ""
|
||||
};
|
||||
|
||||
const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
|
||||
class AddressResolver
|
||||
{
|
||||
public:
|
||||
|
||||
AddressResolver (std::shared_ptr<ClientDestination> destination);
|
||||
void AddAddress (const std::string& name, const i2p::data::IdentHash& ident);
|
||||
|
||||
private:
|
||||
|
||||
void HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<ClientDestination> m_LocalDestination;
|
||||
std::map<std::string, i2p::data::IdentHash> m_LocalAddresses;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,6 +117,7 @@ namespace config {
|
||||
("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")
|
||||
("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")
|
||||
("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'")
|
||||
|
@ -72,7 +72,7 @@ namespace i2p
|
||||
if (config == "")
|
||||
{
|
||||
config = i2p::fs::DataDirPath("i2p.conf");
|
||||
// use i2p.cong only if exists
|
||||
// use i2p.conf only if exists
|
||||
if (!i2p::fs::Exists (config)) config = ""; /* reset */
|
||||
}
|
||||
|
||||
@ -104,9 +104,11 @@ namespace i2p
|
||||
i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
|
||||
}
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
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.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
|
||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||
|
@ -427,18 +427,18 @@ namespace util
|
||||
s << " (" << i2p::transport::transports.GetOutBandwidth () <<" Bps)<br>\r\n";
|
||||
s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n<br>\r\n";
|
||||
s << "<b>Our external address:</b>" << "<br>\r\n" ;
|
||||
for (auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
||||
for (auto address : i2p::context.GetRouterInfo().GetAddresses())
|
||||
{
|
||||
switch (address.transportStyle)
|
||||
switch (address->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
if (address.host.is_v6 ())
|
||||
if (address->host.is_v6 ())
|
||||
s << "NTCP6 ";
|
||||
else
|
||||
s << "NTCP ";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
if (address.host.is_v6 ())
|
||||
if (address->host.is_v6 ())
|
||||
s << "SSU6 ";
|
||||
else
|
||||
s << "SSU ";
|
||||
@ -446,7 +446,7 @@ namespace util
|
||||
default:
|
||||
s << "Unknown ";
|
||||
}
|
||||
s << address.host.to_string() << ":" << address.port << "<br>\r\n";
|
||||
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
|
||||
}
|
||||
s << "<br>\r\n<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
||||
s << "<b>Floodfills:</b> " << i2p::data::netdb.GetNumFloodfills () << " ";
|
||||
@ -534,7 +534,7 @@ namespace util
|
||||
auto dest = i2p::client::context.FindLocalDestination (ident);
|
||||
if (dest)
|
||||
{
|
||||
s << "<b>Base64:</b><br>\r\n<textarea readonly=\"readonly\" cols=\"64\" rows=\"1\" wrap=\"off\">";
|
||||
s << "<b>Base64:</b><br>\r\n<textarea readonly=\"readonly\" cols=\"64\" rows=\"11\" wrap=\"on\">";
|
||||
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
|
||||
s << "<b>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets () << "</i><br>\r\n";
|
||||
auto pool = dest->GetTunnelPool ();
|
||||
|
@ -759,15 +759,15 @@ namespace transport
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&NTCPServer::Run, this));
|
||||
// create acceptors
|
||||
auto addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (auto& address : addresses)
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (auto address: addresses)
|
||||
{
|
||||
if (address.transportStyle == i2p::data::RouterInfo::eTransportNTCP && address.host.is_v4 ())
|
||||
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));
|
||||
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
||||
|
||||
LogPrint (eLogInfo, "NTCP: Start listening TCP port ", 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));
|
||||
@ -777,10 +777,10 @@ namespace transport
|
||||
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->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);
|
||||
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));
|
||||
|
43
NetDb.cpp
43
NetDb.cpp
@ -118,6 +118,7 @@ namespace data
|
||||
{
|
||||
SaveUpdated ();
|
||||
ManageLeaseSets ();
|
||||
ManageLookupResponses ();
|
||||
}
|
||||
lastSave = ts;
|
||||
}
|
||||
@ -671,13 +672,31 @@ namespace data
|
||||
if (!replyMsg)
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: Requested ", key, " not found. ", numExcluded, " excluded");
|
||||
std::set<IdentHash> excludedRouters;
|
||||
for (int i = 0; i < numExcluded; i++)
|
||||
{
|
||||
excludedRouters.insert (excluded);
|
||||
excluded += 32;
|
||||
// find or cleate response
|
||||
std::vector<IdentHash> closestFloodfills;
|
||||
bool found = false;
|
||||
if (!numExcluded)
|
||||
{
|
||||
auto it = m_LookupResponses.find (ident);
|
||||
if (it != m_LookupResponses.end ())
|
||||
{
|
||||
closestFloodfills = it->second.first;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
std::set<IdentHash> excludedRouters;
|
||||
for (int i = 0; i < numExcluded; i++)
|
||||
{
|
||||
excludedRouters.insert (excluded);
|
||||
excluded += 32;
|
||||
}
|
||||
closestFloodfills = GetClosestFloodfills (ident, 3, excludedRouters, true);
|
||||
if (!numExcluded) // save if no excluded
|
||||
m_LookupResponses[ident] = std::make_pair(closestFloodfills, i2p::util::GetSecondsSinceEpoch ());
|
||||
}
|
||||
replyMsg = CreateDatabaseSearchReply (ident, GetClosestFloodfills (ident, 3, excludedRouters, true));
|
||||
replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills);
|
||||
}
|
||||
}
|
||||
|
||||
@ -972,5 +991,17 @@ namespace data
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void NetDb::ManageLookupResponses ()
|
||||
{
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
for (auto it = m_LookupResponses.begin (); it != m_LookupResponses.end ();)
|
||||
{
|
||||
if (ts > it->second.second + 180) // 3 minutes
|
||||
it = m_LookupResponses.erase (it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
NetDb.h
3
NetDb.h
@ -84,6 +84,7 @@ namespace data
|
||||
void Publish ();
|
||||
void ManageLeaseSets ();
|
||||
void ManageRequests ();
|
||||
void ManageLookupResponses ();
|
||||
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
||||
@ -108,6 +109,8 @@ namespace data
|
||||
|
||||
friend class NetDbRequests;
|
||||
NetDbRequests m_Requests;
|
||||
|
||||
std::map<IdentHash, std::pair<std::vector<IdentHash>, uint64_t> > m_LookupResponses; // ident->(closest FFs, timestamp)
|
||||
};
|
||||
|
||||
extern NetDb netdb;
|
||||
|
@ -92,11 +92,11 @@ namespace i2p
|
||||
void RouterContext::UpdatePort (int port)
|
||||
{
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
for (auto address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (address.port != port)
|
||||
if (address->port != port)
|
||||
{
|
||||
address.port = port;
|
||||
address->port = port;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
@ -107,11 +107,11 @@ namespace i2p
|
||||
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
|
||||
{
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
for (auto address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (address.host != host && address.IsCompatible (host))
|
||||
if (address->host != host && address->IsCompatible (host))
|
||||
{
|
||||
address.host = host;
|
||||
address->host = host;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
@ -206,15 +206,15 @@ namespace i2p
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (size_t i = 0; i < addresses.size (); i++)
|
||||
{
|
||||
if (addresses[i].transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
if (addresses[i]->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
{
|
||||
addresses.erase (addresses.begin () + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// delete previous introducers
|
||||
for (auto& addr : addresses)
|
||||
addr.introducers.clear ();
|
||||
for (auto addr : addresses)
|
||||
addr->introducers.clear ();
|
||||
|
||||
// update
|
||||
UpdateRouterInfo ();
|
||||
@ -235,16 +235,16 @@ namespace i2p
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (size_t i = 0; i < addresses.size (); i++)
|
||||
{
|
||||
if (addresses[i].transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
if (addresses[i]->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
{
|
||||
// insert NTCP address with host/port from SSU
|
||||
m_RouterInfo.AddNTCPAddress (addresses[i].host.to_string ().c_str (), addresses[i].port);
|
||||
m_RouterInfo.AddNTCPAddress (addresses[i]->host.to_string ().c_str (), addresses[i]->port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// delete previous introducers
|
||||
for (auto& addr : addresses)
|
||||
addr.introducers.clear ();
|
||||
for (auto addr : addresses)
|
||||
addr->introducers.clear ();
|
||||
|
||||
// update
|
||||
UpdateRouterInfo ();
|
||||
@ -257,26 +257,36 @@ namespace i2p
|
||||
else
|
||||
m_RouterInfo.DisableV6 ();
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::SetSupportsV4 (bool supportsV4)
|
||||
{
|
||||
if (supportsV4)
|
||||
m_RouterInfo.EnableV4 ();
|
||||
else
|
||||
m_RouterInfo.DisableV4 ();
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
|
||||
void RouterContext::UpdateNTCPV6Address (const boost::asio::ip::address& host)
|
||||
{
|
||||
bool updated = false, found = false;
|
||||
int port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr : addresses)
|
||||
for (auto addr: addresses)
|
||||
{
|
||||
if (addr.host.is_v6 () && addr.transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
if (addr->host.is_v6 () && addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
{
|
||||
if (addr.host != host)
|
||||
if (addr->host != host)
|
||||
{
|
||||
addr.host = host;
|
||||
addr->host = host;
|
||||
updated = true;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
port = addr.port;
|
||||
port = addr->port;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
|
@ -64,7 +64,10 @@ namespace i2p
|
||||
bool AcceptsTunnels () const { return m_AcceptsTunnels; };
|
||||
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
|
||||
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
|
||||
bool SupportsV4 () const { return m_RouterInfo.IsV4 (); };
|
||||
void SetSupportsV6 (bool supportsV6);
|
||||
void SetSupportsV4 (bool supportsV4);
|
||||
|
||||
void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session
|
||||
void UpdateStats ();
|
||||
|
||||
|
130
RouterInfo.cpp
130
RouterInfo.cpp
@ -232,7 +232,7 @@ namespace data
|
||||
}
|
||||
if (isValidAddress)
|
||||
{
|
||||
m_Addresses.push_back(address);
|
||||
m_Addresses.push_back(std::make_shared<Address>(address));
|
||||
m_SupportedTransports |= supportedTransports;
|
||||
}
|
||||
}
|
||||
@ -359,8 +359,9 @@ namespace data
|
||||
// addresses
|
||||
uint8_t numAddresses = m_Addresses.size ();
|
||||
s.write ((char *)&numAddresses, sizeof (numAddresses));
|
||||
for (auto& address : m_Addresses)
|
||||
for (auto addr : m_Addresses)
|
||||
{
|
||||
Address& address = *addr;
|
||||
s.write ((char *)&address.cost, sizeof (address.cost));
|
||||
s.write ((char *)&address.date, sizeof (address.date));
|
||||
std::stringstream properties;
|
||||
@ -543,46 +544,46 @@ namespace data
|
||||
|
||||
void RouterInfo::AddNTCPAddress (const char * host, int port)
|
||||
{
|
||||
Address addr;
|
||||
addr.host = boost::asio::ip::address::from_string (host);
|
||||
addr.port = port;
|
||||
addr.transportStyle = eTransportNTCP;
|
||||
addr.cost = 2;
|
||||
addr.date = 0;
|
||||
addr.mtu = 0;
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->host = boost::asio::ip::address::from_string (host);
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->cost = 2;
|
||||
addr->date = 0;
|
||||
addr->mtu = 0;
|
||||
for (auto it: m_Addresses) // don't insert same address twice
|
||||
if (it == addr) return;
|
||||
if (*it == *addr) return;
|
||||
m_Addresses.push_back(addr);
|
||||
m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eNTCPV4;
|
||||
m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4;
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
|
||||
{
|
||||
Address addr;
|
||||
addr.host = boost::asio::ip::address::from_string (host);
|
||||
addr.port = port;
|
||||
addr.transportStyle = eTransportSSU;
|
||||
addr.cost = 10; // NTCP should have priority over SSU
|
||||
addr.date = 0;
|
||||
addr.mtu = mtu;
|
||||
memcpy (addr.key, key, 32);
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->host = boost::asio::ip::address::from_string (host);
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportSSU;
|
||||
addr->cost = 10; // NTCP should have priority over SSU
|
||||
addr->date = 0;
|
||||
addr->mtu = mtu;
|
||||
memcpy (addr->key, key, 32);
|
||||
for (auto it: m_Addresses) // don't insert same address twice
|
||||
if (it == addr) return;
|
||||
if (*it == *addr) return;
|
||||
m_Addresses.push_back(addr);
|
||||
m_SupportedTransports |= addr.host.is_v6 () ? eSSUV6 : eSSUV4;
|
||||
m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
|
||||
m_Caps |= eSSUTesting;
|
||||
m_Caps |= eSSUIntroducer;
|
||||
}
|
||||
|
||||
bool RouterInfo::AddIntroducer (const Introducer& introducer)
|
||||
{
|
||||
for (auto& addr : m_Addresses)
|
||||
for (auto addr : m_Addresses)
|
||||
{
|
||||
if (addr.transportStyle == eTransportSSU && addr.host.is_v4 ())
|
||||
if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ())
|
||||
{
|
||||
for (auto intro: addr.introducers)
|
||||
for (auto intro: addr->introducers)
|
||||
if (intro.iTag == introducer.iTag) return false; // already presented
|
||||
addr.introducers.push_back (introducer);
|
||||
addr->introducers.push_back (introducer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -591,14 +592,14 @@ namespace data
|
||||
|
||||
bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e)
|
||||
{
|
||||
for (auto& addr : m_Addresses)
|
||||
for (auto addr: m_Addresses)
|
||||
{
|
||||
if (addr.transportStyle == eTransportSSU && addr.host.is_v4 ())
|
||||
if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ())
|
||||
{
|
||||
for (std::vector<Introducer>::iterator it = addr.introducers.begin (); it != addr.introducers.end (); it++)
|
||||
for (std::vector<Introducer>::iterator it = addr->introducers.begin (); it != addr->introducers.end (); it++)
|
||||
if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e)
|
||||
{
|
||||
addr.introducers.erase (it);
|
||||
addr->introducers.erase (it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -650,12 +651,24 @@ namespace data
|
||||
return m_SupportedTransports & (eNTCPV6 | eSSUV6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsV4 () const
|
||||
{
|
||||
return m_SupportedTransports & (eNTCPV4 | eSSUV4);
|
||||
}
|
||||
|
||||
void RouterInfo::EnableV6 ()
|
||||
{
|
||||
if (!IsV6 ())
|
||||
m_SupportedTransports |= eNTCPV6 | eSSUV6;
|
||||
}
|
||||
|
||||
|
||||
void RouterInfo::EnableV4 ()
|
||||
{
|
||||
if (!IsV4 ())
|
||||
m_SupportedTransports |= eNTCPV4 | eSSUV4;
|
||||
}
|
||||
|
||||
|
||||
void RouterInfo::DisableV6 ()
|
||||
{
|
||||
if (IsV6 ())
|
||||
@ -664,8 +677,8 @@ namespace data
|
||||
m_SupportedTransports &= ~eNTCPV6;
|
||||
for (size_t i = 0; i < m_Addresses.size (); i++)
|
||||
{
|
||||
if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
|
||||
m_Addresses[i].host.is_v6 ())
|
||||
if (m_Addresses[i]->transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
|
||||
m_Addresses[i]->host.is_v6 ())
|
||||
{
|
||||
m_Addresses.erase (m_Addresses.begin () + i);
|
||||
break;
|
||||
@ -676,8 +689,8 @@ namespace data
|
||||
m_SupportedTransports &= ~eSSUV6;
|
||||
for (size_t i = 0; i < m_Addresses.size (); i++)
|
||||
{
|
||||
if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
m_Addresses[i].host.is_v6 ())
|
||||
if (m_Addresses[i]->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
m_Addresses[i]->host.is_v6 ())
|
||||
{
|
||||
m_Addresses.erase (m_Addresses.begin () + i);
|
||||
break;
|
||||
@ -685,35 +698,66 @@ namespace data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RouterInfo::DisableV4 ()
|
||||
{
|
||||
if (IsV4 ())
|
||||
{
|
||||
// NTCP
|
||||
m_SupportedTransports &= ~eNTCPV4;
|
||||
for (size_t i = 0; i < m_Addresses.size (); i++)
|
||||
{
|
||||
if (m_Addresses[i]->transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
|
||||
m_Addresses[i]->host.is_v4 ())
|
||||
{
|
||||
m_Addresses.erase (m_Addresses.begin () + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SSU
|
||||
m_SupportedTransports &= ~eSSUV4;
|
||||
for (size_t i = 0; i < m_Addresses.size (); i++)
|
||||
{
|
||||
if (m_Addresses[i]->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
m_Addresses[i]->host.is_v4 ())
|
||||
{
|
||||
m_Addresses.erase (m_Addresses.begin () + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool RouterInfo::UsesIntroducer () const
|
||||
{
|
||||
return m_Caps & Caps::eUnreachable; // non-reachable
|
||||
}
|
||||
|
||||
const RouterInfo::Address * RouterInfo::GetNTCPAddress (bool v4only) const
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCPAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (eTransportNTCP, v4only);
|
||||
}
|
||||
|
||||
const RouterInfo::Address * RouterInfo::GetSSUAddress (bool v4only) const
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (eTransportSSU, v4only);
|
||||
}
|
||||
|
||||
const RouterInfo::Address * RouterInfo::GetSSUV6Address () const
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUV6Address () const
|
||||
{
|
||||
return GetAddress (eTransportSSU, false, true);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
for (auto& address : m_Addresses)
|
||||
for (auto address : m_Addresses)
|
||||
{
|
||||
if (address.transportStyle == s)
|
||||
if (address->transportStyle == s)
|
||||
{
|
||||
if ((!v4only || address.host.is_v4 ()) && (!v6only || address.host.is_v6 ()))
|
||||
return &address;
|
||||
if ((!v4only || address->host.is_v4 ()) && (!v6only || address->host.is_v6 ()))
|
||||
return address;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
15
RouterInfo.h
15
RouterInfo.h
@ -116,10 +116,10 @@ namespace data
|
||||
void SetRouterIdentity (std::shared_ptr<const IdentityEx> identity);
|
||||
std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
|
||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||
std::vector<Address>& GetAddresses () { return m_Addresses; };
|
||||
const Address * GetNTCPAddress (bool v4only = true) const;
|
||||
const Address * GetSSUAddress (bool v4only = true) const;
|
||||
const Address * GetSSUV6Address () const;
|
||||
std::vector<std::shared_ptr<Address> >& GetAddresses () { return m_Addresses; };
|
||||
std::shared_ptr<const Address> GetNTCPAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUV6Address () const;
|
||||
|
||||
void AddNTCPAddress (const char * host, int port);
|
||||
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
||||
@ -133,8 +133,11 @@ namespace data
|
||||
bool IsNTCP (bool v4only = true) const;
|
||||
bool IsSSU (bool v4only = true) const;
|
||||
bool IsV6 () const;
|
||||
bool IsV4 () const;
|
||||
void EnableV6 ();
|
||||
void DisableV6 ();
|
||||
void EnableV4 ();
|
||||
void DisableV4 ();
|
||||
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
||||
bool UsesIntroducer () const;
|
||||
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
|
||||
@ -182,7 +185,7 @@ namespace data
|
||||
size_t ReadString (char * str, std::istream& s);
|
||||
void WriteString (const std::string& str, std::ostream& s);
|
||||
void ExtractCaps (const char * value);
|
||||
const Address * GetAddress (TransportStyle s, bool v4only, bool v6only = false) const;
|
||||
std::shared_ptr<const Address> GetAddress (TransportStyle s, bool v4only, bool v6only = false) const;
|
||||
void UpdateCapsProperty ();
|
||||
|
||||
private:
|
||||
@ -192,7 +195,7 @@ namespace data
|
||||
uint8_t * m_Buffer;
|
||||
size_t m_BufferLen;
|
||||
uint64_t m_Timestamp;
|
||||
std::vector<Address> m_Addresses;
|
||||
std::vector<std::shared_ptr<Address> > m_Addresses;
|
||||
std::map<std::string, std::string> m_Properties;
|
||||
bool m_IsUpdated, m_IsUnreachable;
|
||||
uint8_t m_SupportedTransports, m_Caps;
|
||||
|
@ -112,8 +112,8 @@ namespace transport
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
||||
// create acceptors
|
||||
auto addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (auto& address : addresses)
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
for (auto address : addresses)
|
||||
{
|
||||
if (!m_NTCPServer)
|
||||
{
|
||||
@ -121,12 +121,12 @@ namespace transport
|
||||
m_NTCPServer->Start ();
|
||||
}
|
||||
|
||||
if (address.transportStyle == RouterInfo::eTransportSSU && address.host.is_v4 ())
|
||||
if (address->transportStyle == RouterInfo::eTransportSSU && address->host.is_v4 ())
|
||||
{
|
||||
if (!m_SSUServer)
|
||||
{
|
||||
m_SSUServer = new SSUServer (address.port);
|
||||
LogPrint (eLogInfo, "Transports: Start listening UDP port ", address.port);
|
||||
m_SSUServer = new SSUServer (address->port);
|
||||
LogPrint (eLogInfo, "Transports: Start listening UDP port ", address->port);
|
||||
m_SSUServer->Start ();
|
||||
DetectExternalIP ();
|
||||
}
|
||||
@ -376,14 +376,24 @@ namespace transport
|
||||
auto& peer = it1->second;
|
||||
if (!ecode && peer.router)
|
||||
{
|
||||
auto address = (*it).endpoint ().address ();
|
||||
LogPrint (eLogDebug, "Transports: ", (*it).host_name (), " has been resolved to ", address);
|
||||
auto addr = peer.router->GetNTCPAddress ();
|
||||
if (addr)
|
||||
{
|
||||
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
|
||||
m_NTCPServer->Connect (address, addr->port, s);
|
||||
return;
|
||||
while (it != boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
auto address = (*it).endpoint ().address ();
|
||||
LogPrint (eLogDebug, "Transports: ", (*it).host_name (), " has been resolved to ", address);
|
||||
if (address.is_v4 () || context.SupportsV6 ())
|
||||
{
|
||||
auto addr = peer.router->GetNTCPAddress (); // TODO: take one we requested
|
||||
if (addr)
|
||||
{
|
||||
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
|
||||
m_NTCPServer->Connect (address, addr->port, s);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "Transports: NTCP ", address, " is not supported");
|
||||
it++;
|
||||
}
|
||||
}
|
||||
LogPrint (eLogError, "Transports: Unable to resolve NTCP address: ", ecode.message ());
|
||||
@ -409,13 +419,23 @@ namespace transport
|
||||
auto& peer = it1->second;
|
||||
if (!ecode && peer.router)
|
||||
{
|
||||
auto address = (*it).endpoint ().address ();
|
||||
LogPrint (eLogDebug, "Transports: ", (*it).host_name (), " has been resolved to ", address);
|
||||
auto addr = peer.router->GetSSUAddress (!context.SupportsV6 ());;
|
||||
if (addr)
|
||||
{
|
||||
m_SSUServer->CreateSession (peer.router, address, addr->port);
|
||||
return;
|
||||
while (it != boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
auto address = (*it).endpoint ().address ();
|
||||
LogPrint (eLogDebug, "Transports: ", (*it).host_name (), " has been resolved to ", address);
|
||||
if (address.is_v4 () || context.SupportsV6 ())
|
||||
{
|
||||
auto addr = peer.router->GetSSUAddress (); // TODO: take one we requested
|
||||
if (addr)
|
||||
{
|
||||
m_SSUServer->CreateSession (peer.router, address, addr->port);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "Transports: SSU ", address, " is not supported");
|
||||
it++;
|
||||
}
|
||||
}
|
||||
LogPrint (eLogError, "Transports: Unable to resolve SSU address: ", ecode.message ());
|
||||
|
14
UPnP.cpp
14
UPnP.cpp
@ -101,19 +101,19 @@ namespace transport
|
||||
|
||||
void UPnP::Run ()
|
||||
{
|
||||
std::vector<data::RouterInfo::Address> a = context.GetRouterInfo().GetAddresses();
|
||||
for (auto& address : a)
|
||||
const std::vector<std::shared_ptr<i2p::data::RouterInfo::Address> > a = context.GetRouterInfo().GetAddresses();
|
||||
for (auto address : a)
|
||||
{
|
||||
if (!address.host.is_v6 ())
|
||||
if (!address->host.is_v6 ())
|
||||
{
|
||||
Discover ();
|
||||
if (address.transportStyle == data::RouterInfo::eTransportSSU )
|
||||
if (address->transportStyle == data::RouterInfo::eTransportSSU )
|
||||
{
|
||||
TryPortMapping (I2P_UPNP_UDP, address.port);
|
||||
TryPortMapping (I2P_UPNP_UDP, address->port);
|
||||
}
|
||||
else if (address.transportStyle == data::RouterInfo::eTransportNTCP )
|
||||
else if (address->transportStyle == data::RouterInfo::eTransportNTCP )
|
||||
{
|
||||
TryPortMapping (I2P_UPNP_TCP, address.port);
|
||||
TryPortMapping (I2P_UPNP_TCP, address->port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
UPnP.h
5
UPnP.h
@ -58,6 +58,5 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // USE_UPNP
|
||||
#endif // __UPNP_H__
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include "../Config.h"
|
||||
#include "../version.h"
|
||||
#include "resource.h"
|
||||
#include "Win32App.h"
|
||||
#include <stdio.h>
|
||||
@ -90,7 +91,9 @@ namespace win32
|
||||
{
|
||||
case ID_ABOUT:
|
||||
{
|
||||
MessageBox( hWnd, TEXT("i2pd"), TEXT("About"), MB_ICONINFORMATION | MB_OK );
|
||||
std::stringstream text;
|
||||
text << "Version: " << I2PD_VERSION << " " << CODENAME;
|
||||
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
||||
return 0;
|
||||
}
|
||||
case ID_EXIT:
|
||||
@ -171,12 +174,12 @@ namespace win32
|
||||
auto mascot = LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE (MASCOT));
|
||||
auto mascotDC = CreateCompatibleDC (hDC);
|
||||
SelectObject (mascotDC, mascot);
|
||||
BitBlt (hDC, 0,0, 533, 700, mascotDC, 0, 0, SRCCOPY);
|
||||
BitBlt (hDC, 0,0, 533, 700, mascotDC, 0, 0, SRCCOPY);
|
||||
DeleteDC (mascotDC);
|
||||
DeleteObject (mascot);
|
||||
EndPaint (hWnd, &ps);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DefWindowProc( hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
@ -205,7 +208,7 @@ namespace win32
|
||||
wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
|
||||
RegisterClassEx (&wclx);
|
||||
// create new window
|
||||
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 533, 700, NULL, NULL, hInst, NULL))
|
||||
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 549, 738, NULL, NULL, hInst, NULL))
|
||||
{
|
||||
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
|
||||
return false;
|
||||
|
@ -4,7 +4,7 @@ Build requirements
|
||||
Linux/FreeBSD/OSX
|
||||
-----------------
|
||||
|
||||
GCC 4.6 or newer, Boost 1.46 or newer, openssl, zlib. Clang can be used instead of GCC.
|
||||
GCC 4.8 or newer, Boost 1.49 or newer, openssl, zlib. Clang can be used instead of GCC.
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
@ -8,11 +8,11 @@ New family
|
||||
-----------
|
||||
You must create family self-signed certificate and key.
|
||||
The only key type supposted is prime256v1.
|
||||
Use the following list of commands:
|
||||
openssl ecparam -name prime256v1 -genkey -out <your family name>.key
|
||||
openssl req -new -key <your family name>.key -out <your family name>.csr
|
||||
touch v3.ext
|
||||
openssl x509 -req -days 3650 -in <your family name>.csr -signkey <your family name>.key -out <your family name>.crt -extfile v3.ext
|
||||
Use the following list of commands:
|
||||
openssl ecparam -name prime256v1 -genkey -out <your family name>.key
|
||||
openssl req -new -key <your family name>.key -out <your family name>.csr
|
||||
touch v3.ext
|
||||
openssl x509 -req -days 3650 -in <your family name>.csr -signkey <your family name>.key -out <your family name>.crt -extfile v3.ext
|
||||
|
||||
specify <your family name>.family.i2p.net for CN.
|
||||
|
||||
|
8
util.cpp
8
util.cpp
@ -106,11 +106,15 @@ namespace http
|
||||
while (!response.eof ())
|
||||
{
|
||||
std::string hexLen;
|
||||
int len;
|
||||
size_t len;
|
||||
std::getline (response, hexLen);
|
||||
std::istringstream iss (hexLen);
|
||||
iss >> std::hex >> len;
|
||||
if (!len) break;
|
||||
if (!len || len > 10000000L) // 10M
|
||||
{
|
||||
LogPrint (eLogError, "Unexpected chunk length ", len);
|
||||
break;
|
||||
}
|
||||
char * buf = new char[len];
|
||||
response.read (buf, len);
|
||||
merged.write (buf, len);
|
||||
|
Loading…
x
Reference in New Issue
Block a user