diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 7cc87df8..f4c3dcb9 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -93,15 +93,18 @@ namespace http std::size_t pos_c = 0; /* < work position */ if(url.at(0) != '/' || pos_p > 0) { std::size_t pos_s = 0; + /* schema */ pos_c = url.find("://"); if (pos_c != std::string::npos) { schema = url.substr(0, pos_c); pos_p = pos_c + 3; } + /* user[:pass] */ pos_s = url.find('/', pos_p); /* find first slash */ 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)) { std::size_t delim = url.find(':', pos_p); if (delim && delim != std::string::npos && delim < pos_c) { @@ -113,21 +116,28 @@ namespace http } pos_p = pos_c + 1; } + /* hostname[:port][/path] */ - if (url[pos_p] == '[') // ipv6 + if (url.at(pos_p) == '[') // ipv6 { auto pos_b = url.find(']', pos_p); if (pos_b == std::string::npos) return false; + ipv6 = true; pos_c = url.find_first_of(":/", pos_b); } else pos_c = url.find_first_of(":/", pos_p); + if (pos_c == std::string::npos) { /* 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; } 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] */ pos_p = pos_c + 1; pos_c = url.find('/', pos_p); @@ -147,7 +157,9 @@ namespace http pos_p = pos_c; } else { /* 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; } } @@ -212,10 +224,18 @@ namespace http } else if (user != "") { out += user + "@"; } - if (port) { - out += host + ":" + std::to_string(port); + if (ipv6) { + if (port) { + out += "[" + host + "]:" + std::to_string(port); + } else { + out += "[" + host + "]"; + } } else { - out += host; + if (port) { + out += host + ":" + std::to_string(port); + } else { + out += host; + } } } out += path; diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index f9d5d009..41f0560a 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -36,8 +36,9 @@ namespace http bool hasquery; std::string query; 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 diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index f0a4cc29..dfc10043 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -703,6 +703,7 @@ namespace data s.lowest_layer().connect (ep, ecode); if (!ecode) { + LogPrint (eLogDebug, "Reseed: Resolved to ", ep.address ()); connected = true; break; } @@ -790,17 +791,45 @@ namespace data boost::asio::io_service service; boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6()); - if (url.host.length () < 2) return ""; // assume [] - auto host = url.host.substr (1, url.host.length () - 2); - 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); + auto it = boost::asio::ip::tcp::resolver(service).resolve ( + boost::asio::ip::tcp::resolver::query (url.host, std::to_string(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) { - 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()); } 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 ""; }