From b57b75f98dcc71de3bc0a767b01e3301b2a7f66e Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 8 May 2009 07:58:50 +0000 Subject: [PATCH] 2009-05-08 Tatsuhiro Tsujikawa Added xml-rpc functionality. Currently only addURI commad is supported. To enable xml-rpc, run aria2 with --enable-http-server. This option name is temporal and will be changed. The feature that reports download progress in html format is temporarily disabled. * src/HttpServer.cc * src/HttpServer.h * src/HttpServerBodyCommand.cc * src/HttpServerBodyCommand.h * src/HttpServerCommand.cc * src/HttpServerResponseCommand.cc * src/Makefile.am * src/OptionParser.cc * src/OptionParser.h * src/RequestGroupMan.cc * src/RequestGroupMan.h * src/XmlRpcMethod.cc * src/XmlRpcMethod.h * src/XmlRpcMethodFactory.cc * src/XmlRpcMethodFactory.h * src/XmlRpcMethodImpl.cc * src/XmlRpcMethodImpl.h * src/download_helper.cc * src/download_helper.h * test/Makefile.am * test/XmlRpcMethodTest.cc --- ChangeLog | 29 ++++++ src/HttpServer.cc | 44 ++++++++- src/HttpServer.h | 16 +++- src/HttpServerBodyCommand.cc | 122 +++++++++++++++++++++++ src/HttpServerBodyCommand.h | 67 +++++++++++++ src/HttpServerCommand.cc | 8 +- src/HttpServerResponseCommand.cc | 10 +- src/Makefile.am | 30 +++++- src/Makefile.in | 158 +++++++++++++++++++----------- src/OptionParser.cc | 12 +++ src/OptionParser.h | 4 + src/RequestGroupMan.cc | 6 ++ src/RequestGroupMan.h | 2 + src/XmlRpcMethod.cc | 160 +++++++++++++++++++++++++++++++ src/XmlRpcMethod.h | 76 +++++++++++++++ src/XmlRpcMethodFactory.cc | 56 +++++++++++ src/XmlRpcMethodFactory.h | 59 ++++++++++++ src/XmlRpcMethodImpl.cc | 101 +++++++++++++++++++ src/XmlRpcMethodImpl.h | 58 +++++++++++ src/download_helper.cc | 52 ++++++---- src/download_helper.h | 10 ++ test/Makefile.am | 6 ++ test/Makefile.in | 47 +++++---- test/XmlRpcMethodTest.cc | 65 +++++++++++++ 24 files changed, 1091 insertions(+), 107 deletions(-) create mode 100644 src/HttpServerBodyCommand.cc create mode 100644 src/HttpServerBodyCommand.h create mode 100644 src/XmlRpcMethod.cc create mode 100644 src/XmlRpcMethod.h create mode 100644 src/XmlRpcMethodFactory.cc create mode 100644 src/XmlRpcMethodFactory.h create mode 100644 src/XmlRpcMethodImpl.cc create mode 100644 src/XmlRpcMethodImpl.h create mode 100644 test/XmlRpcMethodTest.cc diff --git a/ChangeLog b/ChangeLog index 83a0c24a..4612f29d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2009-05-08 Tatsuhiro Tsujikawa + + Added xml-rpc functionality. Currently only addURI commad is + supported. To enable xml-rpc, run aria2 with + --enable-http-server. This option name is temporal and will be + changed. The feature that reports download progress in html format + is temporarily disabled. + * src/HttpServer.cc + * src/HttpServer.h + * src/HttpServerBodyCommand.cc + * src/HttpServerBodyCommand.h + * src/HttpServerCommand.cc + * src/HttpServerResponseCommand.cc + * src/Makefile.am + * src/OptionParser.cc + * src/OptionParser.h + * src/RequestGroupMan.cc + * src/RequestGroupMan.h + * src/XmlRpcMethod.cc + * src/XmlRpcMethod.h + * src/XmlRpcMethodFactory.cc + * src/XmlRpcMethodFactory.h + * src/XmlRpcMethodImpl.cc + * src/XmlRpcMethodImpl.h + * src/download_helper.cc + * src/download_helper.h + * test/Makefile.am + * test/XmlRpcMethodTest.cc + 2009-05-08 Tatsuhiro Tsujikawa Added xml-rpc request parser. The supported value types are: diff --git a/src/HttpServer.cc b/src/HttpServer.cc index cae0a076..70b5e00b 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -33,6 +33,9 @@ */ /* copyright --> */ #include "HttpServer.h" + +#include + #include "HttpHeader.h" #include "SocketCore.h" #include "HttpHeaderProcessor.h" @@ -50,7 +53,8 @@ HttpServer::HttpServer(const SharedHandle& socket, _socketBuffer(socket), _e(e), _headerProcessor(new HttpHeaderProcessor()), - _logger(LogFactory::getInstance()) + _logger(LogFactory::getInstance()), + _keepAlive(true) {} HttpServer::~HttpServer() {} @@ -77,14 +81,48 @@ SharedHandle HttpServer::receiveRequest() _logger->info("HTTP Server received request\n%s", _headerProcessor->getHeaderString().c_str()); _lastRequestHeader = header; + _lastBody.clear(); + _lastBody.str(""); + _lastContentLength = + _lastRequestHeader->getFirstAsUInt(HttpHeader::CONTENT_LENGTH); _headerProcessor->clear(); } return header; } +bool HttpServer::receiveBody() +{ + if(_lastContentLength == 0) { + return true; + } + const size_t BUFLEN = 4096; + char buf[BUFLEN]; + size_t length = std::min(BUFLEN, _lastContentLength-_lastBody.tellg()); + _socket->readData(buf, length); + if(length == 0 && !(_socket->wantRead() || _socket->wantWrite())) { + throw DlAbortEx(EX_EOF_FROM_PEER); + } + _lastBody.write(buf, length); + return _lastContentLength == static_cast(_lastBody.tellp()); +} + +std::string HttpServer::getBody() const +{ + return _lastBody.str(); +} + +const std::string& HttpServer::getRequestPath() const +{ + return _lastRequestHeader->getRequestPath(); +} + bool HttpServer::supportsPersistentConnection() const { + if(!_keepAlive) { + return false; + } + std::string connection = Util::toLower(_lastRequestHeader->getFirst(HttpHeader::CONNECTION)); @@ -93,10 +131,10 @@ bool HttpServer::supportsPersistentConnection() const connection.find("keep-alive") != std::string::npos); } -void HttpServer::feedResponse(const std::string& text) +void HttpServer::feedResponse(const std::string& text, const std::string& contentType) { std::string header = "HTTP/1.1 200 OK\r\n" - "Content-Type: text/html\r\n" + "Content-Type: "+contentType+"\r\n" "Content-Length: "+Util::uitos(text.size())+"\r\n"; if(!supportsPersistentConnection()) { diff --git a/src/HttpServer.h b/src/HttpServer.h index 9b789260..8c8d184a 100644 --- a/src/HttpServer.h +++ b/src/HttpServer.h @@ -38,6 +38,7 @@ #include "common.h" #include +#include #include "SharedHandle.h" #include "SocketBuffer.h" @@ -58,6 +59,9 @@ private: SharedHandle _headerProcessor; Logger* _logger; SharedHandle _lastRequestHeader; + uint64_t _lastContentLength; + std::stringstream _lastBody; + bool _keepAlive; public: HttpServer(const SharedHandle& socket, DownloadEngine* e); @@ -65,13 +69,23 @@ public: SharedHandle receiveRequest(); - void feedResponse(const std::string& text); + bool receiveBody(); + + std::string getBody() const; + + const std::string& getRequestPath() const; + + void feedResponse(const std::string& text, const std::string& contentType); ssize_t sendResponse(); bool sendBufferIsEmpty() const; bool supportsPersistentConnection() const; + + void enableKeepAlive() { _keepAlive = true; } + + void disableKeepAlive() { _keepAlive = false; } }; } // namespace aria2 diff --git a/src/HttpServerBodyCommand.cc b/src/HttpServerBodyCommand.cc new file mode 100644 index 00000000..6ed81ec5 --- /dev/null +++ b/src/HttpServerBodyCommand.cc @@ -0,0 +1,122 @@ +/* */ +#include "HttpServerBodyCommand.h" +#include "SocketCore.h" +#include "DownloadEngine.h" +#include "HttpServer.h" +#include "HttpHeader.h" +#include "Logger.h" +#include "RequestGroup.h" +#include "RequestGroupMan.h" +#include "RecoverableException.h" +#include "HttpServerResponseCommand.h" +#include "OptionParser.h" +#include "OptionHandler.h" +#include "XmlRpcRequestProcessor.h" +#include "XmlRpcRequestParserStateMachine.h" +#include "XmlRpcMethod.h" +#include "XmlRpcMethodFactory.h" + +namespace aria2 { + +HttpServerBodyCommand::HttpServerBodyCommand +(int32_t cuid, + const SharedHandle& httpServer, + DownloadEngine* e, + const SharedHandle& socket): + Command(cuid), + _e(e), + _socket(socket), + _httpServer(httpServer) +{ + _e->addSocketForReadCheck(_socket, this); +} + +HttpServerBodyCommand::~HttpServerBodyCommand() +{ + _e->deleteSocketForReadCheck(_socket, this); +} + +bool HttpServerBodyCommand::execute() +{ + if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) { + return true; + } + if(_socket->isReadable(0)) { + _timeout.reset(); + + try { + if(_httpServer->receiveBody()) { + // Do something for requestpath and body + if(_httpServer->getRequestPath() == "/rpc") { + // For xml-rpc, disable keep-alive + //_httpServer->disableKeepAlive(); + xmlrpc::XmlRpcRequest req = + xmlrpc::XmlRpcRequestProcessor().parseMemory(_httpServer->getBody()); + + SharedHandle method = + xmlrpc::XmlRpcMethodFactory::create(req._methodName); + std::string response = method->execute(req, _e); + _httpServer->feedResponse(response, "text/xml"); + Command* command = + new HttpServerResponseCommand(cuid, _httpServer, _e, _socket); + command->setStatus(Command::STATUS_ONESHOT_REALTIME); + _e->commands.push_back(command); + _e->setNoWait(true); + return true; + } else { + return true; + } + } else { + _e->commands.push_back(this); + return false; + } + } catch(RecoverableException& e) { + logger->info("CUID#%d - Error occurred while reading HTTP request body", + e, cuid); + return true; + } + } else { + if(_timeout.elapsed(30)) { + logger->info("HTTP request body timeout."); + return true; + } else { + _e->commands.push_back(this); + return false; + } + } +} + +} // namespace aria2 diff --git a/src/HttpServerBodyCommand.h b/src/HttpServerBodyCommand.h new file mode 100644 index 00000000..0a8468a4 --- /dev/null +++ b/src/HttpServerBodyCommand.h @@ -0,0 +1,67 @@ +/* */ +#ifndef _D_HTTP_SERVER_BODY_COMMAND_H_ +#define _D_HTTP_SERVER_BODY_COMMAND_H_ + +#include "Command.h" +#include "SharedHandle.h" +#include "TimeA2.h" + +namespace aria2 { + +class DownloadEngine; +class SocketCore; +class HttpServer; + +class HttpServerBodyCommand : public Command { +private: + DownloadEngine* _e; + SharedHandle _socket; + SharedHandle _httpServer; + Time _timeout; +public: + HttpServerBodyCommand(int32_t cuid, + const SharedHandle& httpServer, + DownloadEngine* e, + const SharedHandle& socket); + + virtual ~HttpServerBodyCommand(); + + virtual bool execute(); +}; + +} // namespace aria2 + +#endif // _D_HTTP_SERVER_BODY_COMMAND_H_ diff --git a/src/HttpServerCommand.cc b/src/HttpServerCommand.cc index 4bbd0117..a06e53f9 100644 --- a/src/HttpServerCommand.cc +++ b/src/HttpServerCommand.cc @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "SocketCore.h" @@ -49,6 +49,7 @@ #include "BtContext.h" #include "Util.h" #include "HttpServerResponseCommand.h" +#include "HttpServerBodyCommand.h" #include "CheckIntegrityEntry.h" #include "FileAllocationEntry.h" #include "RecoverableException.h" @@ -248,9 +249,8 @@ bool HttpServerCommand::execute() _e->commands.push_back(this); return false; } else { - _httpServer->feedResponse(createResponse(_e)); - Command* command = new HttpServerResponseCommand(cuid, _httpServer, _e, - _socket); + Command* command = new HttpServerBodyCommand(cuid, _httpServer, _e, + _socket); command->setStatus(Command::STATUS_ONESHOT_REALTIME); _e->commands.push_back(command); _e->setNoWait(true); diff --git a/src/HttpServerResponseCommand.cc b/src/HttpServerResponseCommand.cc index ca096b93..60d9766e 100644 --- a/src/HttpServerResponseCommand.cc +++ b/src/HttpServerResponseCommand.cc @@ -69,11 +69,11 @@ bool HttpServerResponseCommand::execute() _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)); - } +// 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)) { diff --git a/src/Makefile.am b/src/Makefile.am index 9945f1a6..404fc8b0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -209,6 +209,28 @@ SRCS = Socket.h\ bitfield.h\ BDE.cc BDE.h +if ENABLE_XML_RPC +SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\ + XmlRpcRequestParserStateMachine.cc XmlRpcRequestParserStateMachine.h\ + XmlRpcRequestParserState.h\ + XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\ + XmlRpcElements.cc XmlRpcElements.h\ + XmlRpcRequest.h\ + XmlRpcRequestProcessor.h\ + HttpServerBodyCommand.cc HttpServerBodyCommand.h\ + XmlRpcMethod.cc XmlRpcMethod.h\ + XmlRpcMethodImpl.cc XmlRpcMethodImpl.h\ + XmlRpcMethodFactory.cc XmlRpcMethodFactory.h +endif # ENABLE_XML_RPC + +if HAVE_LIBXML2 +SRCS += Xml2XmlRpcRequestProcessor.cc Xml2XmlRpcRequestProcessor.h +endif # HAVE_LIBXML2 + +if HAVE_LIBEXPAT +SRCS += ExpatXmlRpcRequestProcessor.cc ExpatXmlRpcRequestProcessor.h +endif # HAVE_LIBEXPAT + if HAVE_POSIX_FALLOCATE SRCS += FallocFileAllocationIterator.cc FallocFileAllocationIterator.h endif # HAVE_POSIX_FALLOCATE @@ -445,13 +467,13 @@ SRCS += Metalinker.cc Metalinker.h\ MetalinkHelper.cc MetalinkHelper.h endif # ENABLE_METALINK -if ENABLE_LIBXML2 +if ENABLE_METALINK_LIBXML2 SRCS += XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h -endif # ENABLE_LIBXML2 +endif # ENABLE_METALINK_LIBXML2 -if ENABLE_LIBEXPAT +if ENABLE_METALINK_LIBEXPAT SRCS += ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h -endif # ENABLE_LIBEXPAT +endif # ENABLE_METALINK_LIBEXPAT if !HAVE_ASCTIME_R SRCS += asctime_r.c asctime_r.h diff --git a/src/Makefile.in b/src/Makefile.in index 9969bf8f..b909dc12 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -35,15 +35,29 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = aria2c$(EXEEXT) -@HAVE_POSIX_FALLOCATE_TRUE@am__append_1 = FallocFileAllocationIterator.cc FallocFileAllocationIterator.h -@HAVE_EPOLL_TRUE@am__append_2 = EpollEventPoll.cc EpollEventPoll.h -@ENABLE_SSL_TRUE@am__append_3 = TLSContext.h -@HAVE_LIBGNUTLS_TRUE@am__append_4 = LibgnutlsTLSContext.cc LibgnutlsTLSContext.h -@HAVE_LIBSSL_TRUE@am__append_5 = LibsslTLSContext.cc LibsslTLSContext.h -@HAVE_LIBZ_TRUE@am__append_6 = GZipDecoder.cc GZipDecoder.h -@HAVE_SQLITE3_TRUE@am__append_7 = Sqlite3MozCookieParser.cc Sqlite3MozCookieParser.h -@ENABLE_ASYNC_DNS_TRUE@am__append_8 = AsyncNameResolver.cc AsyncNameResolver.h -@ENABLE_MESSAGE_DIGEST_TRUE@am__append_9 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ +@ENABLE_XML_RPC_TRUE@am__append_1 = XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserStateMachine.cc XmlRpcRequestParserStateMachine.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserState.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcElements.cc XmlRpcElements.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequest.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestProcessor.h\ +@ENABLE_XML_RPC_TRUE@ HttpServerBodyCommand.cc HttpServerBodyCommand.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethod.cc XmlRpcMethod.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethodImpl.cc XmlRpcMethodImpl.h\ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethodFactory.cc XmlRpcMethodFactory.h + +@HAVE_LIBXML2_TRUE@am__append_2 = Xml2XmlRpcRequestProcessor.cc Xml2XmlRpcRequestProcessor.h +@HAVE_LIBEXPAT_TRUE@am__append_3 = ExpatXmlRpcRequestProcessor.cc ExpatXmlRpcRequestProcessor.h +@HAVE_POSIX_FALLOCATE_TRUE@am__append_4 = FallocFileAllocationIterator.cc FallocFileAllocationIterator.h +@HAVE_EPOLL_TRUE@am__append_5 = EpollEventPoll.cc EpollEventPoll.h +@ENABLE_SSL_TRUE@am__append_6 = TLSContext.h +@HAVE_LIBGNUTLS_TRUE@am__append_7 = LibgnutlsTLSContext.cc LibgnutlsTLSContext.h +@HAVE_LIBSSL_TRUE@am__append_8 = LibsslTLSContext.cc LibsslTLSContext.h +@HAVE_LIBZ_TRUE@am__append_9 = GZipDecoder.cc GZipDecoder.h +@HAVE_SQLITE3_TRUE@am__append_10 = Sqlite3MozCookieParser.cc Sqlite3MozCookieParser.h +@ENABLE_ASYNC_DNS_TRUE@am__append_11 = AsyncNameResolver.cc AsyncNameResolver.h +@ENABLE_MESSAGE_DIGEST_TRUE@am__append_12 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.cc IteratableChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityDispatcherCommand.cc CheckIntegrityDispatcherCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ @@ -53,7 +67,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_MESSAGE_DIGEST_TRUE@ Checksum.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ ChunkChecksum.h -@ENABLE_BITTORRENT_TRUE@am__append_10 = PeerMessageUtil.cc PeerMessageUtil.h\ +@ENABLE_BITTORRENT_TRUE@am__append_13 = PeerMessageUtil.cc PeerMessageUtil.h\ @ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.cc PeerAbstractCommand.h\ @ENABLE_BITTORRENT_TRUE@ PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\ @ENABLE_BITTORRENT_TRUE@ PeerInteractionCommand.cc PeerInteractionCommand.h\ @@ -213,7 +227,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ IndexBtMessageValidator.h\ @ENABLE_BITTORRENT_TRUE@ ExtensionMessageRegistry.h -@ENABLE_METALINK_TRUE@am__append_11 = Metalinker.cc Metalinker.h\ +@ENABLE_METALINK_TRUE@am__append_14 = Metalinker.cc Metalinker.h\ @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\ @ENABLE_METALINK_TRUE@ MetalinkProcessor.h\ @@ -241,17 +255,17 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\ @ENABLE_METALINK_TRUE@ MetalinkHelper.cc MetalinkHelper.h -@ENABLE_LIBXML2_TRUE@am__append_12 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h -@ENABLE_LIBEXPAT_TRUE@am__append_13 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h -@HAVE_ASCTIME_R_FALSE@am__append_14 = asctime_r.c asctime_r.h -@HAVE_BASENAME_FALSE@am__append_15 = libgen.c libgen.h -@HAVE_GETADDRINFO_FALSE@am__append_16 = getaddrinfo.c getaddrinfo.h -@HAVE_GAI_STRERROR_FALSE@am__append_17 = gai_strerror.c gai_strerror.h -@HAVE_GETTIMEOFDAY_FALSE@am__append_18 = gettimeofday.c gettimeofday.h -@HAVE_INET_ATON_FALSE@am__append_19 = inet_aton.c inet_aton.h -@HAVE_LOCALTIME_R_FALSE@am__append_20 = localtime_r.c localtime_r.h -@HAVE_STRPTIME_FALSE@am__append_21 = strptime.c strptime.h -@HAVE_TIMEGM_FALSE@am__append_22 = timegm.c timegm.h +@ENABLE_METALINK_LIBXML2_TRUE@am__append_15 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h +@ENABLE_METALINK_LIBEXPAT_TRUE@am__append_16 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h +@HAVE_ASCTIME_R_FALSE@am__append_17 = asctime_r.c asctime_r.h +@HAVE_BASENAME_FALSE@am__append_18 = libgen.c libgen.h +@HAVE_GETADDRINFO_FALSE@am__append_19 = getaddrinfo.c getaddrinfo.h +@HAVE_GAI_STRERROR_FALSE@am__append_20 = gai_strerror.c gai_strerror.h +@HAVE_GETTIMEOFDAY_FALSE@am__append_21 = gettimeofday.c gettimeofday.h +@HAVE_INET_ATON_FALSE@am__append_22 = inet_aton.c inet_aton.h +@HAVE_LOCALTIME_R_FALSE@am__append_23 = localtime_r.c localtime_r.h +@HAVE_STRPTIME_FALSE@am__append_24 = strptime.c strptime.h +@HAVE_TIMEGM_FALSE@am__append_25 = timegm.c timegm.h subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -409,11 +423,22 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ HttpServerResponseCommand.h HttpServer.cc HttpServer.h \ PieceSelector.h LongestSequencePieceSelector.cc \ LongestSequencePieceSelector.h bitfield.h BDE.cc BDE.h \ - FallocFileAllocationIterator.cc FallocFileAllocationIterator.h \ - EpollEventPoll.cc EpollEventPoll.h TLSContext.h \ - LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \ - LibsslTLSContext.cc LibsslTLSContext.h GZipDecoder.cc \ - GZipDecoder.h Sqlite3MozCookieParser.cc \ + XmlRpcRequestParserController.cc \ + XmlRpcRequestParserController.h \ + XmlRpcRequestParserStateMachine.cc \ + XmlRpcRequestParserStateMachine.h XmlRpcRequestParserState.h \ + XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h \ + XmlRpcElements.cc XmlRpcElements.h XmlRpcRequest.h \ + XmlRpcRequestProcessor.h HttpServerBodyCommand.cc \ + HttpServerBodyCommand.h XmlRpcMethod.cc XmlRpcMethod.h \ + XmlRpcMethodImpl.cc XmlRpcMethodImpl.h XmlRpcMethodFactory.cc \ + XmlRpcMethodFactory.h Xml2XmlRpcRequestProcessor.cc \ + Xml2XmlRpcRequestProcessor.h ExpatXmlRpcRequestProcessor.cc \ + ExpatXmlRpcRequestProcessor.h FallocFileAllocationIterator.cc \ + FallocFileAllocationIterator.h EpollEventPoll.cc \ + EpollEventPoll.h TLSContext.h LibgnutlsTLSContext.cc \ + LibgnutlsTLSContext.h LibsslTLSContext.cc LibsslTLSContext.h \ + GZipDecoder.cc GZipDecoder.h Sqlite3MozCookieParser.cc \ Sqlite3MozCookieParser.h AsyncNameResolver.cc \ AsyncNameResolver.h IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.h \ @@ -563,22 +588,35 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ gai_strerror.h gettimeofday.c gettimeofday.h inet_aton.c \ inet_aton.h localtime_r.c localtime_r.h strptime.c strptime.h \ timegm.c timegm.h -@HAVE_POSIX_FALLOCATE_TRUE@am__objects_1 = FallocFileAllocationIterator.$(OBJEXT) -@HAVE_EPOLL_TRUE@am__objects_2 = EpollEventPoll.$(OBJEXT) -am__objects_3 = -@HAVE_LIBGNUTLS_TRUE@am__objects_4 = LibgnutlsTLSContext.$(OBJEXT) -@HAVE_LIBSSL_TRUE@am__objects_5 = LibsslTLSContext.$(OBJEXT) -@HAVE_LIBZ_TRUE@am__objects_6 = GZipDecoder.$(OBJEXT) -@HAVE_SQLITE3_TRUE@am__objects_7 = Sqlite3MozCookieParser.$(OBJEXT) -@ENABLE_ASYNC_DNS_TRUE@am__objects_8 = AsyncNameResolver.$(OBJEXT) -@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_9 = IteratableChunkChecksumValidator.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@am__objects_1 = \ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserController.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserStateMachine.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestParserStateImpl.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcElements.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ HttpServerBodyCommand.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethod.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethodImpl.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethodFactory.$(OBJEXT) +@HAVE_LIBXML2_TRUE@am__objects_2 = \ +@HAVE_LIBXML2_TRUE@ Xml2XmlRpcRequestProcessor.$(OBJEXT) +@HAVE_LIBEXPAT_TRUE@am__objects_3 = \ +@HAVE_LIBEXPAT_TRUE@ ExpatXmlRpcRequestProcessor.$(OBJEXT) +@HAVE_POSIX_FALLOCATE_TRUE@am__objects_4 = FallocFileAllocationIterator.$(OBJEXT) +@HAVE_EPOLL_TRUE@am__objects_5 = EpollEventPoll.$(OBJEXT) +am__objects_6 = +@HAVE_LIBGNUTLS_TRUE@am__objects_7 = LibgnutlsTLSContext.$(OBJEXT) +@HAVE_LIBSSL_TRUE@am__objects_8 = LibsslTLSContext.$(OBJEXT) +@HAVE_LIBZ_TRUE@am__objects_9 = GZipDecoder.$(OBJEXT) +@HAVE_SQLITE3_TRUE@am__objects_10 = Sqlite3MozCookieParser.$(OBJEXT) +@ENABLE_ASYNC_DNS_TRUE@am__objects_11 = AsyncNameResolver.$(OBJEXT) +@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_12 = IteratableChunkChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityDispatcherCommand.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT) -@ENABLE_BITTORRENT_TRUE@am__objects_10 = PeerMessageUtil.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@am__objects_13 = PeerMessageUtil.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerInitiateConnectionCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerInteractionCommand.$(OBJEXT) \ @@ -686,7 +724,7 @@ am__objects_3 = @ENABLE_BITTORRENT_TRUE@ RangeBtMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ IndexBtMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ ZeroBtMessage.$(OBJEXT) -@ENABLE_METALINK_TRUE@am__objects_11 = Metalinker.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@am__objects_14 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkParserController.$(OBJEXT) \ @@ -711,20 +749,18 @@ am__objects_3 = @ENABLE_METALINK_TRUE@ Metalink2RequestGroup.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkHelper.$(OBJEXT) -@ENABLE_LIBXML2_TRUE@am__objects_12 = \ -@ENABLE_LIBXML2_TRUE@ XML2SAXMetalinkProcessor.$(OBJEXT) -@ENABLE_LIBEXPAT_TRUE@am__objects_13 = \ -@ENABLE_LIBEXPAT_TRUE@ ExpatMetalinkProcessor.$(OBJEXT) -@HAVE_ASCTIME_R_FALSE@am__objects_14 = asctime_r.$(OBJEXT) -@HAVE_BASENAME_FALSE@am__objects_15 = libgen.$(OBJEXT) -@HAVE_GETADDRINFO_FALSE@am__objects_16 = getaddrinfo.$(OBJEXT) -@HAVE_GAI_STRERROR_FALSE@am__objects_17 = gai_strerror.$(OBJEXT) -@HAVE_GETTIMEOFDAY_FALSE@am__objects_18 = gettimeofday.$(OBJEXT) -@HAVE_INET_ATON_FALSE@am__objects_19 = inet_aton.$(OBJEXT) -@HAVE_LOCALTIME_R_FALSE@am__objects_20 = localtime_r.$(OBJEXT) -@HAVE_STRPTIME_FALSE@am__objects_21 = strptime.$(OBJEXT) -@HAVE_TIMEGM_FALSE@am__objects_22 = timegm.$(OBJEXT) -am__objects_23 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ +@ENABLE_METALINK_LIBXML2_TRUE@am__objects_15 = XML2SAXMetalinkProcessor.$(OBJEXT) +@ENABLE_METALINK_LIBEXPAT_TRUE@am__objects_16 = ExpatMetalinkProcessor.$(OBJEXT) +@HAVE_ASCTIME_R_FALSE@am__objects_17 = asctime_r.$(OBJEXT) +@HAVE_BASENAME_FALSE@am__objects_18 = libgen.$(OBJEXT) +@HAVE_GETADDRINFO_FALSE@am__objects_19 = getaddrinfo.$(OBJEXT) +@HAVE_GAI_STRERROR_FALSE@am__objects_20 = gai_strerror.$(OBJEXT) +@HAVE_GETTIMEOFDAY_FALSE@am__objects_21 = gettimeofday.$(OBJEXT) +@HAVE_INET_ATON_FALSE@am__objects_22 = inet_aton.$(OBJEXT) +@HAVE_LOCALTIME_R_FALSE@am__objects_23 = localtime_r.$(OBJEXT) +@HAVE_STRPTIME_FALSE@am__objects_24 = strptime.$(OBJEXT) +@HAVE_TIMEGM_FALSE@am__objects_25 = timegm.$(OBJEXT) +am__objects_26 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ AbstractCommand.$(OBJEXT) \ InitiateConnectionCommandFactory.$(OBJEXT) \ DownloadCommand.$(OBJEXT) \ @@ -810,8 +846,9 @@ am__objects_23 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ $(am__objects_13) $(am__objects_14) $(am__objects_15) \ $(am__objects_16) $(am__objects_17) $(am__objects_18) \ $(am__objects_19) $(am__objects_20) $(am__objects_21) \ - $(am__objects_22) -am_libaria2c_a_OBJECTS = $(am__objects_23) + $(am__objects_22) $(am__objects_23) $(am__objects_24) \ + $(am__objects_25) +am_libaria2c_a_OBJECTS = $(am__objects_26) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -1147,7 +1184,8 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ $(am__append_13) $(am__append_14) $(am__append_15) \ $(am__append_16) $(am__append_17) $(am__append_18) \ $(am__append_19) $(am__append_20) $(am__append_21) \ - $(am__append_22) + $(am__append_22) $(am__append_23) $(am__append_24) \ + $(am__append_25) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -1374,6 +1412,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EpollEventPoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Exception.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ExpatMetalinkProcessor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ExpatXmlRpcRequestProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FallocFileAllocationIterator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeedbackURISelector.Po@am__quote@ @@ -1411,6 +1450,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpServer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpServerBodyCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpServerCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpServerResponseCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpSkipResponseCommand.Po@am__quote@ @@ -1520,6 +1560,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VerificationMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VersionMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XML2SAXMetalinkProcessor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2XmlRpcRequestProcessor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcElements.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethod.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodFactory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodImpl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserController.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserStateImpl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserStateMachine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ZeroBtMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asctime_r.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bencode.Po@am__quote@ diff --git a/src/OptionParser.cc b/src/OptionParser.cc index 564343ea..42920737 100644 --- a/src/OptionParser.cc +++ b/src/OptionParser.cc @@ -47,6 +47,7 @@ #include "A2STR.h" #include "a2functional.h" #include "array_fun.h" +#include "OptionHandlerFactory.h" namespace aria2 { @@ -337,4 +338,15 @@ OptionParser::getOptionHandlers() const return _optionHandlers; } +SharedHandle OptionParser::_optionParser; + +SharedHandle OptionParser::getInstance() +{ + if(_optionParser.isNull()) { + _optionParser.reset(new OptionParser()); + _optionParser->setOptionHandlers(OptionHandlerFactory::createOptionHandlers()); + } + return _optionParser; +} + } // namespace aria2 diff --git a/src/OptionParser.h b/src/OptionParser.h index b02f46c1..32422f50 100644 --- a/src/OptionParser.h +++ b/src/OptionParser.h @@ -56,6 +56,8 @@ private: SharedHandle getOptionHandlerByName(const std::string& optName); + + static SharedHandle _optionParser; public: OptionParser(); @@ -92,6 +94,8 @@ public: SharedHandle findByShortName(char shortName) const; const std::deque >& getOptionHandlers() const; + + static SharedHandle getInstance(); }; typedef SharedHandle OptionParserHandle; diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc index a2029e44..0e2c5af1 100644 --- a/src/RequestGroupMan.cc +++ b/src/RequestGroupMan.cc @@ -130,6 +130,12 @@ RequestGroupMan::getRequestGroups() const return _requestGroups; } +const std::deque >& +RequestGroupMan::getReservedGroups() const +{ + return _reservedGroups; +} + class ProcessStoppedRequestGroup { private: DownloadEngine* _e; diff --git a/src/RequestGroupMan.h b/src/RequestGroupMan.h index 07ac17f9..e9d1b607 100644 --- a/src/RequestGroupMan.h +++ b/src/RequestGroupMan.h @@ -112,6 +112,8 @@ public: const std::deque >& getRequestGroups() const; + const std::deque >& getReservedGroups() const; + void showDownloadResults(std::ostream& o) const; bool isSameFileBeingDownloaded(RequestGroup* requestGroup) const; diff --git a/src/XmlRpcMethod.cc b/src/XmlRpcMethod.cc new file mode 100644 index 00000000..46faacab --- /dev/null +++ b/src/XmlRpcMethod.cc @@ -0,0 +1,160 @@ +/* */ +#include "XmlRpcMethod.h" + +#include +#include + +#include "DownloadEngine.h" +#include "BDE.h" +#include "LogFactory.h" +#include "RecoverableException.h" +#include "message.h" +#include "OptionParser.h" +#include "OptionHandler.h" +#include "Option.h" +#include "array_fun.h" +#include "download_helper.h" +#include "XmlRpcRequest.h" + +namespace aria2 { + +namespace xmlrpc { + +XmlRpcMethod::XmlRpcMethod(): + _optionParser(OptionParser::getInstance()), + _logger(LogFactory::getInstance()) {} + +static BDE createErrorResponse(const Exception& e) +{ + BDE params = BDE::list(); + params << BDE("ERROR"); + params << BDE(e.what()); + return params; +} + +static void encodeValue(const BDE& value, std::ostream& o); + +template +static void encodeArray +(InputIterator first, InputIterator last, std::ostream& o) +{ + o << "" << ""; + for(; first != last; ++first) { + encodeValue(*first, o); + } + o << "" << ""; +} + +template +static void encodeStruct +(InputIterator first, InputIterator last, std::ostream& o) +{ + o << ""; + for(; first != last; ++first) { + o << "" + << "" << (*first).first << ""; + encodeValue((*first).second, o); + o << ""; + } + o << ""; +} + +static void encodeValue(const BDE& value, std::ostream& o) +{ + o << ""; + if(value.isString()) { + o << "" << value.s() << ""; + } else if(value.isList()) { + encodeArray(value.listBegin(), value.listEnd(), o); + } else if(value.isDict()) { + encodeStruct(value.dictBegin(), value.dictEnd(), o); + } + o << ""; +} + +template +static void encodeParams +(InputIterator first, InputIterator last, std::ostream& o) +{ + o << ""; + for(; first != last; ++first) { + o << ""; + encodeValue(*first, o); + o << ""; + } + o << ""; +} + +static std::string encodeXml(const BDE& params) +{ + assert(params.isList()); + std::stringstream o; + o << "" << ""; + encodeParams(params.listBegin(), params.listEnd(), o); + o << ""; + return o.str(); +} + +std::string XmlRpcMethod::execute(const XmlRpcRequest& req, DownloadEngine* e) +{ + try { + BDE retparams = process(req, e); + return encodeXml(retparams); + } catch(RecoverableException& e) { + _logger->debug(EX_EXCEPTION_CAUGHT, e); + return encodeXml(createErrorResponse(e)); + } +} + +void XmlRpcMethod::gatherRequestOption +(Option& requestOption, const Option& option, const BDE& optionsDict) +{ + for(std::vector::const_iterator i = listRequestOptions().begin(); + i != listRequestOptions().end(); ++i) { + if(optionsDict.containsKey(*i)) { + const BDE& value = optionsDict[*i]; + if(value.isString()) { + _optionParser->findByName(*i)->parse + (requestOption, value.s()); + } + } + } + completeRequestOption(requestOption, option); +} + +} // namespace xmlrpc + +} // namespace aria2 diff --git a/src/XmlRpcMethod.h b/src/XmlRpcMethod.h new file mode 100644 index 00000000..52b59a61 --- /dev/null +++ b/src/XmlRpcMethod.h @@ -0,0 +1,76 @@ +/* */ +#ifndef _D_XML_RPC_METHOD_H_ +#define _D_XML_RPC_METHOD_H_ + +#include "common.h" + +#include + +#include "SharedHandle.h" + +namespace aria2 { + +class DownloadEngine; +class OptionParser; +class BDE; +class Logger; +class Option; + +namespace xmlrpc { + +struct XmlRpcRequest; + +class XmlRpcMethod { +protected: + SharedHandle _optionParser; + + Logger* _logger; + + virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e) = 0; + + void gatherRequestOption(Option& requestOption, const Option& option, + const BDE& optionsDict); +public: + XmlRpcMethod(); + + std::string execute(const XmlRpcRequest& req, DownloadEngine* e); +}; + +} // namespace xmlrpc + +} // namespace aria2 + +#endif // _D_XML_RPC_METHOD_H_ diff --git a/src/XmlRpcMethodFactory.cc b/src/XmlRpcMethodFactory.cc new file mode 100644 index 00000000..b1c19755 --- /dev/null +++ b/src/XmlRpcMethodFactory.cc @@ -0,0 +1,56 @@ +/* */ +#include "XmlRpcMethodFactory.h" +#include "XmlRpcMethodImpl.h" +#include "OptionParser.h" +#include "OptionHandler.h" + +namespace aria2 { + +namespace xmlrpc { + +SharedHandle +XmlRpcMethodFactory::create(const std::string& methodName) +{ + if(methodName == "aria2.addURI") { + return SharedHandle(new AddURIXmlRpcMethod()); + } else { + return SharedHandle(new FailXmlRpcMethod()); + } +} + +} // namespace xmlrpc + +} // namespace aria2 diff --git a/src/XmlRpcMethodFactory.h b/src/XmlRpcMethodFactory.h new file mode 100644 index 00000000..431d6810 --- /dev/null +++ b/src/XmlRpcMethodFactory.h @@ -0,0 +1,59 @@ +/* */ +#ifndef _D_XML_RPC_METHOD_FACTORY_H_ +#define _D_XML_RPC_METHOD_FACTORY_H_ + +#include "common.h" + +#include + +#include "SharedHandle.h" + +namespace aria2 { + +namespace xmlrpc { + +class XmlRpcMethod; + +class XmlRpcMethodFactory { +public: + static SharedHandle create(const std::string& methodName); +}; + +} // namespace xmlrpc + +} // namespace aria2 + +#endif // _D_XML_RPC_METHOD_FACTORY_H_ diff --git a/src/XmlRpcMethodImpl.cc b/src/XmlRpcMethodImpl.cc new file mode 100644 index 00000000..ec4aa38a --- /dev/null +++ b/src/XmlRpcMethodImpl.cc @@ -0,0 +1,101 @@ +/* */ +#include "XmlRpcMethodImpl.h" + +#include + +#include "Logger.h" +#include "BDE.h" +#include "DlAbortEx.h" +#include "Option.h" +#include "OptionParser.h" +#include "OptionHandler.h" +#include "DownloadEngine.h" +#include "RequestGroup.h" +#include "download_helper.h" +#include "Util.h" +#include "RequestGroupMan.h" +#include "StringFormat.h" +#include "XmlRpcRequest.h" + +namespace aria2 { + +namespace xmlrpc { + +BDE AddURIXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) +{ + const BDE& params = req._params; + assert(params.isList()); + if(params.empty() || !params[0].isList() || params[0].empty()) { + throw DlAbortEx("URI is not provided."); + } + std::deque uris; + for(BDE::List::const_iterator i = params[0].listBegin(); + i != params[0].listEnd(); ++i) { + if((*i).isString()) { + uris.push_back((*i).s()); + } + } + + Option requestOption; + if(params.size() > 1 && params[1].isDict()) { + gatherRequestOption(requestOption, *e->option, params[1]); + } + std::deque > result; + createRequestGroupForUri(result, *e->option, uris, requestOption, + /* ignoreForceSeq = */ true, + /* ignoreNonURI = */ true); + + if(!result.empty()) { + e->_requestGroupMan->addReservedGroup(result.front()); + BDE resParams = BDE::list(); + resParams << BDE("OK"); + resParams << BDE(Util::itos(result.front()->getGID())); + return resParams; + } else { + throw DlAbortEx("No URI to download."); + } +} + +BDE FailXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e) +{ + throw DlAbortEx + (StringFormat("Method %s was not recognized.", + req._methodName.c_str()).str()); +} + +} // namespace xmlrpc + +} // namespace aria2 diff --git a/src/XmlRpcMethodImpl.h b/src/XmlRpcMethodImpl.h new file mode 100644 index 00000000..dc9be756 --- /dev/null +++ b/src/XmlRpcMethodImpl.h @@ -0,0 +1,58 @@ +/* */ +#ifndef _D_XML_RPC_METHOD_IMPL_H_ +#define _D_XML_RPC_METHOD_IMPL_H_ + +#include "XmlRpcMethod.h" + +namespace aria2 { + +namespace xmlrpc { + +class AddURIXmlRpcMethod:public XmlRpcMethod { +protected: + virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); +}; + +class FailXmlRpcMethod:public XmlRpcMethod { +protected: + virtual BDE process(const XmlRpcRequest& req, DownloadEngine* e); +}; + +} // namespace xmlrpc + +} // namespace aria2 + +#endif // _D_XML_RPC_METHOD_IMPL_H_ diff --git a/src/download_helper.cc b/src/download_helper.cc index 7b23a6f7..ae03d0d3 100644 --- a/src/download_helper.cc +++ b/src/download_helper.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include "RequestGroup.h" #include "Option.h" @@ -62,6 +63,21 @@ namespace aria2 { +const std::vector& listRequestOptions() +{ + static const std::string REQUEST_OPTIONS[] = { + PREF_DIR, + PREF_OUT, + PREF_SELECT_FILE, + PREF_INDEX_OUT + }; + static std::vector requestOptions + (&REQUEST_OPTIONS[0], + &REQUEST_OPTIONS[arrayLength(REQUEST_OPTIONS)]);; + + return requestOptions; +} + static void unfoldURI (std::deque& result, const std::deque& args) { @@ -246,9 +262,10 @@ static void copyIfndef(Option& dest, const Option& src, const std::string& name) } } -static void createRequestGroupForUri +void createRequestGroupForUri (std::deque >& result, const Option& op, - const std::deque& uris, const Option& requestOption) + const std::deque& uris, const Option& requestOption, + bool ignoreForceSequential, bool ignoreNonURI) { std::deque nargs; if(op.get(PREF_PARAMETERIZED_URI) == V_TRUE) { @@ -256,7 +273,7 @@ static void createRequestGroupForUri } else { nargs = uris; } - if(op.get(PREF_FORCE_SEQUENTIAL) == V_TRUE) { + if(!ignoreForceSequential && op.get(PREF_FORCE_SEQUENTIAL) == V_TRUE) { std::for_each(nargs.begin(), nargs.end(), AccRequestGroup(result, op, requestOption)); } else { @@ -273,9 +290,11 @@ static void createRequestGroupForUri rg->setNumConcurrentCommand(numSplit); result.push_back(rg); } - // process remaining URIs(local metalink, BitTorrent files) - std::for_each(strmProtoEnd, nargs.end(), - AccRequestGroup(result, op, requestOption)); + if(!ignoreNonURI) { + // process remaining URIs(local metalink, BitTorrent files) + std::for_each(strmProtoEnd, nargs.end(), + AccRequestGroup(result, op, requestOption)); + } } } @@ -288,7 +307,7 @@ void createRequestGroupForUri template static void foreachCopyIfndef(InputIterator first, InputIterator last, - Option& dest, const Option& src) + Option& dest, const Option& src) { for(; first != last; ++first) { copyIfndef(dest, src, *first); @@ -307,17 +326,7 @@ static void createRequestGroupForUriList if(uris.empty()) { continue; } - // TODO use OptionParser to validate the value in the options. - // These options can be specified in input list(-i list). - static const std::string REQUEST_OPTIONS[] = { - PREF_DIR, - PREF_OUT, - PREF_SELECT_FILE, - PREF_INDEX_OUT - }; - foreachCopyIfndef(&REQUEST_OPTIONS[0], - &REQUEST_OPTIONS[arrayLength(REQUEST_OPTIONS)], - requestOption, op); + completeRequestOption(requestOption, op); createRequestGroupForUri(result, op, uris, requestOption); } @@ -339,4 +348,11 @@ void createRequestGroupForUriList } } +void completeRequestOption(Option& requestOption, const Option& option) +{ + foreachCopyIfndef(listRequestOptions().begin(), + listRequestOptions().end(), + requestOption, option); +} + } // namespace aria2 diff --git a/src/download_helper.h b/src/download_helper.h index 3448f094..51551df4 100644 --- a/src/download_helper.h +++ b/src/download_helper.h @@ -39,6 +39,7 @@ #include #include +#include #include "SharedHandle.h" @@ -47,6 +48,8 @@ namespace aria2 { class RequestGroup; class Option; +const std::vector& listRequestOptions(); + #ifdef ENABLE_BITTORRENT // Create RequestGroup object using torrent file specified by torrent-file // option. In this function, force-sequential is ignored. @@ -75,6 +78,13 @@ void createRequestGroupForUri (std::deque >& result, const Option& op, const std::deque& uris); +void createRequestGroupForUri +(std::deque >& result, const Option& op, + const std::deque& uris, const Option& requestOption, + bool ignoreForceSequential = false, bool ignoreNonURI = false); + +void completeRequestOption(Option& requestOption, const Option& option); + } // namespace aria2 #endif // _D_DOWNLOAD_HELPER_H_ diff --git a/test/Makefile.am b/test/Makefile.am index 24c6a546..2f27fc9b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -73,6 +73,12 @@ aria2c_SOURCES = AllTest.cc\ bitfieldTest.cc\ BDETest.cc +if ENABLE_XML_RPC +aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc\ + XmlRpcRequestProcessorTest.cc\ + XmlRpcMethodTest.cc +endif # ENABLE_XML_RPC + if HAVE_POSIX_FALLOCATE aria2c_SOURCES += FallocFileAllocationIteratorTest.cc endif # HAVE_POSIX_FALLOCATE diff --git a/test/Makefile.in b/test/Makefile.in index 3a503303..becc0c55 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -34,14 +34,18 @@ host_triplet = @host@ target_triplet = @target@ TESTS = aria2c$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_1) -@HAVE_POSIX_FALLOCATE_TRUE@am__append_1 = FallocFileAllocationIteratorTest.cc -@HAVE_LIBZ_TRUE@am__append_2 = GZipDecoderTest.cc -@HAVE_SQLITE3_TRUE@am__append_3 = Sqlite3MozCookieParserTest.cc -@ENABLE_MESSAGE_DIGEST_TRUE@am__append_4 = MessageDigestHelperTest.cc\ +@ENABLE_XML_RPC_TRUE@am__append_1 = XmlRpcRequestParserControllerTest.cc\ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestProcessorTest.cc\ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethodTest.cc + +@HAVE_POSIX_FALLOCATE_TRUE@am__append_2 = FallocFileAllocationIteratorTest.cc +@HAVE_LIBZ_TRUE@am__append_3 = GZipDecoderTest.cc +@HAVE_SQLITE3_TRUE@am__append_4 = Sqlite3MozCookieParserTest.cc +@ENABLE_MESSAGE_DIGEST_TRUE@am__append_5 = MessageDigestHelperTest.cc\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.cc\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.cc -@ENABLE_BITTORRENT_TRUE@am__append_5 = BtAllowedFastMessageTest.cc\ +@ENABLE_BITTORRENT_TRUE@am__append_6 = BtAllowedFastMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtCancelMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtChokeMessageTest.cc\ @@ -127,7 +131,7 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_BITTORRENT_TRUE@ MockExtensionMessageFactory.h\ @ENABLE_BITTORRENT_TRUE@ MockPieceStorage.h -@ENABLE_METALINK_TRUE@am__append_6 = MetalinkerTest.cc\ +@ENABLE_METALINK_TRUE@am__append_7 = MetalinkerTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.cc\ @@ -195,9 +199,11 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ SequentialPickerTest.cc RarestPieceSelectorTest.cc \ PieceStatManTest.cc InOrderPieceSelector.h \ LongestSequencePieceSelectorTest.cc a2algoTest.cc \ - bitfieldTest.cc BDETest.cc FallocFileAllocationIteratorTest.cc \ - GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \ - MessageDigestHelperTest.cc \ + bitfieldTest.cc BDETest.cc \ + XmlRpcRequestParserControllerTest.cc \ + XmlRpcRequestProcessorTest.cc XmlRpcMethodTest.cc \ + FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \ + Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ BtBitfieldMessageTest.cc BtCancelMessageTest.cc \ @@ -245,15 +251,18 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ Metalink2RequestGroupTest.cc \ MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \ MetalinkParserControllerTest.cc MetalinkProcessorTest.cc -@HAVE_POSIX_FALLOCATE_TRUE@am__objects_1 = FallocFileAllocationIteratorTest.$(OBJEXT) -@HAVE_LIBZ_TRUE@am__objects_2 = GZipDecoderTest.$(OBJEXT) -@HAVE_SQLITE3_TRUE@am__objects_3 = \ +@ENABLE_XML_RPC_TRUE@am__objects_1 = XmlRpcRequestParserControllerTest.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcRequestProcessorTest.$(OBJEXT) \ +@ENABLE_XML_RPC_TRUE@ XmlRpcMethodTest.$(OBJEXT) +@HAVE_POSIX_FALLOCATE_TRUE@am__objects_2 = FallocFileAllocationIteratorTest.$(OBJEXT) +@HAVE_LIBZ_TRUE@am__objects_3 = GZipDecoderTest.$(OBJEXT) +@HAVE_SQLITE3_TRUE@am__objects_4 = \ @HAVE_SQLITE3_TRUE@ Sqlite3MozCookieParserTest.$(OBJEXT) -@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_4 = \ +@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_5 = \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelperTest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.$(OBJEXT) -@ENABLE_BITTORRENT_TRUE@am__objects_5 = \ +@ENABLE_BITTORRENT_TRUE@am__objects_6 = \ @ENABLE_BITTORRENT_TRUE@ BtAllowedFastMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtCancelMessageTest.$(OBJEXT) \ @@ -321,7 +330,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ @ENABLE_BITTORRENT_TRUE@ ARC4Test.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTUtilTest.$(OBJEXT) -@ENABLE_METALINK_TRUE@am__objects_6 = MetalinkerTest.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@am__objects_7 = MetalinkerTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \ @@ -368,7 +377,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \ LongestSequencePieceSelectorTest.$(OBJEXT) \ a2algoTest.$(OBJEXT) bitfieldTest.$(OBJEXT) BDETest.$(OBJEXT) \ $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) $(am__objects_5) $(am__objects_6) + $(am__objects_4) $(am__objects_5) $(am__objects_6) \ + $(am__objects_7) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a ../src/download_helper.o \ @@ -597,7 +607,7 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \ LongestSequencePieceSelectorTest.cc a2algoTest.cc \ bitfieldTest.cc BDETest.cc $(am__append_1) $(am__append_2) \ $(am__append_3) $(am__append_4) $(am__append_5) \ - $(am__append_6) + $(am__append_6) $(am__append_7) #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} @@ -833,6 +843,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParserTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XORCloserTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserControllerTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestProcessorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2algoTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array_funTest.Po@am__quote@ diff --git a/test/XmlRpcMethodTest.cc b/test/XmlRpcMethodTest.cc new file mode 100644 index 00000000..8d7afd88 --- /dev/null +++ b/test/XmlRpcMethodTest.cc @@ -0,0 +1,65 @@ +#include "XmlRpcMethod.h" + +#include + +#include "DownloadEngine.h" +#include "SelectEventPoll.h" +#include "Option.h" +#include "RequestGroupMan.h" +#include "ServerStatMan.h" +#include "RequestGroup.h" +#include "XmlRpcMethodImpl.h" +#include "BDE.h" +#include "OptionParser.h" +#include "OptionHandler.h" +#include "XmlRpcRequest.h" + +namespace aria2 { + +namespace xmlrpc { + +class XmlRpcMethodTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(XmlRpcMethodTest); + CPPUNIT_TEST(testAddURI); + CPPUNIT_TEST_SUITE_END(); +private: + SharedHandle _e; + SharedHandle