/* */ #include "HttpDownloadCommand.h" #include "RequestGroup.h" #include "DownloadEngine.h" #include "Request.h" #include "HttpRequestCommand.h" #include "HttpConnection.h" #include "HttpRequest.h" #include "Segment.h" #include "Socket.h" #include "prefs.h" #include "Option.h" #include "HttpResponse.h" #include "HttpHeader.h" #include "Range.h" #include "DownloadContext.h" #include "Decoder.h" namespace aria2 { HttpDownloadCommand::HttpDownloadCommand (int cuid, const RequestHandle& req, const SharedHandle& fileEntry, RequestGroup* requestGroup, const SharedHandle& httpResponse, const HttpConnectionHandle& httpConnection, DownloadEngine* e, const SocketHandle& socket) :DownloadCommand(cuid, req, fileEntry, requestGroup, e, socket), _httpResponse(httpResponse), _httpConnection(httpConnection) {} HttpDownloadCommand::~HttpDownloadCommand() {} bool HttpDownloadCommand::prepareForNextSegment() { bool downloadFinished = _requestGroup->downloadFinished(); if(req->isPipeliningEnabled() && !downloadFinished) { HttpRequestCommand* command = new HttpRequestCommand(cuid, req, _fileEntry, _requestGroup, _httpConnection, e, socket); // Set proxy request here. aria2 sends the HTTP request specialized for // proxy. if(resolveProxyMethod(req->getProtocol()) == V_GET) { command->setProxyRequest(createProxyRequest()); } e->commands.push_back(command); return true; } else { if(req->isPipeliningEnabled() || (req->isKeepAliveEnabled() && ( ((!_transferEncodingDecoder.isNull() && _transferEncodingDecoder->finished()) || (!_contentEncodingDecoder.isNull() && _contentEncodingDecoder->finished())) || _fileEntry->getLastOffset() == _segments.front()->getPositionToWrite() ) ) ) { // TODO What if server sends EOF when _contentEncodingDecoder is // used and server didn't send Connection: close? We end up to // pool terminated socket. In HTTP/1.1, keep-alive is default, // so closing connection without Connection: close header means // that server is broken or not configured properly. e->poolSocket(req, isProxyDefined(), socket); } // The request was sent assuming that server supported pipelining, but // it turned out that server didn't support it. // We detect this situation by comparing the end byte in range header // of the response with the end byte of segment. // If it is the same, HTTP negotiation is necessary for the next request. if(!req->isPipeliningEnabled() && req->isPipeliningHint() && !downloadFinished) { const SharedHandle& segment = _segments.front(); off_t lastOffset =_fileEntry->gtoloff (std::min(static_cast(segment->getPosition()+segment->getLength()), _fileEntry->getLastOffset())); if(lastOffset == _httpResponse->getHttpHeader()->getRange()->getEndByte()+1) { return prepareForRetry(0); } } return DownloadCommand::prepareForNextSegment(); } } } // namespace aria2