فهرست منبع

2009-05-08 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	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
Tatsuhiro Tsujikawa 16 سال پیش
والد
کامیت
b57b75f98d

+ 29 - 0
ChangeLog

@@ -1,3 +1,32 @@
+2009-05-08  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	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  <t-tujikawa@users.sourceforge.net>
 
 	Added xml-rpc request parser. The supported value types are:

+ 41 - 3
src/HttpServer.cc

@@ -33,6 +33,9 @@
  */
 /* copyright --> */
 #include "HttpServer.h"
+
+#include <sstream>
+
 #include "HttpHeader.h"
 #include "SocketCore.h"
 #include "HttpHeaderProcessor.h"
@@ -50,7 +53,8 @@ HttpServer::HttpServer(const SharedHandle<SocketCore>& socket,
   _socketBuffer(socket),
   _e(e),
   _headerProcessor(new HttpHeaderProcessor()),
-  _logger(LogFactory::getInstance())
+  _logger(LogFactory::getInstance()),
+  _keepAlive(true)
 {}
 
 HttpServer::~HttpServer() {}
@@ -77,14 +81,48 @@ SharedHandle<HttpHeader> 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<uint64_t>(_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()) {

+ 15 - 1
src/HttpServer.h

@@ -38,6 +38,7 @@
 #include "common.h"
 
 #include <string>
+#include <sstream>
 
 #include "SharedHandle.h"
 #include "SocketBuffer.h"
@@ -58,6 +59,9 @@ private:
   SharedHandle<HttpHeaderProcessor> _headerProcessor;
   Logger* _logger;
   SharedHandle<HttpHeader> _lastRequestHeader;
+  uint64_t _lastContentLength;
+  std::stringstream _lastBody;
+  bool _keepAlive;
 public:
   HttpServer(const SharedHandle<SocketCore>& socket, DownloadEngine* e);
 
@@ -65,13 +69,23 @@ public:
 
   SharedHandle<HttpHeader> 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

+ 122 - 0
src/HttpServerBodyCommand.cc

@@ -0,0 +1,122 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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 "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>& httpServer,
+ DownloadEngine* e,
+ const SharedHandle<SocketCore>& 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<xmlrpc::XmlRpcMethod> 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

+ 67 - 0
src/HttpServerBodyCommand.h

@@ -0,0 +1,67 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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_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<SocketCore> _socket;
+  SharedHandle<HttpServer> _httpServer;
+  Time _timeout;
+public:
+  HttpServerBodyCommand(int32_t cuid,
+			const SharedHandle<HttpServer>& httpServer,
+			DownloadEngine* e,
+			const SharedHandle<SocketCore>& socket);
+
+  virtual ~HttpServerBodyCommand();
+  
+  virtual bool execute();
+};
+
+} // namespace aria2 
+
+#endif // _D_HTTP_SERVER_BODY_COMMAND_H_

+ 4 - 4
src/HttpServerCommand.cc

@@ -36,7 +36,7 @@
 
 #include <sstream>
 #include <algorithm>
-#include <iostream>
+#include <ostream>
 #include <iomanip>
 
 #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);

+ 5 - 5
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)) {

+ 26 - 4
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

+ 103 - 55
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@

+ 12 - 0
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::_optionParser;
+
+SharedHandle<OptionParser> OptionParser::getInstance()
+{
+  if(_optionParser.isNull()) {
+    _optionParser.reset(new OptionParser());
+    _optionParser->setOptionHandlers(OptionHandlerFactory::createOptionHandlers());
+  }
+  return _optionParser;
+}
+
 } // namespace aria2

+ 4 - 0
src/OptionParser.h

@@ -56,6 +56,8 @@ private:
 
   SharedHandle<OptionHandler>
   getOptionHandlerByName(const std::string& optName);
+
+  static SharedHandle<OptionParser> _optionParser;
 public:
   OptionParser();
 
@@ -92,6 +94,8 @@ public:
   SharedHandle<OptionHandler> findByShortName(char shortName) const;
 
   const std::deque<SharedHandle<OptionHandler> >& getOptionHandlers() const;
+
+  static SharedHandle<OptionParser> getInstance();
 };
 
 typedef SharedHandle<OptionParser> OptionParserHandle;

+ 6 - 0
src/RequestGroupMan.cc

@@ -130,6 +130,12 @@ RequestGroupMan::getRequestGroups() const
   return _requestGroups;
 }
 
