+ if( r->isComplete() )
+ return;
+
+ if( r->url().find("://") == std::string::npos ) {
+ r->setFailure(EINVAL, "malformed URL");
+ return;
+ }
+
+ if( r->url().find("http://") != 0 ) {
+ r->setFailure(EINVAL, "only HTTP protocol is supported");
+ return;
+ }
+
+ std::string host = r->host();
+ int port = r->port();
+ if (!d->proxy.empty()) {
+ host = d->proxy;
+ port = d->proxyPort;
+ }
+
+ Connection* con = NULL;
+ std::stringstream ss;
+ ss << host << "-" << port;
+ std::string connectionId = ss.str();
+ bool havePending = !d->pendingRequests.empty();
+ bool atConnectionsLimit = d->connections.size() >= d->maxConnections;
+ ConnectionDict::iterator consEnd = d->connections.end();
+
+ // assign request to an existing Connection.
+ // various options exist here, examined in order
+ ConnectionDict::iterator it = d->connections.find(connectionId);
+ if (atConnectionsLimit && (it == consEnd)) {
+ // maximum number of connections active, queue this request
+ // when a connection goes inactive, we'll start this one
+ d->pendingRequests.push_back(r);
+ return;
+ }
+
+ // scan for an idle Connection to the same host (likely if we're
+ // retrieving multiple resources from the same host in quick succession)
+ // if we have pending requests (waiting for a free Connection), then
+ // force new requests on this id to always use the first Connection
+ // (instead of the random selection below). This ensures that when
+ // there's pressure on the number of connections to keep alive, one
+ // host can't DoS every other.
+ int count = 0;
+ for (; (it != consEnd) && (it->first == connectionId); ++it, ++count) {
+ if (havePending || !it->second->isActive()) {
+ con = it->second;
+ break;
+ }