XmlRpcMethodImpl.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2009 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "XmlRpcMethodImpl.h"
  36. #include <cassert>
  37. #include <algorithm>
  38. #include "Logger.h"
  39. #include "BDE.h"
  40. #include "DlAbortEx.h"
  41. #include "Option.h"
  42. #include "OptionParser.h"
  43. #include "OptionHandler.h"
  44. #include "DownloadEngine.h"
  45. #include "RequestGroup.h"
  46. #include "download_helper.h"
  47. #include "Util.h"
  48. #include "RequestGroupMan.h"
  49. #include "StringFormat.h"
  50. #include "XmlRpcRequest.h"
  51. #include "PieceStorage.h"
  52. #include "DownloadContext.h"
  53. #include "DiskAdaptor.h"
  54. #include "FileEntry.h"
  55. #include "BtProgressInfoFile.h"
  56. #include "prefs.h"
  57. #include "message.h"
  58. #ifdef ENABLE_BITTORRENT
  59. # include "bittorrent_helper.h"
  60. # include "BtRegistry.h"
  61. # include "PeerStorage.h"
  62. # include "Peer.h"
  63. # include "BtRuntime.h"
  64. # include "BtAnnounce.h"
  65. #endif // ENABLE_BITTORRENT
  66. namespace aria2 {
  67. namespace xmlrpc {
  68. static const BDE BDE_TRUE = BDE("true");
  69. static const BDE BDE_FALSE = BDE("false");
  70. static const BDE BDE_OK = BDE("OK");
  71. static const BDE BDE_ACTIVE = BDE("active");
  72. static const BDE BDE_WAITING = BDE("waiting");
  73. static const BDE BDE_REMOVED = BDE("removed");
  74. static const BDE BDE_ERROR = BDE("error");
  75. static const BDE BDE_COMPLETE = BDE("complete");
  76. static BDE createGIDResponse(int32_t gid)
  77. {
  78. return BDE(Util::itos(gid));
  79. }
  80. static BDE addRequestGroup(const SharedHandle<RequestGroup>& group,
  81. DownloadEngine* e,
  82. bool posGiven, int pos)
  83. {
  84. if(posGiven) {
  85. e->_requestGroupMan->insertReservedGroup(pos, group);
  86. } else {
  87. e->_requestGroupMan->addReservedGroup(group);
  88. }
  89. return createGIDResponse(group->getGID());
  90. }
  91. static bool hasDictParam(const BDE& params, size_t index)
  92. {
  93. return params.size() > index && params[index].isDict();
  94. }
  95. static void getPosParam(const BDE& params, size_t posParamIndex,
  96. bool& posGiven, size_t& pos)
  97. {
  98. if(params.size() > posParamIndex && params[posParamIndex].isInteger()) {
  99. if(params[posParamIndex].i() >= 0) {
  100. pos = params[posParamIndex].i();
  101. posGiven = true;
  102. } else {
  103. throw DL_ABORT_EX("Position must be greater than or equal to 0.");
  104. }
  105. } else {
  106. posGiven = false;
  107. }
  108. }
  109. BDE AddUriXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  110. {
  111. const BDE& params = req._params;
  112. assert(params.isList());
  113. if(params.empty() || !params[0].isList() || params[0].empty()) {
  114. throw DL_ABORT_EX("URI is not provided.");
  115. }
  116. std::deque<std::string> uris;
  117. for(BDE::List::const_iterator i = params[0].listBegin();
  118. i != params[0].listEnd(); ++i) {
  119. if((*i).isString()) {
  120. uris.push_back((*i).s());
  121. }
  122. }
  123. SharedHandle<Option> requestOption(new Option(*e->option));
  124. if(hasDictParam(params, 1)) {
  125. gatherRequestOption(requestOption, params[1]);
  126. }
  127. size_t pos = 0;
  128. bool posGiven = false;
  129. getPosParam(params, 2, posGiven, pos);
  130. std::deque<SharedHandle<RequestGroup> > result;
  131. createRequestGroupForUri(result, requestOption, uris,
  132. /* ignoreForceSeq = */ true,
  133. /* ignoreNonURI = */ true);
  134. if(!result.empty()) {
  135. return addRequestGroup(result.front(), e, posGiven, pos);
  136. } else {
  137. throw DL_ABORT_EX("No URI to download.");
  138. }
  139. }
  140. #ifdef ENABLE_BITTORRENT
  141. BDE AddTorrentXmlRpcMethod::process
  142. (const XmlRpcRequest& req, DownloadEngine* e)
  143. {
  144. const BDE& params = req._params;
  145. assert(params.isList());
  146. if(params.empty() || !params[0].isString()) {
  147. throw DL_ABORT_EX("Torrent data is not provided.");
  148. }
  149. std::deque<std::string> uris;
  150. if(params.size() > 1 && params[1].isList()) {
  151. for(BDE::List::const_iterator i = params[1].listBegin();
  152. i != params[1].listEnd(); ++i) {
  153. if((*i).isString()) {
  154. uris.push_back((*i).s());
  155. }
  156. }
  157. }
  158. SharedHandle<Option> requestOption(new Option(*e->option));
  159. if(hasDictParam(params, 2)) {
  160. gatherRequestOption(requestOption, params[2]);
  161. }
  162. size_t pos = 0;
  163. bool posGiven = false;
  164. getPosParam(params, 3, posGiven, pos);
  165. std::deque<SharedHandle<RequestGroup> > result;
  166. createRequestGroupForBitTorrent(result, requestOption,
  167. uris,
  168. params[0].s());
  169. if(!result.empty()) {
  170. return addRequestGroup(result.front(), e, posGiven, pos);
  171. } else {
  172. throw DL_ABORT_EX("No Torrent to download.");
  173. }
  174. }
  175. #endif // ENABLE_BITTORRENT
  176. #ifdef ENABLE_METALINK
  177. BDE AddMetalinkXmlRpcMethod::process
  178. (const XmlRpcRequest& req, DownloadEngine* e)
  179. {
  180. const BDE& params = req._params;
  181. assert(params.isList());
  182. if(params.empty() || !params[0].isString()) {
  183. throw DL_ABORT_EX("Metalink data is not provided.");
  184. }
  185. SharedHandle<Option> requestOption(new Option(*e->option));
  186. if(hasDictParam(params, 1)) {
  187. gatherRequestOption(requestOption, params[1]);
  188. };
  189. size_t pos = 0;
  190. bool posGiven = false;
  191. getPosParam(params, 2, posGiven, pos);
  192. std::deque<SharedHandle<RequestGroup> > result;
  193. createRequestGroupForMetalink(result, requestOption, params[0].s());
  194. if(!result.empty()) {
  195. if(posGiven) {
  196. e->_requestGroupMan->insertReservedGroup(pos, result);
  197. } else {
  198. e->_requestGroupMan->addReservedGroup(result);
  199. }
  200. BDE gids = BDE::list();
  201. for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
  202. result.begin(); i != result.end(); ++i) {
  203. gids << BDE(Util::itos((*i)->getGID()));
  204. }
  205. return gids;
  206. } else {
  207. throw DL_ABORT_EX("No files to download.");
  208. }
  209. }
  210. #endif // ENABLE_METALINK
  211. BDE RemoveXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  212. {
  213. const BDE& params = req._params;
  214. assert(params.isList());
  215. if(params.empty() || !params[0].isString()) {
  216. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  217. }
  218. int32_t gid = Util::parseInt(params[0].s());
  219. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  220. if(group.isNull()) {
  221. group = e->_requestGroupMan->findReservedGroup(gid);
  222. if(group.isNull()) {
  223. throw DL_ABORT_EX
  224. (StringFormat("Active Download not found for GID#%d", gid).str());
  225. }
  226. if(group->isDependencyResolved()) {
  227. e->_requestGroupMan->removeReservedGroup(gid);
  228. } else {
  229. throw DL_ABORT_EX
  230. (StringFormat("GID#%d cannot be removed now", gid).str());
  231. }
  232. } else {
  233. group->setHaltRequested(true, RequestGroup::USER_REQUEST);
  234. }
  235. return createGIDResponse(gid);
  236. }
  237. static void gatherProgressCommon
  238. (BDE& entryDict, const SharedHandle<RequestGroup>& group)
  239. {
  240. entryDict["gid"] = Util::itos(group->getGID());
  241. // This is "filtered" total length if --select-file is used.
  242. entryDict["totalLength"] = Util::uitos(group->getTotalLength());
  243. // This is "filtered" total length if --select-file is used.
  244. entryDict["completedLength"] = Util::uitos(group->getCompletedLength());
  245. TransferStat stat = group->calculateStat();
  246. entryDict["downloadSpeed"] = Util::uitos(stat.getDownloadSpeed());
  247. entryDict["uploadSpeed"] = Util::uitos(stat.getUploadSpeed());
  248. entryDict["uploadLength"] = Util::uitos(stat.getAllTimeUploadLength());
  249. entryDict["connections"] = Util::uitos(group->getNumConnection());
  250. SharedHandle<PieceStorage> ps = group->getPieceStorage();
  251. if(!ps.isNull()) {
  252. if(ps->getBitfieldLength() > 0) {
  253. entryDict["bitfield"] = Util::toHex(ps->getBitfield(),
  254. ps->getBitfieldLength());
  255. }
  256. }
  257. entryDict["pieceLength"] =
  258. Util::uitos(group->getDownloadContext()->getPieceLength());
  259. entryDict["numPieces"] =
  260. Util::uitos(group->getDownloadContext()->getNumPieces());
  261. }
  262. #ifdef ENABLE_BITTORRENT
  263. static void gatherProgressBitTorrent
  264. (BDE& entryDict, const BDE& torrentAttrs, const SharedHandle<BtRegistry>& btreg)
  265. {
  266. const std::string& infoHash = torrentAttrs[bittorrent::INFO_HASH].s();
  267. entryDict["infoHash"] = Util::toHex(infoHash);
  268. SharedHandle<PeerStorage> peerStorage = btreg->get(infoHash)._peerStorage;
  269. assert(!peerStorage.isNull());
  270. std::deque<SharedHandle<Peer> > peers;
  271. peerStorage->getActivePeers(peers);
  272. entryDict["numSeeders"] = countSeeder(peers.begin(), peers.end());
  273. }
  274. static void gatherPeer(BDE& peers, const SharedHandle<PeerStorage>& ps)
  275. {
  276. std::deque<SharedHandle<Peer> > activePeers;
  277. ps->getActivePeers(activePeers);
  278. for(std::deque<SharedHandle<Peer> >::const_iterator i =
  279. activePeers.begin(); i != activePeers.end(); ++i) {
  280. BDE peerEntry = BDE::dict();
  281. peerEntry["peerId"] = Util::torrentUrlencode((*i)->getPeerId(),
  282. PEER_ID_LENGTH);
  283. peerEntry["ip"] = (*i)->ipaddr;
  284. peerEntry["port"] = Util::uitos((*i)->port);
  285. peerEntry["bitfield"] = Util::toHex((*i)->getBitfield(),
  286. (*i)->getBitfieldLength());
  287. peerEntry["amChoking"] = (*i)->amChoking()?BDE_TRUE:BDE_FALSE;
  288. peerEntry["peerChoking"] = (*i)->peerChoking()?BDE_TRUE:BDE_FALSE;
  289. TransferStat stat = ps->getTransferStatFor(*i);
  290. peerEntry["downloadSpeed"] = Util::uitos(stat.getDownloadSpeed());
  291. peerEntry["uploadSpeed"] = Util::uitos(stat.getUploadSpeed());
  292. peerEntry["seeder"] = (*i)->isSeeder()?BDE_TRUE:BDE_FALSE;
  293. peers << peerEntry;
  294. }
  295. }
  296. #endif // ENABLE_BITTORRENT
  297. static void gatherProgress
  298. (BDE& entryDict, const SharedHandle<RequestGroup>& group, DownloadEngine* e)
  299. {
  300. gatherProgressCommon(entryDict, group);
  301. #ifdef ENABLE_BITTORRENT
  302. if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
  303. const BDE& torrentAttrs =
  304. group->getDownloadContext()->getAttribute(bittorrent::BITTORRENT);
  305. SharedHandle<BtRegistry> btreg = e->getBtRegistry();
  306. gatherProgressBitTorrent(entryDict, torrentAttrs, btreg);
  307. }
  308. #endif // ENABLE_BITTORRENT
  309. }
  310. static void gatherStoppedDownload
  311. (BDE& entryDict, const SharedHandle<DownloadResult>& ds)
  312. {
  313. entryDict["gid"] = Util::itos(ds->gid);
  314. if(ds->result == downloadresultcode::IN_PROGRESS) {
  315. entryDict["status"] = BDE_REMOVED;
  316. } else if(ds->result == downloadresultcode::FINISHED) {
  317. entryDict["status"] = BDE_COMPLETE;
  318. } else {
  319. entryDict["status"] = BDE_ERROR;
  320. }
  321. }
  322. static
  323. SharedHandle<RequestGroup>
  324. findRequestGroup(const SharedHandle<RequestGroupMan>& rgman, int32_t gid)
  325. {
  326. SharedHandle<RequestGroup> group = rgman->findRequestGroup(gid);
  327. if(group.isNull()) {
  328. group = rgman->findReservedGroup(gid);
  329. }
  330. return group;
  331. }
  332. template<typename InputIterator>
  333. static void createFileEntry(BDE& files, InputIterator first, InputIterator last)
  334. {
  335. size_t index = 1;
  336. for(; first != last; ++first, ++index) {
  337. BDE entry = BDE::dict();
  338. entry["index"] = Util::uitos(index);
  339. entry["path"] = (*first)->getPath();
  340. entry["selected"] = (*first)->isRequested()?BDE_TRUE:BDE_FALSE;
  341. entry["length"] = Util::uitos((*first)->getLength());
  342. files << entry;
  343. }
  344. }
  345. BDE GetFilesXmlRpcMethod::process
  346. (const XmlRpcRequest& req, DownloadEngine* e)
  347. {
  348. const BDE& params = req._params;
  349. assert(params.isList());
  350. if(params.empty() || !params[0].isString()) {
  351. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  352. }
  353. int32_t gid = Util::parseInt(params[0].s());
  354. BDE files = BDE::list();
  355. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  356. if(group.isNull()) {
  357. SharedHandle<DownloadResult> dr =
  358. e->_requestGroupMan->findDownloadResult(gid);
  359. if(dr.isNull()) {
  360. throw DL_ABORT_EX
  361. (StringFormat("No file data is available for GID#%d", gid).str());
  362. } else {
  363. createFileEntry(files, dr->fileEntries.begin(), dr->fileEntries.end());
  364. }
  365. } else {
  366. createFileEntry(files,
  367. group->getDownloadContext()->getFileEntries().begin(),
  368. group->getDownloadContext()->getFileEntries().end());
  369. }
  370. return files;
  371. }
  372. BDE GetUrisXmlRpcMethod::process
  373. (const XmlRpcRequest& req, DownloadEngine* e)
  374. {
  375. const BDE& params = req._params;
  376. assert(params.isList());
  377. if(params.empty() || !params[0].isString()) {
  378. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  379. }
  380. int32_t gid = Util::parseInt(params[0].s());
  381. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  382. if(group.isNull()) {
  383. throw DL_ABORT_EX
  384. (StringFormat("No URI data is available for GID#%d", gid).str());
  385. }
  386. BDE uriList = BDE::list();
  387. std::deque<std::string> uris;
  388. // TODO1.5 getUris should return list of URIs attached to each FileEntry.
  389. // Current implementation just returns first FileEntry's URIs.
  390. group->getDownloadContext()->getFirstFileEntry()->getUris(uris);
  391. for(std::deque<std::string>::const_iterator i = uris.begin(); i != uris.end();
  392. ++i) {
  393. BDE entry = BDE::dict();
  394. entry["uri"] = *i;
  395. uriList << entry;
  396. }
  397. return uriList;
  398. }
  399. #ifdef ENABLE_BITTORRENT
  400. BDE GetPeersXmlRpcMethod::process
  401. (const XmlRpcRequest& req, DownloadEngine* e)
  402. {
  403. const BDE& params = req._params;
  404. assert(params.isList());
  405. if(params.empty() || !params[0].isString()) {
  406. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  407. }
  408. int32_t gid = Util::parseInt(params[0].s());
  409. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  410. if(group.isNull()) {
  411. throw DL_ABORT_EX
  412. (StringFormat("No peer data is available for GID#%d", gid).str());
  413. }
  414. BDE peers = BDE::list();
  415. if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
  416. SharedHandle<BtRegistry> btreg = e->getBtRegistry();
  417. const BDE& torrentAttrs =
  418. group->getDownloadContext()->getAttribute(bittorrent::BITTORRENT);
  419. SharedHandle<PeerStorage> peerStorage =
  420. btreg->get(torrentAttrs[bittorrent::INFO_HASH].s())._peerStorage;
  421. assert(!peerStorage.isNull());
  422. BDE entry = BDE::dict();
  423. gatherPeer(peers, peerStorage);
  424. }
  425. return peers;
  426. }
  427. #endif // ENABLE_BITTORRENT
  428. BDE TellStatusXmlRpcMethod::process
  429. (const XmlRpcRequest& req, DownloadEngine* e)
  430. {
  431. const BDE& params = req._params;
  432. assert(params.isList());
  433. if(params.empty() || !params[0].isString()) {
  434. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  435. }
  436. int32_t gid = Util::parseInt(params[0].s());
  437. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  438. BDE entryDict = BDE::dict();
  439. if(group.isNull()) {
  440. group = e->_requestGroupMan->findReservedGroup(gid);
  441. if(group.isNull()) {
  442. SharedHandle<DownloadResult> ds =
  443. e->_requestGroupMan->findDownloadResult(gid);
  444. if(ds.isNull()) {
  445. throw DL_ABORT_EX
  446. (StringFormat("No such download for GID#%d", gid).str());
  447. }
  448. gatherStoppedDownload(entryDict, ds);
  449. } else {
  450. entryDict["status"] = BDE_WAITING;
  451. gatherProgress(entryDict, group, e);
  452. }
  453. } else {
  454. entryDict["status"] = BDE_ACTIVE;
  455. gatherProgress(entryDict, group, e);
  456. }
  457. return entryDict;
  458. }
  459. BDE TellActiveXmlRpcMethod::process
  460. (const XmlRpcRequest& req, DownloadEngine* e)
  461. {
  462. BDE list = BDE::list();
  463. const std::deque<SharedHandle<RequestGroup> >& groups =
  464. e->_requestGroupMan->getRequestGroups();
  465. for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
  466. groups.begin(); i != groups.end(); ++i) {
  467. BDE entryDict = BDE::dict();
  468. entryDict["status"] = BDE_ACTIVE;
  469. gatherProgress(entryDict, *i, e);
  470. list << entryDict;
  471. }
  472. return list;
  473. }
  474. BDE TellWaitingXmlRpcMethod::process
  475. (const XmlRpcRequest& req, DownloadEngine* e)
  476. {
  477. const BDE& params = req._params;
  478. assert(params.isList());
  479. if(params.size() != 2 ||
  480. !params[0].isInteger() || !params[1].isInteger() ||
  481. params[0].i() < 0 || params[1].i() < 0) {
  482. throw DL_ABORT_EX("Invalid argument. Specify offset and num in integer.");
  483. }
  484. size_t offset = params[0].i();
  485. size_t num = params[1].i();
  486. BDE list = BDE::list();
  487. const std::deque<SharedHandle<RequestGroup> >& waitings =
  488. e->_requestGroupMan->getReservedGroups();
  489. if(waitings.size() <= offset) {
  490. return list;
  491. }
  492. size_t lastDistance;
  493. if(waitings.size() < offset+num) {
  494. lastDistance = waitings.size();
  495. } else {
  496. lastDistance = offset+num;
  497. }
  498. std::deque<SharedHandle<RequestGroup> >::const_iterator first =
  499. waitings.begin();
  500. std::advance(first, offset);
  501. std::deque<SharedHandle<RequestGroup> >::const_iterator last =
  502. waitings.begin();
  503. std::advance(last, lastDistance);
  504. for(; first != last; ++first) {
  505. BDE entryDict = BDE::dict();
  506. entryDict["status"] = BDE_WAITING;
  507. gatherProgress(entryDict, *first, e);
  508. list << entryDict;
  509. }
  510. return list;
  511. }
  512. BDE PurgeDownloadResultXmlRpcMethod::process
  513. (const XmlRpcRequest& req, DownloadEngine* e)
  514. {
  515. e->_requestGroupMan->purgeDownloadResult();
  516. return BDE_OK;
  517. }
  518. BDE ChangeOptionXmlRpcMethod::process
  519. (const XmlRpcRequest& req, DownloadEngine* e)
  520. {
  521. const BDE& params = req._params;
  522. assert(params.isList());
  523. if(params.empty() || !params[0].isString()) {
  524. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  525. }
  526. int32_t gid = Util::parseInt(params[0].s());
  527. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  528. if(group.isNull()) {
  529. throw DL_ABORT_EX
  530. (StringFormat("Cannot change option for GID#%d", gid).str());
  531. }
  532. SharedHandle<Option> option(new Option(*group->getOption().get()));
  533. if(params.size() > 1 && params[1].isDict()) {
  534. gatherChangeableOption(option, params[1]);
  535. }
  536. if(option->defined(PREF_MAX_DOWNLOAD_LIMIT)) {
  537. group->setMaxDownloadSpeedLimit(option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
  538. }
  539. if(option->defined(PREF_MAX_UPLOAD_LIMIT)) {
  540. group->setMaxUploadSpeedLimit(option->getAsInt(PREF_MAX_UPLOAD_LIMIT));
  541. }
  542. return BDE_OK;
  543. }
  544. BDE ChangeGlobalOptionXmlRpcMethod::process
  545. (const XmlRpcRequest& req, DownloadEngine* e)
  546. {
  547. const BDE& params = req._params;
  548. assert(params.isList());
  549. if(params.empty() || !params[0].isDict()) {
  550. return BDE_OK;
  551. }
  552. SharedHandle<Option> option(new Option(*e->option));
  553. gatherChangeableGlobalOption(option, params[0]);
  554. if(option->defined(PREF_MAX_OVERALL_DOWNLOAD_LIMIT)) {
  555. e->_requestGroupMan->setMaxOverallDownloadSpeedLimit
  556. (option->getAsInt(PREF_MAX_OVERALL_DOWNLOAD_LIMIT));
  557. }
  558. if(option->defined(PREF_MAX_OVERALL_UPLOAD_LIMIT)) {
  559. e->_requestGroupMan->setMaxOverallUploadSpeedLimit
  560. (option->getAsInt(PREF_MAX_OVERALL_UPLOAD_LIMIT));
  561. }
  562. if(option->defined(PREF_MAX_CONCURRENT_DOWNLOADS)) {
  563. e->_requestGroupMan->setMaxSimultaneousDownloads
  564. (option->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
  565. }
  566. return BDE_OK;
  567. }
  568. BDE NoSuchMethodXmlRpcMethod::process
  569. (const XmlRpcRequest& req, DownloadEngine* e)
  570. {
  571. throw DL_ABORT_EX
  572. (StringFormat("No such method: %s", req._methodName.c_str()).str());
  573. }
  574. } // namespace xmlrpc
  575. } // namespace aria2