2009-01-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Persist connection between the built-in HTTP server and a client
	if a client supports keep-alive. Fixed the bug that aria2 exits
	when the HTTP server receives EOF from a client.	
	* src/HttpServer.cc
	* src/HttpServer.h
	* src/HttpServerCommand.cc
	* src/HttpServerCommand.h
	* src/HttpServerResponseCommand.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-01-25 10:55:27 +00:00
parent 0742e3921f
commit 5def96906f
6 changed files with 88 additions and 7 deletions

View File

@ -1,3 +1,14 @@
2009-01-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Persist connection between the built-in HTTP server and a client
if a client supports keep-alive. Fixed the bug that aria2 exits
when the HTTP server receives EOF from a client.
* src/HttpServer.cc
* src/HttpServer.h
* src/HttpServerCommand.cc
* src/HttpServerCommand.h
* src/HttpServerResponseCommand.cc
2009-01-25 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added experimental built-in HTTP server. Currently, when a client

View File

@ -39,6 +39,8 @@
#include "DlAbortEx.h"
#include "message.h"
#include "Util.h"
#include "LogFactory.h"
#include "Logger.h"
namespace aria2 {
@ -47,7 +49,8 @@ HttpServer::HttpServer(const SharedHandle<SocketCore>& socket,
_socket(socket),
_socketBuffer(socket),
_e(e),
_headerProcessor(new HttpHeaderProcessor())
_headerProcessor(new HttpHeaderProcessor()),
_logger(LogFactory::getInstance())
{}
HttpServer::~HttpServer() {}
@ -69,16 +72,40 @@ SharedHandle<HttpHeader> HttpServer::receiveRequest()
size -= putbackDataLength;
_socket->readData(buf, size);
return _headerProcessor->getHttpRequestHeader();
SharedHandle<HttpHeader> header = _headerProcessor->getHttpRequestHeader();
if(!header.isNull()) {
_logger->info("HTTP Server received request\n%s",
_headerProcessor->getHeaderString().c_str());
_lastRequestHeader = header;
_headerProcessor->clear();
}
return header;
}
bool HttpServer::supportsPersistentConnection() const
{
std::string connection =
Util::toLower(_lastRequestHeader->getFirst(HttpHeader::CONNECTION));
return connection.find(HttpHeader::CLOSE) == std::string::npos &&
(_lastRequestHeader->getVersion() == HttpHeader::HTTP_1_1 ||
connection.find("keep-alive") != std::string::npos);
}
void HttpServer::feedResponse(const std::string& text)
{
std::string header = "HTTP/1.0 200 OK\r\n"
std::string header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: "+Util::uitos(text.size())+"\r\n"
"Connection: close\r\n"
"\r\n";
"Content-Length: "+Util::uitos(text.size())+"\r\n";
if(!supportsPersistentConnection()) {
header += "Connection: close\r\n";
}
header += "\r\n";
_logger->debug("HTTP Server sends response:\n%s", header.c_str());
_socketBuffer.feedSendBuffer(header);
_socketBuffer.feedSendBuffer(text);
}

View File

@ -48,6 +48,7 @@ class SocketCore;
class HttpHeader;
class HttpHeaderProcessor;
class DownloadEngine;
class Logger;
class HttpServer {
private:
@ -55,6 +56,8 @@ private:
SocketBuffer _socketBuffer;
DownloadEngine* _e;
SharedHandle<HttpHeaderProcessor> _headerProcessor;
Logger* _logger;
SharedHandle<HttpHeader> _lastRequestHeader;
public:
HttpServer(const SharedHandle<SocketCore>& socket, DownloadEngine* e);
@ -67,6 +70,8 @@ public:
ssize_t sendResponse();
bool sendBufferIsEmpty() const;
bool supportsPersistentConnection() const;
};
} // namespace aria2

View File

@ -51,6 +51,7 @@
#include "HttpServerResponseCommand.h"
#include "CheckIntegrityEntry.h"
#include "FileAllocationEntry.h"
#include "RecoverableException.h"
namespace aria2 {
@ -64,6 +65,18 @@ HttpServerCommand::HttpServerCommand(int32_t cuid, DownloadEngine* e,
_e->addSocketForReadCheck(_socket, this);
}
HttpServerCommand::HttpServerCommand(int32_t cuid,
const SharedHandle<HttpServer>& httpServer,
DownloadEngine* e,
const SharedHandle<SocketCore>& socket):
Command(cuid),
_e(e),
_socket(socket),
_httpServer(httpServer)
{
_e->addSocketForReadCheck(_socket, this);
}
HttpServerCommand::~HttpServerCommand()
{
_e->deleteSocketForReadCheck(_socket, this);
@ -218,9 +231,19 @@ static std::string createResponse(DownloadEngine* e)
bool HttpServerCommand::execute()
{
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
return true;
}
if(_socket->isReadable(0)) {
_timeout.reset();
SharedHandle<HttpHeader> header = _httpServer->receiveRequest();
SharedHandle<HttpHeader> header;
try {
header = _httpServer->receiveRequest();
} catch(RecoverableException& e) {
logger->info("CUID#%d - Error occurred while reading HTTP request",
e, cuid);
return true;
}
if(header.isNull()) {
_e->commands.push_back(this);
return false;

View File

@ -55,6 +55,11 @@ public:
HttpServerCommand(int32_t cuid, DownloadEngine* e,
const SharedHandle<SocketCore>& socket);
HttpServerCommand(int32_t cuid,
const SharedHandle<HttpServer>& httpServer,
DownloadEngine* e,
const SharedHandle<SocketCore>& socket);
virtual ~HttpServerCommand();
virtual bool execute();

View File

@ -37,6 +37,8 @@
#include "DownloadEngine.h"
#include "HttpServer.h"
#include "Logger.h"
#include "HttpServerCommand.h"
#include "RequestGroupMan.h"
namespace aria2 {
@ -61,9 +63,17 @@ HttpServerResponseCommand::~HttpServerResponseCommand()
bool HttpServerResponseCommand::execute()
{
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
return true;
}
_httpServer->sendResponse();
if(_httpServer->sendBufferIsEmpty()) {
logger->info("CUID#%d - HttpServer: all response transmitted.", cuid);
if(_httpServer->supportsPersistentConnection()) {
logger->info("CUID#%d - Persist connection.", cuid);
_e->commands.push_back
(new HttpServerCommand(cuid, _httpServer, _e, _socket));
}
return true;
} else {
if(_timeout.elapsed(10)) {