mirror of https://github.com/aria2/aria2
2008-05-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Receive content body of 302 response so that the connection can be reused later when http keep-alive is enabled. * src/HttpNullDownloadCommand.cc * src/HttpNullDownloadCommand.h * src/HttpResponseCommand.cc * src/HttpResponseCommand.hpull/1/head
parent
53464fd0fc
commit
4f150057ca
|
@ -1,3 +1,12 @@
|
|||
2008-05-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Receive content body of 302 response so that the connection can be
|
||||
reused later when http keep-alive is enabled.
|
||||
* src/HttpNullDownloadCommand.cc
|
||||
* src/HttpNullDownloadCommand.h
|
||||
* src/HttpResponseCommand.cc
|
||||
* src/HttpResponseCommand.h
|
||||
|
||||
2008-05-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
const SharedHandle<Request> -> const SharedHandle<Request>&
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "HttpNullDownloadCommand.h"
|
||||
#include "HttpConnection.h"
|
||||
#include "HttpResponse.h"
|
||||
#include "message.h"
|
||||
#include "SocketCore.h"
|
||||
#include "TransferEncoding.h"
|
||||
#include "DlRetryEx.h"
|
||||
#include "Request.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "Logger.h"
|
||||
#include "HttpRequest.h"
|
||||
#include "Segment.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
HttpNullDownloadCommand::HttpNullDownloadCommand
|
||||
(int cuid,
|
||||
const SharedHandle<Request>& req,
|
||||
RequestGroup* requestGroup,
|
||||
const SharedHandle<HttpConnection>& httpConnection,
|
||||
const SharedHandle<HttpResponse>& httpResponse,
|
||||
DownloadEngine* e,
|
||||
const SharedHandle<SocketCore>& s):
|
||||
AbstractCommand(cuid, req, requestGroup, e, s),
|
||||
_httpConnection(httpConnection),
|
||||
_httpResponse(httpResponse),
|
||||
_totalLength(_httpResponse->getEntityLength()),
|
||||
_receivedBytes(0)
|
||||
{}
|
||||
|
||||
HttpNullDownloadCommand::~HttpNullDownloadCommand() {}
|
||||
|
||||
void HttpNullDownloadCommand::setTransferDecoder
|
||||
(const SharedHandle<TransferEncoding>& transferDecoder)
|
||||
{
|
||||
_transferDecoder = transferDecoder;
|
||||
}
|
||||
|
||||
bool HttpNullDownloadCommand::executeInternal()
|
||||
{
|
||||
const size_t BUFSIZE = 16*1024;
|
||||
unsigned char buf[BUFSIZE];
|
||||
size_t bufSize = BUFSIZE;
|
||||
socket->readData(buf, bufSize);
|
||||
|
||||
if(_transferDecoder.isNull()) {
|
||||
_receivedBytes += bufSize;
|
||||
} else {
|
||||
// _receivedBytes is not updated if transferEncoding is set.
|
||||
size_t infbufSize = 16*1024;
|
||||
unsigned char infbuf[infbufSize];
|
||||
_transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
|
||||
}
|
||||
if(_totalLength != 0 && bufSize == 0) {
|
||||
throw DlRetryEx(EX_GOT_EOF);
|
||||
}
|
||||
|
||||
if(bufSize == 0) {
|
||||
// Since this method is called by DownloadEngine only when the socket is
|
||||
// readable, bufSize == 0 means server shutdown the connection.
|
||||
// So socket cannot be reused in this case.
|
||||
return prepareForRetry(0);
|
||||
} else if((!_transferDecoder.isNull() && _transferDecoder->finished())
|
||||
|| (_transferDecoder.isNull() && _totalLength == _receivedBytes)) {
|
||||
if(!_transferDecoder.isNull()) _transferDecoder->end();
|
||||
|
||||
if(req->supportsPersistentConnection()) {
|
||||
std::pair<std::string, uint16_t> peerInfo;
|
||||
socket->getPeerInfo(peerInfo);
|
||||
e->poolSocket(peerInfo.first, peerInfo.second, socket);
|
||||
}
|
||||
_httpResponse->processRedirect();
|
||||
logger->info(MSG_REDIRECT, cuid, _httpResponse->getRedirectURI().c_str());
|
||||
return prepareForRetry(0);
|
||||
} else {
|
||||
e->commands.push_back(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,75 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_HTTP_NULL_DOWNLOAD_COMMAND_H_
|
||||
#define _D_HTTP_NULL_DOWNLOAD_COMMAND_H_
|
||||
|
||||
#include "AbstractCommand.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class HttpConnection;
|
||||
class HttpResponse;
|
||||
class TransferEncoding;
|
||||
|
||||
class HttpNullDownloadCommand : public AbstractCommand {
|
||||
private:
|
||||
SharedHandle<HttpConnection> _httpConnection;
|
||||
|
||||
SharedHandle<HttpResponse> _httpResponse;
|
||||
|
||||
SharedHandle<TransferEncoding> _transferDecoder;
|
||||
|
||||
uint64_t _totalLength;
|
||||
|
||||
uint64_t _receivedBytes;
|
||||
protected:
|
||||
virtual bool executeInternal();
|
||||
public:
|
||||
HttpNullDownloadCommand(int cuid,
|
||||
const SharedHandle<Request>& req,
|
||||
RequestGroup* requestGroup,
|
||||
const SharedHandle<HttpConnection>& httpConnection,
|
||||
const SharedHandle<HttpResponse>& httpResponse,
|
||||
DownloadEngine* e,
|
||||
const SharedHandle<SocketCore>& s);
|
||||
|
||||
virtual ~HttpNullDownloadCommand();
|
||||
|
||||
void setTransferDecoder(const SharedHandle<TransferEncoding>& transferDecoder);
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // _D_HTTP_NULL_DOWNLOAD_COMMAND_H_
|
|
@ -60,6 +60,7 @@
|
|||
#include "message.h"
|
||||
#include "prefs.h"
|
||||
#include "StringFormat.h"
|
||||
#include "HttpNullDownloadCommand.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -88,12 +89,25 @@ bool HttpResponseCommand::executeInternal()
|
|||
httpResponse->retrieveCookie();
|
||||
// check whether Location header exists. If it does, update request object
|
||||
// with redirected URL.
|
||||
// then establish a connection to the new host and port
|
||||
if(httpResponse->isRedirect()) {
|
||||
// To reuse a connection, a response body must be received.
|
||||
if(req->supportsPersistentConnection() &&
|
||||
(httpResponse->getEntityLength() > 0 ||
|
||||
httpResponse->isTransferEncodingSpecified())) {
|
||||
return handleRedirect(httpResponse);
|
||||
} else {
|
||||
// Response body is 0 length or a response header shows that a persistent
|
||||
// connection is not enabled.
|
||||
if(req->supportsPersistentConnection()) {
|
||||
std::pair<std::string, uint16_t> peerInfo;
|
||||
socket->getPeerInfo(peerInfo);
|
||||
e->poolSocket(peerInfo.first, peerInfo.second, socket);
|
||||
}
|
||||
httpResponse->processRedirect();
|
||||
logger->info(MSG_REDIRECT, cuid, httpResponse->getRedirectURI().c_str());
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
}
|
||||
if(!_requestGroup->isSingleHostMultiConnectionEnabled()) {
|
||||
_requestGroup->removeURIWhoseHostnameIs(_requestGroup->searchServerHost(cuid)->getHostname());
|
||||
}
|
||||
|
@ -179,7 +193,8 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp
|
|||
return true;
|
||||
}
|
||||
|
||||
HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpResponseHandle& httpResponse)
|
||||
static SharedHandle<TransferEncoding> getTransferEncoding
|
||||
(const SharedHandle<HttpResponse>& httpResponse)
|
||||
{
|
||||
TransferEncodingHandle enc;
|
||||
if(httpResponse->isTransferEncodingSpecified()) {
|
||||
|
@ -191,6 +206,23 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpRe
|
|||
}
|
||||
enc->init();
|
||||
}
|
||||
return enc;
|
||||
}
|
||||
|
||||
bool HttpResponseCommand::handleRedirect
|
||||
(const SharedHandle<HttpResponse>& httpResponse)
|
||||
{
|
||||
SharedHandle<TransferEncoding> enc(getTransferEncoding(httpResponse));
|
||||
HttpNullDownloadCommand* command = new HttpNullDownloadCommand
|
||||
(cuid, req, _requestGroup, httpConnection, httpResponse, e, socket);
|
||||
command->setTransferDecoder(enc);
|
||||
e->commands.push_back(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpResponseHandle& httpResponse)
|
||||
{
|
||||
TransferEncodingHandle enc(getTransferEncoding(httpResponse));
|
||||
HttpDownloadCommand* command =
|
||||
new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e, socket);
|
||||
command->setMaxDownloadSpeedLimit(e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
|
||||
|
|
|
@ -50,6 +50,8 @@ private:
|
|||
|
||||
bool handleDefaultEncoding(const SharedHandle<HttpResponse>& httpResponse);
|
||||
bool handleOtherEncoding(const SharedHandle<HttpResponse>& httpResponse);
|
||||
bool handleRedirect(const SharedHandle<HttpResponse>& httpResponse);
|
||||
|
||||
HttpDownloadCommand* createHttpDownloadCommand(const SharedHandle<HttpResponse>& httpResponse);
|
||||
protected:
|
||||
bool executeInternal();
|
||||
|
|
Loading…
Reference in New Issue