| 72 | HttpDownloadCommand::~HttpDownloadCommand() = default; |
| 73 | |
| 74 | bool HttpDownloadCommand::prepareForNextSegment() |
| 75 | { |
| 76 | bool downloadFinished = getRequestGroup()->downloadFinished(); |
| 77 | if (getRequest()->isPipeliningEnabled() && !downloadFinished) { |
| 78 | auto command = make_unique<HttpRequestCommand>( |
| 79 | getCuid(), getRequest(), getFileEntry(), getRequestGroup(), |
| 80 | httpConnection_, getDownloadEngine(), getSocket()); |
| 81 | // Set proxy request here. aria2 sends the HTTP request specialized for |
| 82 | // proxy. |
| 83 | if (resolveProxyMethod(getRequest()->getProtocol()) == V_GET) { |
| 84 | command->setProxyRequest(createProxyRequest()); |
| 85 | } |
| 86 | getDownloadEngine()->addCommand(std::move(command)); |
| 87 | return true; |
| 88 | } |
| 89 | |
| 90 | const std::string& streamFilterName = getStreamFilter()->getName(); |
| 91 | if (getRequest()->isPipeliningEnabled() || |
| 92 | (getRequest()->isKeepAliveEnabled() && |
| 93 | ( |
| 94 | // Make sure that all filters are finished to pool socket |
| 95 | (!util::endsWith(streamFilterName, SinkStreamFilter::NAME) && |
| 96 | getStreamFilter()->finished()) || |
| 97 | getRequestEndOffset() == |
| 98 | getFileEntry()->gtoloff( |
| 99 | getSegments().front()->getPositionToWrite())))) { |
| 100 | // TODO What if server sends EOF when non-SinkStreamFilter is |
| 101 | // used and server didn't send Connection: close? We end up to |
| 102 | // pool terminated socket. In HTTP/1.1, keep-alive is default, |
| 103 | // so closing connection without Connection: close header means |
| 104 | // that server is broken or not configured properly. |
| 105 | getDownloadEngine()->poolSocket(getRequest(), createProxyRequest(), |
| 106 | getSocket()); |
| 107 | } |
| 108 | |
| 109 | // The request was sent assuming that server supported pipelining, but |
| 110 | // it turned out that server didn't support it. |
| 111 | // We detect this situation by comparing the end byte in range header |
| 112 | // of the response with the end byte of segment. |
| 113 | // If it is the same, HTTP negotiation is necessary for the next request. |
| 114 | if (!getRequest()->isPipeliningEnabled() && |
| 115 | getRequest()->isPipeliningHint() && !downloadFinished) { |
| 116 | const std::shared_ptr<Segment>& segment = getSegments().front(); |
| 117 | |
| 118 | int64_t lastOffset = getFileEntry()->gtoloff( |
| 119 | std::min(segment->getPosition() + segment->getLength(), |
| 120 | getFileEntry()->getLastOffset())); |
| 121 | auto range = httpResponse_->getHttpHeader()->getRange(); |
| 122 | if (lastOffset == range.endByte + 1) { |
| 123 | return prepareForRetry(0); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | return DownloadCommand::prepareForNextSegment(); |
| 128 | } |
| 129 | |
| 130 | int64_t HttpDownloadCommand::getRequestEndOffset() const |
| 131 | { |
nothing calls this directly
no test coverage detected