+const std::deque<SharedHandle<RequestGroup> >&
+RequestGroupMan::getReservedGroups() const
+{
+  return _reservedGroups;
+}
+
 class ProcessStoppedRequestGroup {
 private:
   DownloadEngine* _e;

+ 2 - 0
src/RequestGroupMan.h

@@ -112,6 +112,8 @@ public:
   
   const std::deque<SharedHandle<RequestGroup> >& getRequestGroups() const;
 
+  const std::deque<SharedHandle<RequestGroup> >& getReservedGroups() const;
+
   void showDownloadResults(std::ostream& o) const;
 
   bool isSameFileBeingDownloaded(RequestGroup* requestGroup) const;

+ 160 - 0
src/XmlRpcMethod.cc

@@ -0,0 +1,160 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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 "XmlRpcMethod.h"
+
+#include <cassert>
+#include <sstream>
+
+#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<typename InputIterator>
+static void encodeArray
+(InputIterator first, InputIterator last, std::ostream& o)
+{
+  o << "<array>" << "<data>";
+  for(; first != last; ++first) {
+    encodeValue(*first, o);
+  }
+  o << "</data>" << "</array>";
+}
+
+template<typename InputIterator>
+static void encodeStruct
+(InputIterator first, InputIterator last, std::ostream& o)
+{
+  o << "<struct>";
+  for(; first != last; ++first) {
+    o << "<member>"
+      << "<name>" << (*first).first << "</name>";
+    encodeValue((*first).second, o);
+    o << "</member>";
+  }
+  o << "</struct>";
+}
+
+static void encodeValue(const BDE& value, std::ostream& o)
+{
+  o << "<value>";
+  if(value.isString()) {
+    o << "<string>" << value.s() << "</string>";
+  } else if(value.isList()) {
+    encodeArray(value.listBegin(), value.listEnd(), o);
+  } else if(value.isDict()) {
+    encodeStruct(value.dictBegin(), value.dictEnd(), o);
+  }
+  o << "</value>";
+}
+
+template<typename InputIterator>
+static void encodeParams
+(InputIterator first, InputIterator last, std::ostream& o)
+{
+  o << "<params>";
+  for(; first != last; ++first) {
+    o << "<param>";
+    encodeValue(*first, o);
+    o << "</param>";
+  }
+  o << "</params>";
+}
+
+static std::string encodeXml(const BDE& params)
+{
+  assert(params.isList());
+  std::stringstream o;
+  o << "<?xml version=\"1.0\"?>" << "<methodResponse>";
+  encodeParams(params.listBegin(), params.listEnd(), o);
+  o << "</methodResponse>";
+  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<std::string>::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

+ 76 - 0
src/XmlRpcMethod.h

@@ -0,0 +1,76 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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_XML_RPC_METHOD_H_
+#define _D_XML_RPC_METHOD_H_
+
+#include "common.h"
+
+#include <string>
+
+#include "SharedHandle.h"
+
+namespace aria2 {
+
+class DownloadEngine;
+class OptionParser;
+class BDE;
+class Logger;
+class Option;
+
+namespace xmlrpc {
+
+struct XmlRpcRequest;
+
+class XmlRpcMethod {
+protected:
+  SharedHandle<OptionParser> _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_

+ 56 - 0
src/XmlRpcMethodFactory.cc

@@ -0,0 +1,56 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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 "XmlRpcMethodFactory.h"
+#include "XmlRpcMethodImpl.h"
+#include "OptionParser.h"
+#include "OptionHandler.h"
+
+namespace aria2 {
+
+namespace xmlrpc {
+
+SharedHandle<XmlRpcMethod>
+XmlRpcMethodFactory::create(const std::string& methodName)
+{
+  if(methodName == "aria2.addURI") {
+    return SharedHandle<XmlRpcMethod>(new AddURIXmlRpcMethod());
+  } else {
+    return SharedHandle<XmlRpcMethod>(new FailXmlRpcMethod());
+  }
+}
+
+} // namespace xmlrpc
+
+} // namespace aria2

+ 59 - 0
src/XmlRpcMethodFactory.h

@@ -0,0 +1,59 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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_XML_RPC_METHOD_FACTORY_H_
+#define _D_XML_RPC_METHOD_FACTORY_H_
+
+#include "common.h"
+
+#include <string>
+
+#include "SharedHandle.h"
+
+namespace aria2 {
+
+namespace xmlrpc {
+
+class XmlRpcMethod;
+
+class XmlRpcMethodFactory {
+public:
+  static SharedHandle<XmlRpcMethod> create(const std::string& methodName);
+};
+
+} // namespace xmlrpc
+
+} // namespace aria2
+
+#endif // _D_XML_RPC_METHOD_FACTORY_H_

+ 101 - 0
src/XmlRpcMethodImpl.cc

@@ -0,0 +1,101 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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 "XmlRpcMethodImpl.h"
+
+#include <cassert>
+
+#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<std::string> 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<SharedHandle<RequestGroup> > 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

+ 58 - 0
src/XmlRpcMethodImpl.h

@@ -0,0 +1,58 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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_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_

+ 34 - 18
src/download_helper.cc

@@ -38,6 +38,7 @@
 #include <fstream>
 #include <algorithm>
 #include <sstream>
+#include <vector>
 
 #include "RequestGroup.h"
 #include "Option.h"
@@ -62,6 +63,21 @@
 
 namespace aria2 {
 
+const std::vector<std::string>& listRequestOptions()
+{
+  static const std::string REQUEST_OPTIONS[] = {
+    PREF_DIR,
+    PREF_OUT,
+    PREF_SELECT_FILE,
+    PREF_INDEX_OUT
+  };
+  static std::vector<std::string> requestOptions
+    (&REQUEST_OPTIONS[0],
+     &REQUEST_OPTIONS[arrayLength(REQUEST_OPTIONS)]);;
+
+  return requestOptions;
+}
+
 static void unfoldURI
 (std::deque<std::string>& result, const std::deque<std::string>& args)
 {
@@ -246,9 +262,10 @@ static void copyIfndef(Option& dest, const Option& src, const std::string& name)
   }
 }
 
-static void createRequestGroupForUri
+void createRequestGroupForUri
 (std::deque<SharedHandle<RequestGroup> >& result, const Option& op,
- const std::deque<std::string>& uris, const Option& requestOption)
+ const std::deque<std::string>& uris, const Option& requestOption,
+ bool ignoreForceSequential, bool ignoreNonURI)
 {
   std::deque<std::string> 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<typename InputIterator>
 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

+ 10 - 0
src/download_helper.h

@@ -39,6 +39,7 @@
 
 #include <string>
 #include <deque>
+#include <vector>
 
 #include "SharedHandle.h"
 
@@ -47,6 +48,8 @@ namespace aria2 {
 class RequestGroup;
 class Option;
 
+const std::vector<std::string>& 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<SharedHandle<RequestGroup> >& result, const Option& op,
  const std::deque<std::string>& uris);
 
+void createRequestGroupForUri
+(std::deque<SharedHandle<RequestGroup> >& result, const Option& op,
+ const std::deque<std::string>& uris, const Option& requestOption,
+ bool ignoreForceSequential = false, bool ignoreNonURI = false);
+
+void completeRequestOption(Option& requestOption, const Option& option);
+
 } // namespace aria2
 
 #endif // _D_DOWNLOAD_HELPER_H_

+ 6 - 0
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

+ 30 - 17
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@

+ 65 - 0
test/XmlRpcMethodTest.cc

@@ -0,0 +1,65 @@
+#include "XmlRpcMethod.h"
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#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<DownloadEngine> _e;
+  SharedHandle<Option> _option;
+public:
+  void setUp()
+  {
+    _option.reset(new Option());
+    _e.reset(new DownloadEngine(SharedHandle<EventPoll>(new SelectEventPoll())));
+    _e->option = _option.get();
+    _e->_requestGroupMan.reset
+      (new RequestGroupMan(std::deque<SharedHandle<RequestGroup> >(),
+			   1, _option.get()));
+  }
+
+  void tearDown() {}
+
+  void testAddURI();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(XmlRpcMethodTest);
+
+void XmlRpcMethodTest::testAddURI()
+{
+  AddURIXmlRpcMethod m;
+  XmlRpcRequest req("aria2.addURI", BDE::list());
+  req._params << BDE::list();
+  req._params[0] << BDE("http://localhost/");
+  std::string res = m.execute(req, _e.get());
+  const std::deque<SharedHandle<RequestGroup> > rgs =
+    _e->_requestGroupMan->getReservedGroups();
+  CPPUNIT_ASSERT_EQUAL((size_t)1, rgs.size());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/"),
+		       rgs.front()->getRemainingUris().front());
+  CPPUNIT_ASSERT(res.find("OK") != std::string::npos);
+}
+
+} // namespace xmlrpc
+
+} // namespace aria2