From ce25b54cfe3ba23408da19fcd87539bec879b943 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 30 Aug 2009 15:05:30 +0000 Subject: 2009-08-31 Tatsuhiro Tsujikawa Added support for IPv6 literal address in URI. Now aria2 can handle URI such as http://[::1]/ * src/HttpRequest.cc * src/HttpRequest.h * src/Request.cc * src/Request.h * test/HttpRequestTest.cc * test/OptionHandlerTest.cc * test/RequestTest.cc --- src/HttpRequest.cc | 6 +++--- src/HttpRequest.h | 7 +++++-- src/Request.cc | 48 ++++++++++++++++++++++++++++++++++-------------- src/Request.h | 14 ++++++++++++++ 4 files changed, 56 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 3c4e8f06..63bdc557 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -117,7 +117,7 @@ bool HttpRequest::isRangeSatisfied(const RangeHandle& range) const } } -std::string HttpRequest::getHostText(const std::string& host, uint16_t port) const +static std::string getHostText(const std::string& host, uint16_t port) { std::string hosttext = host; if(!(port == 80 || port == 443)) { @@ -172,7 +172,7 @@ std::string HttpRequest::createRequest() } } - strappend(requestLine, "Host: ", getHostText(getHost(), getPort()), "\r\n"); + strappend(requestLine, "Host: ", getHostText(getURIHost(), getPort()), "\r\n"); requestLine += "Pragma: no-cache\r\n"; requestLine += "Cache-Control: no-cache\r\n"; @@ -235,7 +235,7 @@ std::string HttpRequest::createRequest() std::string HttpRequest::createProxyRequest() const { assert(!_proxyRequest.isNull()); - std::string hostport = getHost(); + std::string hostport = getURIHost(); strappend(hostport, ":", Util::uitos(getPort())); std::string requestLine = "CONNECT "; diff --git a/src/HttpRequest.h b/src/HttpRequest.h index 18a0768b..b32b614b 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -83,8 +83,6 @@ private: SharedHandle _proxyRequest; - std::string getHostText(const std::string& host, uint16_t port) const; - std::string getProxyAuthString() const; public: HttpRequest(); @@ -149,6 +147,11 @@ public: return request->getPreviousUrl(); } + std::string getURIHost() const + { + return request->getURIHost(); + } + SharedHandle getRange() const; /** diff --git a/src/Request.cc b/src/Request.cc index ee9d7c0a..e055811f 100644 --- a/src/Request.cc +++ b/src/Request.cc @@ -71,7 +71,8 @@ Request::Request(): _keepAliveHint(false), _pipeliningHint(false), _maxPipelinedRequest(1), - method(METHOD_GET) + method(METHOD_GET), + _ipv6LiteralAddress(false) {} static std::string removeFragment(const std::string url) @@ -160,6 +161,7 @@ bool Request::parseUrl(const std::string& url) { _query = A2STR::NIL; _username = A2STR::NIL; _password = A2STR::NIL; + _ipv6LiteralAddress = false; // find query part std::string queryTemp; std::string::size_type startQueryIndex = tempUrl.find("?"); @@ -193,22 +195,40 @@ bool Request::parseUrl(const std::string& url) { _password = Util::urldecode(userPass.second); hostPart.erase(0, atmarkp+1); } - std::pair hostAndPort; - Util::split(hostAndPort, hostPart, ':'); - host = hostAndPort.first; - if(hostAndPort.second != A2STR::NIL) { - try { - unsigned int tempPort = Util::parseUInt(hostAndPort.second); - if(65535 < tempPort) { + { + std::string::size_type colonpos; + // Detect IPv6 literal address in square brackets + if(Util::startsWith(hostPart, "[")) { + std::string::size_type rbracketpos = hostPart.find("]"); + if(rbracketpos == std::string::npos) { return false; } - port = tempPort; - } catch(RecoverableException& e) { - return false; + _ipv6LiteralAddress = true; + colonpos = hostPart.find(":", rbracketpos+1); + } else { + colonpos = hostPart.find_last_of(":"); + } + if(colonpos == std::string::npos) { + colonpos = hostPart.size(); + // If port is not specified, then we set it to default port of + // its protocol.. + port = defPort; + } else { + try { + unsigned int tempPort = Util::parseUInt(hostPart.substr(colonpos+1)); + if(65535 < tempPort) { + return false; + } + port = tempPort; + } catch(RecoverableException& e) { + return false; + } + } + if(_ipv6LiteralAddress) { + host = hostPart.substr(1, colonpos-2); + } else { + host = hostPart.substr(0, colonpos); } - } else { - // If port is not specified, then we set it to default port of its protocol.. - port = defPort; } // find directory and file part std::string::size_type direp = tempUrl.find_last_of("/"); diff --git a/src/Request.h b/src/Request.h index cab16999..5c88cf62 100644 --- a/src/Request.h +++ b/src/Request.h @@ -41,6 +41,7 @@ #include "SharedHandle.h" #include "PeerStat.h" +#include "a2functional.h" namespace aria2 { @@ -82,6 +83,8 @@ private: std::string _password; + bool _ipv6LiteralAddress; + SharedHandle _peerStat; bool parseUrl(const std::string& url); @@ -116,10 +119,21 @@ public: void setReferer(const std::string& url); const std::string& getProtocol() const { return protocol; } const std::string& getHost() const { return host; } + // Same as getHost(), but for IPv6 literal addresses, enclose them + // with square brackets and return. + std::string getURIHost() const + { + if(isIPv6LiteralAddress()) { + return strconcat("[", getHost(), "]"); + } else { + return getHost(); + } + } uint16_t getPort() const { return port; } const std::string& getDir() const { return dir; } const std::string& getFile() const { return file;} const std::string& getQuery() const { return _query; } + bool isIPv6LiteralAddress() const { return _ipv6LiteralAddress; } void supportsPersistentConnection(bool f) { -- cgit