diff --git a/AUTHORS b/AUTHORS index 43ee47d4..f6cc2425 100644 --- a/AUTHORS +++ b/AUTHORS @@ -36,5 +36,6 @@ luokar mozillazg multisnow oliviercommelarbre +Sonny Piers [1] https://gist.github.com/tatsuhiro-t/deaffeb064652104ad11 diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index 0e2e98ba..b7808dd3 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -103,7 +103,7 @@ HTTP/FTP/SFTP Options See also `ENVIRONMENT`_ section. .. note:: - + If user and password are embedded in proxy URI and they are also specified by *--{http,https,ftp,all}-proxy-{user,passwd}* options, those specified later override prior options. For example, if you specified @@ -209,7 +209,7 @@ HTTP/FTP/SFTP Options Disables netrc support. netrc support is enabled by default. .. note:: - + netrc file is only read at the startup if :option:`--no-netrc <-n>` is ``false``. So if :option:`--no-netrc <-n>` is ``true`` at the startup, @@ -305,7 +305,7 @@ HTTP/FTP/SFTP Options Default: ``5`` .. note:: - + Some Metalinks regulate the number of servers to connect. aria2 strictly respects them. This means that if Metalink defines the ``maxconnections`` attribute lower than N, then aria2 uses the @@ -417,7 +417,7 @@ HTTP Specific Options ``Content-Encoding: deflate``. Default: ``false`` .. note:: - + Some server responds with ``Content-Encoding: gzip`` for files which itself is gzipped file. aria2 inflates them anyway because of the response header. @@ -500,7 +500,7 @@ HTTP Specific Options Default: ``false`` .. note:: - + In performance perspective, there is usually no advantage to enable this option. @@ -747,7 +747,7 @@ BitTorrent Specific Options If ``true`` is given, aria2 doesn't accept and establish connection with legacy BitTorrent handshake(\\19BitTorrent protocol). Thus aria2 always uses Obfuscation handshake. - Default: ``false`` + Default: ``false`` .. option:: --bt-request-peer-speed-limit= @@ -937,7 +937,7 @@ BitTorrent Specific Options Specify seeding time in minutes. Also see the :option:`--seed-ratio` option. .. note:: - + Specifying :option:`--seed-time=0 <--seed-time>` disables seeding after download completed. .. option:: -T, --torrent-file= @@ -994,7 +994,7 @@ Metalink Specific Options The possible values are ``http``, ``https``, ``ftp`` and ``none``. Specify ``none`` to disable this feature. Default: ``none`` - + .. option:: --metalink-enable-unique-protocol[=true|false] If ``true`` is given and several protocols are available for a mirror in a @@ -1489,7 +1489,7 @@ Advanced Options Default: ``1M`` .. note:: - + The possible use case of :option:`--piece-length` option is change the request range in one HTTP pipelined request. To enable HTTP pipelining use @@ -1631,7 +1631,7 @@ Advanced Options Truncate console readout to fit in a single line. Default: ``true`` - + .. option:: -v, --version Print the version number, copyright and the configuration information and @@ -1883,7 +1883,7 @@ aria2 recognizes the following environment variables. The command-line option :option:`--all-proxy` overrides this value. .. note:: - + Although aria2 accepts ``ftp://`` and ``https://`` scheme in proxy URI, it simply assumes that ``http://`` is specified and does not change its behavior based on the specified scheme. @@ -2111,7 +2111,7 @@ of URIs. These optional lines must start with white space(s). * :option:`uri-selector <--uri-selector>` * :option:`use-head <--use-head>` * :option:`user-agent <-U>` - + These options have exactly same meaning of the ones in the command-line options, but it just applies to the URIs it belongs to. Please note that for options in input file ``--`` prefix must be @@ -2262,9 +2262,8 @@ to provide the token as the first parameter as described above. interface. Therefore it is recommended to prefer Batch or `system.multicall` requests when appropriate. - `system.listMethods` can be executed without token. Since it just - returns the all available methods, and does not alter anything, it - is safe without secret token. + `system.listMethods` and `system.listNotifications` can be executed without token. Since they just + return available methods/notifications, they do not alter anything, they're safe without secret token. Methods ~~~~~~~ @@ -3478,9 +3477,9 @@ For information on the *secret* parameter, see :ref:`rpc_auth`. .. function:: system.listMethods() - This method returns the all available RPC methods in an array of + This method returns all the available RPC methods in an array of string. Unlike other methods, this method does not require secret - token. This is safe because this method jsut returns the available + token. This is safe because this method just returns the available method names. **JSON-RPC Example** @@ -3506,6 +3505,36 @@ For information on the *secret* parameter, see :ref:`rpc_auth`. >>> s.system.listMethods() ['aria2.addUri', 'aria2.addTorrent', ... +.. function:: system.listNotifications() + + This method returns all the available RPC notifications in an array of + string. Unlike other methods, this method does not require secret + token. This is safe because this method just returns the available + notifications names. + + **JSON-RPC Example** + :: + + >>> import urllib2, json + >>> from pprint import pprint + >>> jsonreq = json.dumps({'jsonrpc':'2.0', 'id':'qwer', + ... 'method':'system.listNotifications'}) + >>> c = urllib2.urlopen('http://localhost:6800/jsonrpc', jsonreq) + >>> pprint(json.loads(c.read())) + {u'id': u'qwer', + u'jsonrpc': u'2.0', + u'result': [u'aria2.onDownloadStart', + u'aria2.onDownloadPause', + ... + + **XML-RPC Example** + :: + + >>> import xmlrpclib + >>> s = xmlrpclib.ServerProxy('http://localhost:6800/rpc') + >>> s.system.listNotifications() + ['aria2.onDownloadStart', 'aria2.onDownloadPause', ... + Error Handling ~~~~~~~~~~~~~~ @@ -3665,50 +3694,50 @@ notification method. Following notification methods are defined. This notification will be sent when a download is started. The *event* is of type struct and it contains following keys. The value type is string. - + ``gid`` GID of the download. - + .. function:: aria2.onDownloadPause(event) This notification will be sent when a download is paused. The *event* is the same struct as the *event* argument of :func:`aria2.onDownloadStart` method. - + .. function:: aria2.onDownloadStop(event) This notification will be sent when a download is stopped by the user. The *event* is the same struct as the *event* argument of :func:`aria2.onDownloadStart` method. - + .. function:: aria2.onDownloadComplete(event) - + This notification will be sent when a download is complete. For BitTorrent downloads, this notification is sent when the download is complete and seeding is over. The *event* is the same struct of the - *event* argument of + *event* argument of :func:`aria2.onDownloadStart` method. - + .. function:: aria2.onDownloadError(event) - + This notification will be sent when a download is stopped due to an error. The *event* is the same struct as the *event* argument of :func:`aria2.onDownloadStart` method. - + .. function:: aria2.onBtDownloadComplete(event) - + This notification will be sent when a torrent download is complete but seeding is still going on. The *event* is the same struct as the *event* argument of :func:`aria2.onDownloadStart` method. - + Sample XML-RPC Client Code ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3719,15 +3748,15 @@ prints the RPC response: .. code-block:: ruby #!/usr/bin/env ruby - + require 'xmlrpc/client' require 'pp' - + client=XMLRPC::Client.new2("http://localhost:6800/rpc") - + options={ "dir" => "/downloads" } result=client.call("aria2.addUri", [ "http://localhost/aria2.tar.bz2" ], options) - + pp result @@ -3736,7 +3765,7 @@ xmlrpc.client instead) to interact with aria2:: import xmlrpclib from pprint import pprint - + s = xmlrpclib.ServerProxy("http://localhost:6800/rpc") r = s.aria2.addUri(["http://localhost/aria2.tar.bz2"], {"dir":"/downloads"}) pprint(r) @@ -3870,7 +3899,7 @@ For FTP: $ aria2c --ftp-proxy="http://proxy:8080" "ftp://host/file" .. note:: - + See :option:`--http-proxy`, :option:`--https-proxy`, :option:`--ftp-proxy`, :option:`--all-proxy` and :option:`--no-proxy` for details. You can specify proxy in the environment variables. See `ENVIRONMENT`_ section. @@ -4196,7 +4225,7 @@ Repair a damaged download $ aria2c -V file.metalink .. note:: - + Repairing damaged downloads can be done efficiently when used with BitTorrent or Metalink with chunk checksums. diff --git a/src/RpcMethodFactory.cc b/src/RpcMethodFactory.cc index 2b1ce98c..82579b9e 100644 --- a/src/RpcMethodFactory.cc +++ b/src/RpcMethodFactory.cc @@ -68,11 +68,24 @@ std::vector rpcMethodNames = { "aria2.removeDownloadResult", "aria2.getVersion", "aria2.getSessionInfo", "aria2.shutdown", "aria2.forceShutdown", "aria2.getGlobalStat", "aria2.saveSession", "system.multicall", "system.listMethods", + "system.listNotifications", }; } // namespace const std::vector& allMethodNames() { return rpcMethodNames; } +namespace { +std::vector rpcNotificationsNames = { + "aria2.onDownloadStart", "aria2.onDownloadPause", "aria2.onDownloadStop", + "aria2.onDownloadComplete", "aria2.onDownloadError", + #ifdef ENABLE_BITTORRENT + "aria2.onBtDownloadComplete", + #endif // ENABLE_BITTORRENT +}; +} // namespace + +const std::vector& allNotificationsNames() { return rpcNotificationsNames; } + namespace { std::unique_ptr createMethod(const std::string& methodName) { @@ -220,6 +233,10 @@ std::unique_ptr createMethod(const std::string& methodName) return make_unique(); } + if (methodName == SystemListNotificationsRpcMethod::getMethodName()) { + return make_unique(); + } + return nullptr; } } // namespace diff --git a/src/RpcMethodFactory.h b/src/RpcMethodFactory.h index ebd4a479..e93c1b55 100644 --- a/src/RpcMethodFactory.h +++ b/src/RpcMethodFactory.h @@ -49,6 +49,8 @@ class RpcMethod; const std::vector& allMethodNames(); +const std::vector& allNotificationsNames(); + RpcMethod* getMethod(const std::string& methodName); } // namespace rpc diff --git a/src/RpcMethodImpl.cc b/src/RpcMethodImpl.cc index a1c5770f..d727501c 100644 --- a/src/RpcMethodImpl.cc +++ b/src/RpcMethodImpl.cc @@ -1451,6 +1451,26 @@ RpcResponse SystemListMethodsRpcMethod::execute(RpcRequest req, std::move(req.id)); } +std::unique_ptr +SystemListNotificationsRpcMethod::process(const RpcRequest& req, + DownloadEngine* e) +{ + auto list = List::g(); + for (auto& s : allNotificationsNames()) { + list->append(s); + } + + return std::move(list); +} + +RpcResponse SystemListNotificationsRpcMethod::execute(RpcRequest req, + DownloadEngine* e) +{ + auto r = process(req, e); + return RpcResponse(0, RpcResponse::AUTHORIZED, std::move(r), + std::move(req.id)); +} + std::unique_ptr NoSuchMethodRpcMethod::process(const RpcRequest& req, DownloadEngine* e) { diff --git a/src/RpcMethodImpl.h b/src/RpcMethodImpl.h index 59f86359..a3e4ffeb 100644 --- a/src/RpcMethodImpl.h +++ b/src/RpcMethodImpl.h @@ -537,6 +537,17 @@ public: static const char* getMethodName() { return "system.listMethods"; } }; +class SystemListNotificationsRpcMethod : public RpcMethod { +protected: + virtual std::unique_ptr process(const RpcRequest& req, + DownloadEngine* e) CXX11_OVERRIDE; + +public: + virtual RpcResponse execute(RpcRequest req, DownloadEngine* e) CXX11_OVERRIDE; + + static const char* getMethodName() { return "system.listNotifications"; } +}; + class NoSuchMethodRpcMethod : public RpcMethod { protected: virtual std::unique_ptr process(const RpcRequest& req, diff --git a/test/RpcMethodTest.cc b/test/RpcMethodTest.cc index 1bcac3af..f89afd9b 100644 --- a/test/RpcMethodTest.cc +++ b/test/RpcMethodTest.cc @@ -80,6 +80,7 @@ class RpcMethodTest : public CppUnit::TestFixture { CPPUNIT_TEST(testSystemMulticall); CPPUNIT_TEST(testSystemMulticall_fail); CPPUNIT_TEST(testSystemListMethods); + CPPUNIT_TEST(testSystemListNotifications); CPPUNIT_TEST_SUITE_END(); private: @@ -146,6 +147,7 @@ public: void testSystemMulticall(); void testSystemMulticall_fail(); void testSystemListMethods(); + void testSystemListNotifications(); }; CPPUNIT_TEST_SUITE_REGISTRATION(RpcMethodTest); @@ -1396,6 +1398,24 @@ void RpcMethodTest::testSystemListMethods() } } +void RpcMethodTest::testSystemListNotifications() +{ + SystemListNotificationsRpcMethod m; + auto res = m.execute(createReq("system.listNotifications"), e_.get()); + CPPUNIT_ASSERT_EQUAL(0, res.code); + + const auto resParams = downcast(res.param); + auto& allNames = allNotificationsNames(); + + CPPUNIT_ASSERT_EQUAL(allNames.size(), resParams->size()); + + for (size_t i = 0; i < allNames.size(); ++i) { + const auto s = downcast(resParams->get(i)); + CPPUNIT_ASSERT(s); + CPPUNIT_ASSERT_EQUAL(allNames[i], s->s()); + } +} + } // namespace rpc } // namespace aria2