XmlRpcMethodImpl.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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. #include "FeatureConfig.h"
  59. #ifdef ENABLE_BITTORRENT
  60. # include "bittorrent_helper.h"
  61. # include "BtRegistry.h"
  62. # include "PeerStorage.h"
  63. # include "Peer.h"
  64. # include "BtRuntime.h"
  65. # include "BtAnnounce.h"
  66. #endif // ENABLE_BITTORRENT
  67. namespace aria2 {
  68. namespace xmlrpc {
  69. static const BDE BDE_TRUE = BDE("true");
  70. static const BDE BDE_FALSE = BDE("false");
  71. static const BDE BDE_OK = BDE("OK");
  72. static const BDE BDE_ACTIVE = BDE("active");
  73. static const BDE BDE_WAITING = BDE("waiting");
  74. static const BDE BDE_REMOVED = BDE("removed");
  75. static const BDE BDE_ERROR = BDE("error");
  76. static const BDE BDE_COMPLETE = BDE("complete");
  77. static BDE createGIDResponse(int32_t gid)
  78. {
  79. return BDE(util::itos(gid));
  80. }
  81. static BDE addRequestGroup(const SharedHandle<RequestGroup>& group,
  82. DownloadEngine* e,
  83. bool posGiven, int pos)
  84. {
  85. if(posGiven) {
  86. e->_requestGroupMan->insertReservedGroup(pos, group);
  87. } else {
  88. e->_requestGroupMan->addReservedGroup(group);
  89. }
  90. return createGIDResponse(group->getGID());
  91. }
  92. static bool hasDictParam(const BDE& params, size_t index)
  93. {
  94. return params.size() > index && params[index].isDict();
  95. }
  96. static void getPosParam(const BDE& params, size_t posParamIndex,
  97. bool& posGiven, size_t& pos)
  98. {
  99. if(params.size() > posParamIndex && params[posParamIndex].isInteger()) {
  100. if(params[posParamIndex].i() >= 0) {
  101. pos = params[posParamIndex].i();
  102. posGiven = true;
  103. } else {
  104. throw DL_ABORT_EX("Position must be greater than or equal to 0.");
  105. }
  106. } else {
  107. posGiven = false;
  108. }
  109. }
  110. BDE AddUriXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  111. {
  112. const BDE& params = req._params;
  113. assert(params.isList());
  114. if(params.empty() || !params[0].isList() || params[0].empty()) {
  115. throw DL_ABORT_EX("URI is not provided.");
  116. }
  117. std::deque<std::string> uris;
  118. for(BDE::List::const_iterator i = params[0].listBegin();
  119. i != params[0].listEnd(); ++i) {
  120. if((*i).isString()) {
  121. uris.push_back((*i).s());
  122. }
  123. }
  124. SharedHandle<Option> requestOption(new Option(*e->option));
  125. if(hasDictParam(params, 1)) {
  126. gatherRequestOption(requestOption, params[1]);
  127. }
  128. size_t pos = 0;
  129. bool posGiven = false;
  130. getPosParam(params, 2, posGiven, pos);
  131. std::deque<SharedHandle<RequestGroup> > result;
  132. createRequestGroupForUri(result, requestOption, uris,
  133. /* ignoreForceSeq = */ true,
  134. /* ignoreLocalPath = */ true);
  135. if(!result.empty()) {
  136. return addRequestGroup(result.front(), e, posGiven, pos);
  137. } else {
  138. throw DL_ABORT_EX("No URI to download.");
  139. }
  140. }
  141. #ifdef ENABLE_BITTORRENT
  142. BDE AddTorrentXmlRpcMethod::process
  143. (const XmlRpcRequest& req, DownloadEngine* e)
  144. {
  145. const BDE& params = req._params;
  146. assert(params.isList());
  147. if(params.empty() || !params[0].isString()) {
  148. throw DL_ABORT_EX("Torrent data is not provided.");
  149. }
  150. std::deque<std::string> uris;
  151. if(params.size() > 1 && params[1].isList()) {
  152. for(BDE::List::const_iterator i = params[1].listBegin();
  153. i != params[1].listEnd(); ++i) {
  154. if((*i).isString()) {
  155. uris.push_back((*i).s());
  156. }
  157. }
  158. }
  159. SharedHandle<Option> requestOption(new Option(*e->option));
  160. if(hasDictParam(params, 2)) {
  161. gatherRequestOption(requestOption, params[2]);
  162. }
  163. size_t pos = 0;
  164. bool posGiven = false;
  165. getPosParam(params, 3, posGiven, pos);
  166. std::deque<SharedHandle<RequestGroup> > result;
  167. createRequestGroupForBitTorrent(result, requestOption,
  168. uris,
  169. params[0].s());
  170. if(!result.empty()) {
  171. return addRequestGroup(result.front(), e, posGiven, pos);
  172. } else {
  173. throw DL_ABORT_EX("No Torrent to download.");
  174. }
  175. }
  176. #endif // ENABLE_BITTORRENT
  177. #ifdef ENABLE_METALINK
  178. BDE AddMetalinkXmlRpcMethod::process
  179. (const XmlRpcRequest& req, DownloadEngine* e)
  180. {
  181. const BDE& params = req._params;
  182. assert(params.isList());
  183. if(params.empty() || !params[0].isString()) {
  184. throw DL_ABORT_EX("Metalink data is not provided.");
  185. }
  186. SharedHandle<Option> requestOption(new Option(*e->option));
  187. if(hasDictParam(params, 1)) {
  188. gatherRequestOption(requestOption, params[1]);
  189. };
  190. size_t pos = 0;
  191. bool posGiven = false;
  192. getPosParam(params, 2, posGiven, pos);
  193. std::deque<SharedHandle<RequestGroup> > result;
  194. createRequestGroupForMetalink(result, requestOption, params[0].s());
  195. if(!result.empty()) {
  196. if(posGiven) {
  197. e->_requestGroupMan->insertReservedGroup(pos, result);
  198. } else {
  199. e->_requestGroupMan->addReservedGroup(result);
  200. }
  201. BDE gids = BDE::list();
  202. for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
  203. result.begin(); i != result.end(); ++i) {
  204. gids << BDE(util::itos((*i)->getGID()));
  205. }
  206. return gids;
  207. } else {
  208. throw DL_ABORT_EX("No files to download.");
  209. }
  210. }
  211. #endif // ENABLE_METALINK
  212. BDE RemoveXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  213. {
  214. const BDE& params = req._params;
  215. assert(params.isList());
  216. if(params.empty() || !params[0].isString()) {
  217. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  218. }
  219. int32_t gid = util::parseInt(params[0].s());
  220. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  221. if(group.isNull()) {
  222. group = e->_requestGroupMan->findReservedGroup(gid);
  223. if(group.isNull()) {
  224. throw DL_ABORT_EX
  225. (StringFormat("Active Download not found for GID#%d", gid).str());
  226. }
  227. if(group->isDependencyResolved()) {
  228. e->_requestGroupMan->removeReservedGroup(gid);
  229. } else {
  230. throw DL_ABORT_EX
  231. (StringFormat("GID#%d cannot be removed now", gid).str());
  232. }
  233. } else {
  234. group->setHaltRequested(true, RequestGroup::USER_REQUEST);
  235. }
  236. return createGIDResponse(gid);
  237. }
  238. static void gatherProgressCommon
  239. (BDE& entryDict, const SharedHandle<RequestGroup>& group)
  240. {
  241. entryDict["gid"] = util::itos(group->getGID());
  242. // This is "filtered" total length if --select-file is used.
  243. entryDict["totalLength"] = util::uitos(group->getTotalLength());
  244. // This is "filtered" total length if --select-file is used.
  245. entryDict["completedLength"] = util::uitos(group->getCompletedLength());
  246. TransferStat stat = group->calculateStat();
  247. entryDict["downloadSpeed"] = util::uitos(stat.getDownloadSpeed());
  248. entryDict["uploadSpeed"] = util::uitos(stat.getUploadSpeed());
  249. entryDict["uploadLength"] = util::uitos(stat.getAllTimeUploadLength());
  250. entryDict["connections"] = util::uitos(group->getNumConnection());
  251. SharedHandle<PieceStorage> ps = group->getPieceStorage();
  252. if(!ps.isNull()) {
  253. if(ps->getBitfieldLength() > 0) {
  254. entryDict["bitfield"] = util::toHex(ps->getBitfield(),
  255. ps->getBitfieldLength());
  256. }
  257. }
  258. entryDict["pieceLength"] =
  259. util::uitos(group->getDownloadContext()->getPieceLength());
  260. entryDict["numPieces"] =
  261. util::uitos(group->getDownloadContext()->getNumPieces());
  262. }
  263. #ifdef ENABLE_BITTORRENT
  264. static void gatherProgressBitTorrent
  265. (BDE& entryDict, const BDE& torrentAttrs, const BtObject& btObject)
  266. {
  267. const std::string& infoHash = torrentAttrs[bittorrent::INFO_HASH].s();
  268. entryDict["infoHash"] = util::toHex(infoHash);
  269. if(!btObject.isNull()) {
  270. SharedHandle<PeerStorage> peerStorage = btObject._peerStorage;
  271. assert(!peerStorage.isNull());
  272. std::deque<SharedHandle<Peer> > peers;
  273. peerStorage->getActivePeers(peers);
  274. entryDict["numSeeders"] = countSeeder(peers.begin(), peers.end());
  275. }
  276. }
  277. static void gatherPeer(BDE& peers, const SharedHandle<PeerStorage>& ps)
  278. {
  279. std::deque<SharedHandle<Peer> > activePeers;
  280. ps->getActivePeers(activePeers);
  281. for(std::deque<SharedHandle<Peer> >::const_iterator i =
  282. activePeers.begin(); i != activePeers.end(); ++i) {
  283. BDE peerEntry = BDE::dict();
  284. peerEntry["peerId"] = util::torrentUrlencode((*i)->getPeerId(),
  285. PEER_ID_LENGTH);
  286. peerEntry["ip"] = (*i)->ipaddr;
  287. peerEntry["port"] = util::uitos((*i)->port);
  288. peerEntry["bitfield"] = util::toHex((*i)->getBitfield(),
  289. (*i)->getBitfieldLength());
  290. peerEntry["amChoking"] = (*i)->amChoking()?BDE_TRUE:BDE_FALSE;
  291. peerEntry["peerChoking"] = (*i)->peerChoking()?BDE_TRUE:BDE_FALSE;
  292. TransferStat stat = ps->getTransferStatFor(*i);
  293. peerEntry["downloadSpeed"] = util::uitos(stat.getDownloadSpeed());
  294. peerEntry["uploadSpeed"] = util::uitos(stat.getUploadSpeed());
  295. peerEntry["seeder"] = (*i)->isSeeder()?BDE_TRUE:BDE_FALSE;
  296. peers << peerEntry;
  297. }
  298. }
  299. #endif // ENABLE_BITTORRENT
  300. static void gatherProgress
  301. (BDE& entryDict, const SharedHandle<RequestGroup>& group, DownloadEngine* e)
  302. {
  303. gatherProgressCommon(entryDict, group);
  304. #ifdef ENABLE_BITTORRENT
  305. if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
  306. const BDE& torrentAttrs =
  307. group->getDownloadContext()->getAttribute(bittorrent::BITTORRENT);
  308. BtObject btObject = e->getBtRegistry()->get(group->getGID());
  309. gatherProgressBitTorrent(entryDict, torrentAttrs, btObject);
  310. }
  311. #endif // ENABLE_BITTORRENT
  312. }
  313. static void gatherStoppedDownload
  314. (BDE& entryDict, const SharedHandle<DownloadResult>& ds)
  315. {
  316. entryDict["gid"] = util::itos(ds->gid);
  317. entryDict["errorCode"] = util::itos(static_cast<int>(ds->result));
  318. if(ds->result == downloadresultcode::IN_PROGRESS) {
  319. entryDict["status"] = BDE_REMOVED;
  320. } else if(ds->result == downloadresultcode::FINISHED) {
  321. entryDict["status"] = BDE_COMPLETE;
  322. } else {
  323. entryDict["status"] = BDE_ERROR;
  324. }
  325. }
  326. static
  327. SharedHandle<RequestGroup>
  328. findRequestGroup(const SharedHandle<RequestGroupMan>& rgman, int32_t gid)
  329. {
  330. SharedHandle<RequestGroup> group = rgman->findRequestGroup(gid);
  331. if(group.isNull()) {
  332. group = rgman->findReservedGroup(gid);
  333. }
  334. return group;
  335. }
  336. template<typename InputIterator>
  337. static void createFileEntry(BDE& files, InputIterator first, InputIterator last)
  338. {
  339. size_t index = 1;
  340. for(; first != last; ++first, ++index) {
  341. BDE entry = BDE::dict();
  342. entry["index"] = util::uitos(index);
  343. entry["path"] = (*first)->getPath();
  344. entry["selected"] = (*first)->isRequested()?BDE_TRUE:BDE_FALSE;
  345. entry["length"] = util::uitos((*first)->getLength());
  346. files << entry;
  347. }
  348. }
  349. BDE GetFilesXmlRpcMethod::process
  350. (const XmlRpcRequest& req, DownloadEngine* e)
  351. {
  352. const BDE& params = req._params;
  353. assert(params.isList());
  354. if(params.empty() || !params[0].isString()) {
  355. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  356. }
  357. int32_t gid = util::parseInt(params[0].s());
  358. BDE files = BDE::list();
  359. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  360. if(group.isNull()) {
  361. SharedHandle<DownloadResult> dr =
  362. e->_requestGroupMan->findDownloadResult(gid);
  363. if(dr.isNull()) {
  364. throw DL_ABORT_EX
  365. (StringFormat("No file data is available for GID#%d", gid).str());
  366. } else {
  367. createFileEntry(files, dr->fileEntries.begin(), dr->fileEntries.end());
  368. }
  369. } else {
  370. createFileEntry(files,
  371. group->getDownloadContext()->getFileEntries().begin(),
  372. group->getDownloadContext()->getFileEntries().end());
  373. }
  374. return files;
  375. }
  376. BDE GetUrisXmlRpcMethod::process
  377. (const XmlRpcRequest& req, DownloadEngine* e)
  378. {
  379. const BDE& params = req._params;
  380. assert(params.isList());
  381. if(params.empty() || !params[0].isString()) {
  382. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  383. }
  384. int32_t gid = util::parseInt(params[0].s());
  385. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  386. if(group.isNull()) {
  387. throw DL_ABORT_EX
  388. (StringFormat("No URI data is available for GID#%d", gid).str());
  389. }
  390. BDE uriList = BDE::list();
  391. std::deque<std::string> uris;
  392. // TODO Current implementation just returns first FileEntry's URIs.
  393. if(!group->getDownloadContext()->getFileEntries().empty()) {
  394. group->getDownloadContext()->getFirstFileEntry()->getUris(uris);
  395. for(std::deque<std::string>::const_iterator i = uris.begin();
  396. i != uris.end(); ++i) {
  397. BDE entry = BDE::dict();
  398. entry["uri"] = *i;
  399. uriList << entry;
  400. }
  401. }
  402. return uriList;
  403. }
  404. #ifdef ENABLE_BITTORRENT
  405. BDE GetPeersXmlRpcMethod::process
  406. (const XmlRpcRequest& req, DownloadEngine* e)
  407. {
  408. const BDE& params = req._params;
  409. assert(params.isList());
  410. if(params.empty() || !params[0].isString()) {
  411. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  412. }
  413. int32_t gid = util::parseInt(params[0].s());
  414. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  415. if(group.isNull()) {
  416. throw DL_ABORT_EX
  417. (StringFormat("No peer data is available for GID#%d", gid).str());
  418. }
  419. BDE peers = BDE::list();
  420. BtObject btObject = e->getBtRegistry()->get(group->getGID());
  421. if(!btObject.isNull()) {
  422. assert(!btObject._peerStorage.isNull());
  423. gatherPeer(peers, btObject._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());
  533. if(params.size() > 1 && params[1].isDict()) {
  534. gatherChangeableOption(option, params[1]);
  535. applyChangeableOption(group->getOption().get(), option.get());
  536. if(option->defined(PREF_MAX_DOWNLOAD_LIMIT)) {
  537. group->setMaxDownloadSpeedLimit
  538. (option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
  539. }
  540. if(option->defined(PREF_MAX_UPLOAD_LIMIT)) {
  541. group->setMaxUploadSpeedLimit(option->getAsInt(PREF_MAX_UPLOAD_LIMIT));
  542. }
  543. #ifdef ENABLE_BITTORRENT
  544. BtObject btObject = e->getBtRegistry()->get(group->getGID());
  545. if(!btObject.isNull()) {
  546. if(option->defined(PREF_BT_MAX_PEERS)) {
  547. btObject._btRuntime->setMaxPeers(option->getAsInt(PREF_BT_MAX_PEERS));
  548. }
  549. }
  550. #endif // ENABLE_BITTORRENT
  551. }
  552. return BDE_OK;
  553. }
  554. BDE ChangeGlobalOptionXmlRpcMethod::process
  555. (const XmlRpcRequest& req, DownloadEngine* e)
  556. {
  557. const BDE& params = req._params;
  558. assert(params.isList());
  559. if(params.empty() || !params[0].isDict()) {
  560. return BDE_OK;
  561. }
  562. SharedHandle<Option> option(new Option());
  563. gatherChangeableGlobalOption(option, params[0]);
  564. applyChangeableGlobalOption(e->option, option.get());
  565. if(option->defined(PREF_MAX_OVERALL_DOWNLOAD_LIMIT)) {
  566. e->_requestGroupMan->setMaxOverallDownloadSpeedLimit
  567. (option->getAsInt(PREF_MAX_OVERALL_DOWNLOAD_LIMIT));
  568. }
  569. if(option->defined(PREF_MAX_OVERALL_UPLOAD_LIMIT)) {
  570. e->_requestGroupMan->setMaxOverallUploadSpeedLimit
  571. (option->getAsInt(PREF_MAX_OVERALL_UPLOAD_LIMIT));
  572. }
  573. if(option->defined(PREF_MAX_CONCURRENT_DOWNLOADS)) {
  574. e->_requestGroupMan->setMaxSimultaneousDownloads
  575. (option->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
  576. }
  577. return BDE_OK;
  578. }
  579. BDE GetVersionXmlRpcMethod::process
  580. (const XmlRpcRequest& req, DownloadEngine* e)
  581. {
  582. BDE result = BDE::dict();
  583. result["version"] = std::string(PACKAGE_VERSION);
  584. BDE featureList = BDE::list();
  585. const FeatureMap& features = FeatureConfig::getInstance()->getFeatures();
  586. for(FeatureMap::const_iterator i = features.begin(); i != features.end();++i){
  587. if((*i).second) {
  588. featureList << (*i).first;
  589. }
  590. }
  591. result["enabledFeatures"] = featureList;
  592. return result;
  593. }
  594. BDE NoSuchMethodXmlRpcMethod::process
  595. (const XmlRpcRequest& req, DownloadEngine* e)
  596. {
  597. throw DL_ABORT_EX
  598. (StringFormat("No such method: %s", req._methodName.c_str()).str());
  599. }
  600. } // namespace xmlrpc
  601. } // namespace aria2