Browse Source

[reseed] support domains in yggdrasil reseeder, fix IPv6 URL host parsing

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1905/head
R4SAS 1 year ago
parent
commit
7b35c793f3
Signed by: r4sas
GPG Key ID: 66F6C87B98EBCFE2
  1. 34
      libi2pd/HTTP.cpp
  2. 3
      libi2pd/HTTP.h
  3. 41
      libi2pd/Reseed.cpp

34
libi2pd/HTTP.cpp

@ -93,15 +93,18 @@ namespace http
std::size_t pos_c = 0; /* < work position */ std::size_t pos_c = 0; /* < work position */
if(url.at(0) != '/' || pos_p > 0) { if(url.at(0) != '/' || pos_p > 0) {
std::size_t pos_s = 0; std::size_t pos_s = 0;
/* schema */ /* schema */
pos_c = url.find("://"); pos_c = url.find("://");
if (pos_c != std::string::npos) { if (pos_c != std::string::npos) {
schema = url.substr(0, pos_c); schema = url.substr(0, pos_c);
pos_p = pos_c + 3; pos_p = pos_c + 3;
} }
/* user[:pass] */ /* user[:pass] */
pos_s = url.find('/', pos_p); /* find first slash */ pos_s = url.find('/', pos_p); /* find first slash */
pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */ pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */
if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) { if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) {
std::size_t delim = url.find(':', pos_p); std::size_t delim = url.find(':', pos_p);
if (delim && delim != std::string::npos && delim < pos_c) { if (delim && delim != std::string::npos && delim < pos_c) {
@ -113,21 +116,28 @@ namespace http
} }
pos_p = pos_c + 1; pos_p = pos_c + 1;
} }
/* hostname[:port][/path] */ /* hostname[:port][/path] */
if (url[pos_p] == '[') // ipv6 if (url.at(pos_p) == '[') // ipv6
{ {
auto pos_b = url.find(']', pos_p); auto pos_b = url.find(']', pos_p);
if (pos_b == std::string::npos) return false; if (pos_b == std::string::npos) return false;
ipv6 = true;
pos_c = url.find_first_of(":/", pos_b); pos_c = url.find_first_of(":/", pos_b);
} }
else else
pos_c = url.find_first_of(":/", pos_p); pos_c = url.find_first_of(":/", pos_p);
if (pos_c == std::string::npos) { if (pos_c == std::string::npos) {
/* only hostname, without post and path */ /* only hostname, without post and path */
host = url.substr(pos_p, std::string::npos); host = ipv6 ?
url.substr(pos_p + 1, url.length() - 1) :
url.substr(pos_p, std::string::npos);
return true; return true;
} else if (url.at(pos_c) == ':') { } else if (url.at(pos_c) == ':') {
host = url.substr(pos_p, pos_c - pos_p); host = ipv6 ?
url.substr(pos_p + 1, pos_c - pos_p - 2) :
url.substr(pos_p, pos_c - pos_p);
/* port[/path] */ /* port[/path] */
pos_p = pos_c + 1; pos_p = pos_c + 1;
pos_c = url.find('/', pos_p); pos_c = url.find('/', pos_p);
@ -147,7 +157,9 @@ namespace http
pos_p = pos_c; pos_p = pos_c;
} else { } else {
/* start of path part found */ /* start of path part found */
host = url.substr(pos_p, pos_c - pos_p); host = ipv6 ?
url.substr(pos_p + 1, pos_c - pos_p - 2) :
url.substr(pos_p, pos_c - pos_p);
pos_p = pos_c; pos_p = pos_c;
} }
} }
@ -212,10 +224,18 @@ namespace http
} else if (user != "") { } else if (user != "") {
out += user + "@"; out += user + "@";
} }
if (port) { if (ipv6) {
out += host + ":" + std::to_string(port); if (port) {
out += "[" + host + "]:" + std::to_string(port);
} else {
out += "[" + host + "]";
}
} else { } else {
out += host; if (port) {
out += host + ":" + std::to_string(port);
} else {
out += host;
}
} }
} }
out += path; out += path;

3
libi2pd/HTTP.h

@ -36,8 +36,9 @@ namespace http
bool hasquery; bool hasquery;
std::string query; std::string query;
std::string frag; std::string frag;
bool ipv6;
URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag("") {}; URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag(""), ipv6(false) {};
/** /**
* @brief Tries to parse url from string * @brief Tries to parse url from string

41
libi2pd/Reseed.cpp

@ -703,6 +703,7 @@ namespace data
s.lowest_layer().connect (ep, ecode); s.lowest_layer().connect (ep, ecode);
if (!ecode) if (!ecode)
{ {
LogPrint (eLogDebug, "Reseed: Resolved to ", ep.address ());
connected = true; connected = true;
break; break;
} }
@ -790,17 +791,45 @@ namespace data
boost::asio::io_service service; boost::asio::io_service service;
boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6()); boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6());
if (url.host.length () < 2) return ""; // assume [] auto it = boost::asio::ip::tcp::resolver(service).resolve (
auto host = url.host.substr (1, url.host.length () - 2); boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode);
LogPrint (eLogDebug, "Reseed: Connecting to Yggdrasil ", url.host, ":", url.port);
s.connect (boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::from_string (host), url.port), ecode); if (!ecode)
{
bool connected = false;
boost::asio::ip::tcp::resolver::iterator end;
while (it != end)
{
boost::asio::ip::tcp::endpoint ep = *it;
if (
i2p::util::net::IsYggdrasilAddress (ep.address ()) &&
i2p::context.SupportsMesh ()
)
{
LogPrint (eLogDebug, "Reseed: Yggdrasil: Resolved to ", ep.address ());
s.connect (ep, ecode);
if (!ecode)
{
connected = true;
break;
}
}
it++;
}
if (!connected)
{
LogPrint(eLogError, "Reseed: Yggdrasil: Failed to connect to ", url.host);
return "";
}
}
if (!ecode) if (!ecode)
{ {
LogPrint (eLogDebug, "Reseed: Connected to Yggdrasil ", url.host, ":", url.port); LogPrint (eLogDebug, "Reseed: Yggdrasil: Connected to ", url.host, ":", url.port);
return ReseedRequest (s, url.to_string()); return ReseedRequest (s, url.to_string());
} }
else else
LogPrint (eLogError, "Reseed: Couldn't connect to Yggdrasil ", url.host, ": ", ecode.message ()); LogPrint (eLogError, "Reseed: Yggdrasil: Couldn't connect to ", url.host, ": ", ecode.message ());
return ""; return "";
} }

Loading…
Cancel
Save