diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.cpp 2026-03-26 20:26:03.000000000 +0000 @@ -373,5 +373,5 @@ { for (auto& it : headers) - if (boost::iequals(it.first, name)) + if (it.first == name) { it.second = value; @@ -384,5 +384,5 @@ for (auto it = headers.begin (); it != headers.end ();) { - if (boost::istarts_with(it->first, name) && !boost::iequals(it->first, exempt)) + if (!it->first.compare(0, name.length (), name) && it->first != exempt) it = headers.erase (it); else @@ -394,5 +394,5 @@ { for (auto& it : headers) - if (boost::iequals(it.first, name)) + if (it.first == name) return it.second; return ""; @@ -403,5 +403,5 @@ size_t num = 0; for (auto& it : headers) - if (boost::iequals(it.first, name)) num++; + if (it.first == name) num++; return num; } diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.h /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.h --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/HTTP.h 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/HTTP.h 2026-03-26 20:26:03.000000000 +0000 @@ -17,5 +17,4 @@ #include #include -#include namespace i2p @@ -26,15 +25,4 @@ constexpr std::string_view HTTP_EOH = "\r\n\r\n"; /**< HTTP end-of-headers mark */ - // case-insensitive comparator for HTTP header names (RFC 7230) - struct CaseInsensitiveLess - { - using is_transparent = void; - - bool operator() (std::string_view a, std::string_view b) const - { - return boost::ilexicographical_compare(a, b); - } - }; - struct URL { @@ -79,5 +67,5 @@ struct HTTPMsg { - std::map headers; + std::map headers; void add_header(const char *name, const std::string & value, bool replace = false); diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/Transports.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/Transports.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/Transports.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/Transports.cpp 2026-03-26 20:26:03.000000000 +0000 @@ -1406,20 +1406,24 @@ } - boost::asio::ip::address Transports::GetNetworkAddress (const boost::asio::ip::address& addr) const + boost::asio::ip::address Transports::GetNetworkAddress (std::shared_ptr session) const { - if (!addr.is_unspecified ()) + if (session) { - if (addr.is_v4 ()) - return boost::asio::ip::network_v4 (addr.to_v4 (), 24).network (); // /24 - else + auto networkAddr = session->GetRemoteAddress (); + if (!networkAddr.is_unspecified ()) { - if (i2p::util::net::IsYggdrasilAddress (addr)) + if (networkAddr.is_v4 ()) + return boost::asio::ip::network_v4 (networkAddr.to_v4 (), 24).network (); // /24 + else { - // change to 2xx range - auto bytes = addr.to_v6 ().to_bytes (); - bytes[0] = 0x02; - return boost::asio::ip::network_v6 (boost::asio::ip::address_v6 (bytes), 64).network (); // /64 + if (i2p::util::net::IsYggdrasilAddress (networkAddr)) + { + // change to 2xx range + auto bytes = networkAddr.to_v6 ().to_bytes (); + bytes[0] = 0x02; + return boost::asio::ip::network_v6 (boost::asio::ip::address_v6 (bytes), 64).network (); // /64 + } + return boost::asio::ip::network_v6 (networkAddr.to_v6 (), 56).network (); // /56 } - return boost::asio::ip::network_v6 (addr.to_v6 (), 56).network (); // /56 } } @@ -1427,30 +1431,4 @@ } - boost::asio::ip::address Transports::GetNetworkAddress (std::shared_ptr session) const - { - if (session) - return GetNetworkAddress (session->GetRemoteAddress ()); - return boost::asio::ip::address (); - } - - bool Transports::IsTooManyConnectionsFromSubnet (std::shared_ptr r) const - { - if (!r && !IsCheckReserved ()) return false; - auto addresses = r->GetAddresses (); - if (!addresses) return false; - for (auto& address : *addresses) - if (address && !address->host.is_unspecified ()) - { - auto networkAddr = GetNetworkAddress (address->host); - if (!networkAddr.is_unspecified ()) - { - std::lock_guard l( m_ConnectedNetworksMutex); - auto it = m_ConnectedNetworks.find (networkAddr); - if (it != m_ConnectedNetworks.end () && it->second > MAX_NUM_CONNECTIONS_FROM_SUBNET_FOR_PEER) return true; - } - } - return false; - } - void InitAddressFromIface () { diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/Transports.h /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/Transports.h --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/Transports.h 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/Transports.h 2026-03-26 20:26:03.000000000 +0000 @@ -200,6 +200,4 @@ bool AddBan (const boost::asio::ip::address& addr); - bool IsTooManyConnectionsFromSubnet (std::shared_ptr r) const; - private: @@ -221,5 +219,4 @@ std::shared_ptr GetRandomPeer (Filter filter) const; boost::asio::ip::address GetNetworkAddress (std::shared_ptr session) const; - boost::asio::ip::address GetNetworkAddress (const boost::asio::ip::address& addr) const; private: diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/TunnelPool.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/TunnelPool.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/TunnelPool.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/TunnelPool.cpp 2026-03-26 20:26:03.000000000 +0000 @@ -579,6 +579,5 @@ if (hop) { - if ((!hop->HasProfile () || !hop->GetProfile ()->IsBad ()) && - (prevHop != i2p::context.GetSharedRouterInfo () || !i2p::transport::transports.IsTooManyConnectionsFromSubnet (hop))) + if (!hop->HasProfile () || !hop->GetProfile ()->IsBad ()) break; } diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-req.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-req.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-req.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-req.cpp 2026-03-26 20:26:03.000000000 +0000 @@ -84,57 +84,4 @@ delete req; - /* test: case-insensitive header matching (RFC 7230) */ - buf = - "GET / HTTP/1.1\r\n" - "HOST: example.i2p\r\n" - "content-type: text/html\r\n" - "Content-Length: 100\r\n" - "X-Custom-Header: value\r\n" - "\r\n"; - len = strlen(buf); - req = new HTTPReq; - assert((ret = req->parse(buf, len)) == len); - /* GetHeader should be case-insensitive */ - assert(req->GetHeader("Host") == "example.i2p"); - assert(req->GetHeader("host") == "example.i2p"); - assert(req->GetHeader("HOST") == "example.i2p"); - assert(req->GetHeader("Content-Type") == "text/html"); - assert(req->GetHeader("content-type") == "text/html"); - assert(req->GetHeader("CONTENT-TYPE") == "text/html"); - assert(req->GetHeader("Content-Length") == "100"); - assert(req->GetHeader("content-length") == "100"); - assert(req->GetHeader("x-custom-header") == "value"); - assert(req->GetHeader("X-CUSTOM-HEADER") == "value"); - /* GetNumHeaders should be case-insensitive */ - assert(req->GetNumHeaders("Host") == 1); - assert(req->GetNumHeaders("host") == 1); - assert(req->GetNumHeaders("HOST") == 1); - assert(req->GetNumHeaders("content-type") == 1); - delete req; - - /* test: UpdateHeader case-insensitivity */ - req = new HTTPReq; - req->AddHeader("Content-Type", "text/plain"); - assert(req->GetHeader("Content-Type") == "text/plain"); - req->UpdateHeader("content-type", "application/json"); - assert(req->GetHeader("Content-Type") == "application/json"); - assert(req->GetHeader("CONTENT-TYPE") == "application/json"); - req->UpdateHeader("CONTENT-TYPE", "text/html"); - assert(req->GetHeader("content-type") == "text/html"); - delete req; - - /* test: RemoveHeader case-insensitivity */ - req = new HTTPReq; - req->AddHeader("X-Forwarded-For", "1.2.3.4"); - req->AddHeader("X-Forwarded-Host", "proxy.i2p"); - req->AddHeader("Accept", "*/*"); - assert(req->GetNumHeaders() == 3); - /* remove headers starting with "x-forwarded" (case-insensitive), exempt "X-Forwarded-Host" */ - req->RemoveHeader("X-Forwarded", "x-forwarded-host"); - assert(req->GetNumHeaders() == 2); - assert(req->GetHeader("X-Forwarded-Host") == "proxy.i2p"); - assert(req->GetHeader("X-Forwarded-For") == ""); - delete req; - return 0; } diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-res.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-res.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/tests/test-http-res.cpp 2026-03-27 11:42:26.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/tests/test-http-res.cpp 2026-03-26 20:26:03.000000000 +0000 @@ -45,72 +45,4 @@ assert(res->to_string() == buf); - /* test: case-insensitive header parsing (RFC 7230) */ - buf = - "HTTP/1.1 200 OK\r\n" - "content-type: text/html\r\n" - "CONTENT-LENGTH: 42\r\n" - "transfer-encoding: chunked\r\n" - "content-encoding: gzip\r\n" - "\r\n"; - len = strlen(buf); - res = new HTTPRes; - assert((ret = res->parse(buf, len)) == len); - assert(res->code == 200); - /* content_length() should work with any case */ - assert(res->content_length() == 42); - /* is_chunked() should work with any case */ - assert(res->is_chunked() == true); - /* is_gzipped() should work with any case */ - assert(res->is_gzipped() == true); - delete res; - - /* test: add_header case-insensitivity (no duplicates) */ - res = new HTTPRes; - res->add_header("Content-Type", "text/plain"); - res->add_header("content-type", "text/html"); /* should not add duplicate */ - assert(res->headers.size() == 1); - res->add_header("content-type", "application/json", true); /* replace=true */ - assert(res->headers.size() == 1); - delete res; - - /* test: del_header case-insensitivity */ - res = new HTTPRes; - res->add_header("X-Custom-Header", "value"); - assert(res->headers.size() == 1); - res->del_header("x-custom-header"); - assert(res->headers.size() == 0); - delete res; - - /* test: to_string() doesn't add duplicate Date/Content-Length with different case */ - res = new HTTPRes; - res->version = "HTTP/1.1"; - res->code = 200; - res->status = "OK"; - res->add_header("date", "Thu, 01 Jan 1970 00:00:00 GMT"); - res->add_header("content-length", "0"); - res->body = ""; - std::string response = res->to_string(); - /* should not have duplicate headers */ - size_t date_count = 0, pos = 0; - while ((pos = response.find("ate:", pos)) != std::string::npos) { - date_count++; - pos++; - } - assert(date_count == 1); /* only one Date header */ - delete res; - - /* test: get_header case-insensitivity (used by Reseed for Location redirect) */ - buf = - "HTTP/1.1 302 Found\r\n" - "location: https://example.com/new\r\n" - "\r\n"; - len = strlen(buf); - res = new HTTPRes; - assert((ret = res->parse(buf, len)) == len); - assert(res->get_header("Location") == "https://example.com/new"); - assert(res->get_header("location") == "https://example.com/new"); - assert(res->get_header("LOCATION") == "https://example.com/new"); - delete res; - return 0; }