XmlRpcMethodImpl.cc 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  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 "LogFactory.h"
  40. #include "BDE.h"
  41. #include "DlAbortEx.h"
  42. #include "Option.h"
  43. #include "OptionParser.h"
  44. #include "OptionHandler.h"
  45. #include "DownloadEngine.h"
  46. #include "RequestGroup.h"
  47. #include "download_helper.h"
  48. #include "util.h"
  49. #include "RequestGroupMan.h"
  50. #include "StringFormat.h"
  51. #include "XmlRpcRequest.h"
  52. #include "PieceStorage.h"
  53. #include "DownloadContext.h"
  54. #include "DiskAdaptor.h"
  55. #include "FileEntry.h"
  56. #include "BtProgressInfoFile.h"
  57. #include "prefs.h"
  58. #include "message.h"
  59. #include "FeatureConfig.h"
  60. #include "array_fun.h"
  61. #include "XmlRpcMethodFactory.h"
  62. #include "XmlRpcResponse.h"
  63. #include "SegmentMan.h"
  64. #include "TimedHaltCommand.h"
  65. #ifdef ENABLE_BITTORRENT
  66. # include "bittorrent_helper.h"
  67. # include "BtRegistry.h"
  68. # include "PeerStorage.h"
  69. # include "Peer.h"
  70. # include "BtRuntime.h"
  71. # include "BtAnnounce.h"
  72. #endif // ENABLE_BITTORRENT
  73. namespace aria2 {
  74. namespace xmlrpc {
  75. namespace {
  76. const BDE BDE_TRUE = BDE("true");
  77. const BDE BDE_FALSE = BDE("false");
  78. const BDE BDE_OK = BDE("OK");
  79. const BDE BDE_ACTIVE = BDE("active");
  80. const BDE BDE_WAITING = BDE("waiting");
  81. const BDE BDE_PAUSED = BDE("paused");
  82. const BDE BDE_REMOVED = BDE("removed");
  83. const BDE BDE_ERROR = BDE("error");
  84. const BDE BDE_COMPLETE = BDE("complete");
  85. const BDE BDE_USED = BDE("used");
  86. const BDE BDE_ZERO = BDE("0");
  87. const std::string KEY_GID = "gid";
  88. const std::string KEY_ERROR_CODE = "errorCode";
  89. const std::string KEY_STATUS = "status";
  90. const std::string KEY_TOTAL_LENGTH = "totalLength";
  91. const std::string KEY_COMPLETED_LENGTH = "completedLength";
  92. const std::string KEY_DOWNLOAD_SPEED = "downloadSpeed";
  93. const std::string KEY_UPLOAD_SPEED = "uploadSpeed";
  94. const std::string KEY_UPLOAD_LENGTH = "uploadLength";
  95. const std::string KEY_CONNECTIONS = "connections";
  96. const std::string KEY_BITFIELD = "bitfield";
  97. const std::string KEY_PIECE_LENGTH = "pieceLength";
  98. const std::string KEY_NUM_PIECES = "numPieces";
  99. const std::string KEY_FOLLOWED_BY = "followedBy";
  100. const std::string KEY_BELONGS_TO = "belongsTo";
  101. const std::string KEY_INFO_HASH = "infoHash";
  102. const std::string KEY_NUM_SEEDERS = "numSeeders";
  103. const std::string KEY_PEER_ID = "peerId";
  104. const std::string KEY_IP = "ip";
  105. const std::string KEY_PORT = "port";
  106. const std::string KEY_AM_CHOKING = "amChoking";
  107. const std::string KEY_PEER_CHOKING = "peerChoking";
  108. const std::string KEY_SEEDER = "seeder";
  109. const std::string KEY_INDEX = "index";
  110. const std::string KEY_PATH = "path";
  111. const std::string KEY_SELECTED = "selected";
  112. const std::string KEY_LENGTH = "length";
  113. const std::string KEY_URI = "uri";
  114. const std::string KEY_CURRENT_URI = "currentUri";
  115. const std::string KEY_VERSION = "version";
  116. const std::string KEY_ENABLED_FEATURES = "enabledFeatures";
  117. const std::string KEY_METHOD_NAME = "methodName";
  118. const std::string KEY_PARAMS = "params";
  119. const std::string KEY_SESSION_ID = "sessionId";
  120. const std::string KEY_FILES = "files";
  121. const std::string KEY_DIR = "dir";
  122. const std::string KEY_URIS = "uris";
  123. const std::string KEY_BITTORRENT = "bittorrent";
  124. const std::string KEY_INFO = "info";
  125. const std::string KEY_NAME = "name";
  126. const std::string KEY_ANNOUNCE_LIST = "announceList";
  127. const std::string KEY_COMMENT = "comment";
  128. const std::string KEY_CREATION_DATE = "creationDate";
  129. const std::string KEY_MODE = "mode";
  130. const std::string KEY_SERVERS = "servers";
  131. }
  132. static BDE createGIDResponse(gid_t gid)
  133. {
  134. return BDE(util::itos(gid));
  135. }
  136. static BDE addRequestGroup(const SharedHandle<RequestGroup>& group,
  137. DownloadEngine* e,
  138. bool posGiven, int pos)
  139. {
  140. if(posGiven) {
  141. e->_requestGroupMan->insertReservedGroup(pos, group);
  142. } else {
  143. e->_requestGroupMan->addReservedGroup(group);
  144. }
  145. return createGIDResponse(group->getGID());
  146. }
  147. static
  148. SharedHandle<RequestGroup>
  149. findRequestGroup(const SharedHandle<RequestGroupMan>& rgman, gid_t gid)
  150. {
  151. SharedHandle<RequestGroup> group = rgman->findRequestGroup(gid);
  152. if(group.isNull()) {
  153. group = rgman->findReservedGroup(gid);
  154. }
  155. return group;
  156. }
  157. static bool hasDictParam(const BDE& params, size_t index)
  158. {
  159. return params.size() > index && params[index].isDict();
  160. }
  161. static void getPosParam(const BDE& params, size_t posParamIndex,
  162. bool& posGiven, size_t& pos)
  163. {
  164. if(params.size() > posParamIndex && params[posParamIndex].isInteger()) {
  165. if(params[posParamIndex].i() >= 0) {
  166. pos = params[posParamIndex].i();
  167. posGiven = true;
  168. } else {
  169. throw DL_ABORT_EX("Position must be greater than or equal to 0.");
  170. }
  171. } else {
  172. posGiven = false;
  173. }
  174. }
  175. template<typename OutputIterator>
  176. static void extractUris(OutputIterator out, const BDE& src)
  177. {
  178. for(BDE::List::const_iterator i = src.listBegin(), eoi = src.listEnd();
  179. i != eoi; ++i) {
  180. if((*i).isString()) {
  181. out++ = (*i).s();
  182. }
  183. }
  184. }
  185. BDE AddUriXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  186. {
  187. const BDE& params = req._params;
  188. assert(params.isList());
  189. if(params.empty() || !params[0].isList() || params[0].empty()) {
  190. throw DL_ABORT_EX("URI is not provided.");
  191. }
  192. std::vector<std::string> uris;
  193. extractUris(std::back_inserter(uris), params[0]);
  194. SharedHandle<Option> requestOption(new Option(*e->option));
  195. if(hasDictParam(params, 1)) {
  196. gatherRequestOption(requestOption, params[1]);
  197. }
  198. size_t pos = 0;
  199. bool posGiven = false;
  200. getPosParam(params, 2, posGiven, pos);
  201. std::vector<SharedHandle<RequestGroup> > result;
  202. createRequestGroupForUri(result, requestOption, uris,
  203. /* ignoreForceSeq = */ true,
  204. /* ignoreLocalPath = */ true);
  205. if(!result.empty()) {
  206. return addRequestGroup(result.front(), e, posGiven, pos);
  207. } else {
  208. throw DL_ABORT_EX("No URI to download.");
  209. }
  210. }
  211. #ifdef ENABLE_BITTORRENT
  212. BDE AddTorrentXmlRpcMethod::process
  213. (const XmlRpcRequest& req, DownloadEngine* e)
  214. {
  215. const BDE& params = req._params;
  216. assert(params.isList());
  217. if(params.empty() || !params[0].isString()) {
  218. throw DL_ABORT_EX("Torrent data is not provided.");
  219. }
  220. std::vector<std::string> uris;
  221. if(params.size() > 1 && params[1].isList()) {
  222. extractUris(std::back_inserter(uris), params[1]);
  223. }
  224. SharedHandle<Option> requestOption(new Option(*e->option));
  225. if(hasDictParam(params, 2)) {
  226. gatherRequestOption(requestOption, params[2]);
  227. }
  228. size_t pos = 0;
  229. bool posGiven = false;
  230. getPosParam(params, 3, posGiven, pos);
  231. std::vector<SharedHandle<RequestGroup> > result;
  232. createRequestGroupForBitTorrent(result, requestOption,
  233. uris,
  234. params[0].s());
  235. if(!result.empty()) {
  236. return addRequestGroup(result.front(), e, posGiven, pos);
  237. } else {
  238. throw DL_ABORT_EX("No Torrent to download.");
  239. }
  240. }
  241. #endif // ENABLE_BITTORRENT
  242. #ifdef ENABLE_METALINK
  243. BDE AddMetalinkXmlRpcMethod::process
  244. (const XmlRpcRequest& req, DownloadEngine* e)
  245. {
  246. const BDE& params = req._params;
  247. assert(params.isList());
  248. if(params.empty() || !params[0].isString()) {
  249. throw DL_ABORT_EX("Metalink data is not provided.");
  250. }
  251. SharedHandle<Option> requestOption(new Option(*e->option));
  252. if(hasDictParam(params, 1)) {
  253. gatherRequestOption(requestOption, params[1]);
  254. };
  255. size_t pos = 0;
  256. bool posGiven = false;
  257. getPosParam(params, 2, posGiven, pos);
  258. std::vector<SharedHandle<RequestGroup> > result;
  259. createRequestGroupForMetalink(result, requestOption, params[0].s());
  260. if(!result.empty()) {
  261. if(posGiven) {
  262. e->_requestGroupMan->insertReservedGroup(pos, result);
  263. } else {
  264. e->_requestGroupMan->addReservedGroup(result);
  265. }
  266. BDE gids = BDE::list();
  267. for(std::vector<SharedHandle<RequestGroup> >::const_iterator i =
  268. result.begin(), eoi = result.end(); i != eoi; ++i) {
  269. gids << BDE(util::itos((*i)->getGID()));
  270. }
  271. return gids;
  272. } else {
  273. throw DL_ABORT_EX("No files to download.");
  274. }
  275. }
  276. #endif // ENABLE_METALINK
  277. static BDE removeDownload
  278. (const XmlRpcRequest& req, DownloadEngine* e, bool forceRemove)
  279. {
  280. const BDE& params = req._params;
  281. assert(params.isList());
  282. if(params.empty() || !params[0].isString()) {
  283. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  284. }
  285. gid_t gid = util::parseLLInt(params[0].s());
  286. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  287. if(group.isNull()) {
  288. group = e->_requestGroupMan->findReservedGroup(gid);
  289. if(group.isNull()) {
  290. throw DL_ABORT_EX
  291. (StringFormat("Active Download not found for GID#%s",
  292. util::itos(gid).c_str()).str());
  293. }
  294. if(group->isDependencyResolved()) {
  295. e->_requestGroupMan->removeReservedGroup(gid);
  296. } else {
  297. throw DL_ABORT_EX
  298. (StringFormat("GID#%s cannot be removed now",
  299. util::itos(gid).c_str()).str());
  300. }
  301. } else {
  302. if(forceRemove) {
  303. group->setForceHaltRequested(true, RequestGroup::USER_REQUEST);
  304. } else {
  305. group->setHaltRequested(true, RequestGroup::USER_REQUEST);
  306. }
  307. }
  308. return createGIDResponse(gid);
  309. }
  310. BDE RemoveXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  311. {
  312. return removeDownload(req, e, false);
  313. }
  314. BDE ForceRemoveXmlRpcMethod::process
  315. (const XmlRpcRequest& req, DownloadEngine* e)
  316. {
  317. return removeDownload(req, e, true);
  318. }
  319. static bool pauseRequestGroup
  320. (const SharedHandle<RequestGroup>& group, bool reserved, bool forcePause)
  321. {
  322. if((reserved && !group->isPauseRequested()) ||
  323. (!reserved &&
  324. !group->isForceHaltRequested() &&
  325. ((forcePause && group->isHaltRequested() && group->isPauseRequested()) ||
  326. (!group->isHaltRequested() && !group->isPauseRequested())))) {
  327. if(!reserved) {
  328. // Call setHaltRequested before setPauseRequested because
  329. // setHaltRequested calls setPauseRequested(false) internally.
  330. if(forcePause) {
  331. group->setForceHaltRequested(true, RequestGroup::NONE);
  332. } else {
  333. group->setHaltRequested(true, RequestGroup::NONE);
  334. }
  335. }
  336. group->setPauseRequested(true);
  337. return true;
  338. } else {
  339. return false;
  340. }
  341. }
  342. static BDE pauseDownload
  343. (const XmlRpcRequest& req, DownloadEngine* e, bool forcePause)
  344. {
  345. const BDE& params = req._params;
  346. assert(params.isList());
  347. if(params.empty() || !params[0].isString()) {
  348. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  349. }
  350. gid_t gid = util::parseLLInt(params[0].s());
  351. bool reserved = false;
  352. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  353. if(group.isNull()) {
  354. reserved = true;
  355. group = e->_requestGroupMan->findReservedGroup(gid);
  356. }
  357. if(!group.isNull() && pauseRequestGroup(group, reserved, forcePause)) {
  358. return createGIDResponse(gid);
  359. } else {
  360. throw DL_ABORT_EX
  361. (StringFormat("GID#%s cannot be paused now",
  362. util::itos(gid).c_str()).str());
  363. }
  364. }
  365. BDE PauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  366. {
  367. return pauseDownload(req, e, false);
  368. }
  369. BDE ForcePauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  370. {
  371. return pauseDownload(req, e, true);
  372. }
  373. template<typename InputIterator>
  374. static void pauseRequestGroups
  375. (InputIterator first, InputIterator last, bool reserved, bool forcePause)
  376. {
  377. for(; first != last; ++first) {
  378. pauseRequestGroup(*first, reserved, forcePause);
  379. }
  380. }
  381. static BDE pauseAllDownloads
  382. (const XmlRpcRequest& req, DownloadEngine* e, bool forcePause)
  383. {
  384. const std::deque<SharedHandle<RequestGroup> >& groups =
  385. e->_requestGroupMan->getRequestGroups();
  386. pauseRequestGroups(groups.begin(), groups.end(), false, forcePause);
  387. const std::deque<SharedHandle<RequestGroup> >& reservedGroups =
  388. e->_requestGroupMan->getReservedGroups();
  389. pauseRequestGroups(reservedGroups.begin(), reservedGroups.end(),
  390. true, forcePause);
  391. return BDE_OK;
  392. }
  393. BDE PauseAllXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  394. {
  395. return pauseAllDownloads(req, e, false);
  396. }
  397. BDE ForcePauseAllXmlRpcMethod::process
  398. (const XmlRpcRequest& req, DownloadEngine* e)
  399. {
  400. return pauseAllDownloads(req, e, true);
  401. }
  402. BDE UnpauseXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  403. {
  404. const BDE& params = req._params;
  405. assert(params.isList());
  406. if(params.empty() || !params[0].isString()) {
  407. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  408. }
  409. gid_t gid = util::parseLLInt(params[0].s());
  410. SharedHandle<RequestGroup> group =e->_requestGroupMan->findReservedGroup(gid);
  411. if(group.isNull() || !group->isPauseRequested()) {
  412. throw DL_ABORT_EX
  413. (StringFormat("GID#%s cannot be unpaused now",
  414. util::itos(gid).c_str()).str());
  415. } else {
  416. group->setPauseRequested(false);
  417. e->_requestGroupMan->requestQueueCheck();
  418. }
  419. return createGIDResponse(gid);
  420. }
  421. BDE UnpauseAllXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  422. {
  423. const std::deque<SharedHandle<RequestGroup> >& groups =
  424. e->_requestGroupMan->getReservedGroups();
  425. std::for_each(groups.begin(), groups.end(),
  426. std::bind2nd(mem_fun_sh(&RequestGroup::setPauseRequested),
  427. false));
  428. e->_requestGroupMan->requestQueueCheck();
  429. return BDE_OK;
  430. }
  431. static void createUriEntry(BDE& uriList, const SharedHandle<FileEntry>& file)
  432. {
  433. {
  434. const std::deque<std::string>& uris = file->getSpentUris();
  435. for(std::deque<std::string>::const_iterator i = uris.begin(),
  436. eoi = uris.end(); i != eoi; ++i) {
  437. BDE entry = BDE::dict();
  438. entry[KEY_URI] = *i;
  439. entry[KEY_STATUS] = BDE_USED;
  440. uriList << entry;
  441. }
  442. }
  443. {
  444. const std::deque<std::string>& uris = file->getRemainingUris();
  445. for(std::deque<std::string>::const_iterator i = uris.begin(),
  446. eoi = uris.end(); i != eoi; ++i) {
  447. BDE entry = BDE::dict();
  448. entry[KEY_URI] = *i;
  449. entry[KEY_STATUS] = BDE_WAITING;
  450. uriList << entry;
  451. }
  452. }
  453. }
  454. template<typename InputIterator>
  455. static void createFileEntry(BDE& files, InputIterator first, InputIterator last)
  456. {
  457. size_t index = 1;
  458. for(; first != last; ++first, ++index) {
  459. BDE entry = BDE::dict();
  460. entry[KEY_INDEX] = util::uitos(index);
  461. entry[KEY_PATH] = (*first)->getPath();
  462. entry[KEY_SELECTED] = (*first)->isRequested()?BDE_TRUE:BDE_FALSE;
  463. entry[KEY_LENGTH] = util::uitos((*first)->getLength());
  464. BDE uriList = BDE::list();
  465. createUriEntry(uriList, *first);
  466. entry[KEY_URIS] = uriList;
  467. files << entry;
  468. }
  469. }
  470. void gatherProgressCommon
  471. (BDE& entryDict, const SharedHandle<RequestGroup>& group)
  472. {
  473. entryDict[KEY_GID] = util::itos(group->getGID());
  474. // This is "filtered" total length if --select-file is used.
  475. entryDict[KEY_TOTAL_LENGTH] = util::uitos(group->getTotalLength());
  476. // This is "filtered" total length if --select-file is used.
  477. entryDict[KEY_COMPLETED_LENGTH] = util::uitos(group->getCompletedLength());
  478. TransferStat stat = group->calculateStat();
  479. entryDict[KEY_DOWNLOAD_SPEED] = util::uitos(stat.getDownloadSpeed());
  480. entryDict[KEY_UPLOAD_SPEED] = util::uitos(stat.getUploadSpeed());
  481. entryDict[KEY_UPLOAD_LENGTH] = util::uitos(stat.getAllTimeUploadLength());
  482. entryDict[KEY_CONNECTIONS] = util::uitos(group->getNumConnection());
  483. SharedHandle<PieceStorage> ps = group->getPieceStorage();
  484. if(!ps.isNull()) {
  485. if(ps->getBitfieldLength() > 0) {
  486. entryDict[KEY_BITFIELD] = util::toHex(ps->getBitfield(),
  487. ps->getBitfieldLength());
  488. }
  489. }
  490. const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
  491. entryDict[KEY_PIECE_LENGTH] = util::uitos(dctx->getPieceLength());
  492. entryDict[KEY_NUM_PIECES] = util::uitos(dctx->getNumPieces());
  493. if(!group->followedBy().empty()) {
  494. BDE list = BDE::list();
  495. // The element is GID.
  496. for(std::vector<gid_t>::const_iterator i = group->followedBy().begin(),
  497. eoi = group->followedBy().end(); i != eoi; ++i) {
  498. list << util::itos(*i);
  499. }
  500. entryDict[KEY_FOLLOWED_BY] = list;
  501. }
  502. if(group->belongsTo()) {
  503. entryDict[KEY_BELONGS_TO] = util::itos(group->belongsTo());
  504. }
  505. BDE files = BDE::list();
  506. createFileEntry
  507. (files, dctx->getFileEntries().begin(), dctx->getFileEntries().end());
  508. entryDict[KEY_FILES] = files;
  509. entryDict[KEY_DIR] = dctx->getDir();
  510. }
  511. #ifdef ENABLE_BITTORRENT
  512. void gatherBitTorrentMetadata(BDE& btDict, const BDE& torrentAttrs)
  513. {
  514. if(torrentAttrs.containsKey(bittorrent::COMMENT)) {
  515. btDict[KEY_COMMENT] = torrentAttrs[bittorrent::COMMENT];
  516. }
  517. if(torrentAttrs.containsKey(bittorrent::CREATION_DATE)) {
  518. btDict[KEY_CREATION_DATE] = torrentAttrs[bittorrent::CREATION_DATE];
  519. }
  520. if(torrentAttrs.containsKey(bittorrent::MODE)) {
  521. btDict[KEY_MODE] = torrentAttrs[bittorrent::MODE];
  522. }
  523. // Copy announceList to avoid modification on entyDict to be
  524. // affected original announceList.
  525. // TODO Would it be good to add copy() method in BDE?
  526. const BDE& announceList = torrentAttrs[bittorrent::ANNOUNCE_LIST];
  527. BDE destAnnounceList = BDE::list();
  528. for(BDE::List::const_iterator l = announceList.listBegin(),
  529. eoi = announceList.listEnd(); l != eoi; ++l) {
  530. BDE destAnnounceTier = BDE::list();
  531. for(BDE::List::const_iterator t = (*l).listBegin(),
  532. eoi2 = (*l).listEnd(); t != eoi2; ++t) {
  533. destAnnounceTier << (*t);
  534. }
  535. destAnnounceList << destAnnounceTier;
  536. }
  537. btDict[KEY_ANNOUNCE_LIST] = destAnnounceList;
  538. if(torrentAttrs.containsKey(bittorrent::METADATA)) {
  539. BDE infoDict = BDE::dict();
  540. infoDict[KEY_NAME] = torrentAttrs[bittorrent::NAME];
  541. btDict[KEY_INFO] = infoDict;
  542. }
  543. }
  544. static void gatherProgressBitTorrent
  545. (BDE& entryDict, const BDE& torrentAttrs, const BtObject& btObject)
  546. {
  547. const std::string& infoHash = torrentAttrs[bittorrent::INFO_HASH].s();
  548. entryDict[KEY_INFO_HASH] = util::toHex(infoHash);
  549. BDE btDict = BDE::dict();
  550. gatherBitTorrentMetadata(btDict, torrentAttrs);
  551. entryDict[KEY_BITTORRENT] = btDict;
  552. if(btObject.isNull()) {
  553. entryDict[KEY_NUM_SEEDERS] = BDE_ZERO;
  554. } else {
  555. SharedHandle<PeerStorage> peerStorage = btObject._peerStorage;
  556. assert(!peerStorage.isNull());
  557. std::vector<SharedHandle<Peer> > peers;
  558. peerStorage->getActivePeers(peers);
  559. entryDict[KEY_NUM_SEEDERS] =
  560. util::uitos(countSeeder(peers.begin(), peers.end()));
  561. }
  562. }
  563. static void gatherPeer(BDE& peers, const SharedHandle<PeerStorage>& ps)
  564. {
  565. std::vector<SharedHandle<Peer> > activePeers;
  566. ps->getActivePeers(activePeers);
  567. for(std::vector<SharedHandle<Peer> >::const_iterator i =
  568. activePeers.begin(), eoi = activePeers.end(); i != eoi; ++i) {
  569. BDE peerEntry = BDE::dict();
  570. peerEntry[KEY_PEER_ID] = util::torrentPercentEncode((*i)->getPeerId(),
  571. PEER_ID_LENGTH);
  572. peerEntry[KEY_IP] = (*i)->ipaddr;
  573. if((*i)->isIncomingPeer()) {
  574. peerEntry[KEY_PORT] = std::string("0");
  575. } else {
  576. peerEntry[KEY_PORT] = util::uitos((*i)->port);
  577. }
  578. peerEntry[KEY_BITFIELD] = util::toHex((*i)->getBitfield(),
  579. (*i)->getBitfieldLength());
  580. peerEntry[KEY_AM_CHOKING] = (*i)->amChoking()?BDE_TRUE:BDE_FALSE;
  581. peerEntry[KEY_PEER_CHOKING] = (*i)->peerChoking()?BDE_TRUE:BDE_FALSE;
  582. TransferStat stat = ps->getTransferStatFor(*i);
  583. peerEntry[KEY_DOWNLOAD_SPEED] = util::uitos(stat.getDownloadSpeed());
  584. peerEntry[KEY_UPLOAD_SPEED] = util::uitos(stat.getUploadSpeed());
  585. peerEntry[KEY_SEEDER] = (*i)->isSeeder()?BDE_TRUE:BDE_FALSE;
  586. peers << peerEntry;
  587. }
  588. }
  589. #endif // ENABLE_BITTORRENT
  590. static void gatherProgress
  591. (BDE& entryDict, const SharedHandle<RequestGroup>& group, DownloadEngine* e)
  592. {
  593. gatherProgressCommon(entryDict, group);
  594. #ifdef ENABLE_BITTORRENT
  595. if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
  596. const BDE& torrentAttrs =
  597. group->getDownloadContext()->getAttribute(bittorrent::BITTORRENT);
  598. BtObject btObject = e->getBtRegistry()->get(group->getGID());
  599. gatherProgressBitTorrent(entryDict, torrentAttrs, btObject);
  600. }
  601. #endif // ENABLE_BITTORRENT
  602. }
  603. void gatherStoppedDownload
  604. (BDE& entryDict, const SharedHandle<DownloadResult>& ds)
  605. {
  606. entryDict[KEY_GID] = util::itos(ds->gid);
  607. entryDict[KEY_ERROR_CODE] = util::itos(static_cast<int>(ds->result));
  608. if(ds->result == downloadresultcode::IN_PROGRESS) {
  609. entryDict[KEY_STATUS] = BDE_REMOVED;
  610. } else if(ds->result == downloadresultcode::FINISHED) {
  611. entryDict[KEY_STATUS] = BDE_COMPLETE;
  612. } else {
  613. entryDict[KEY_STATUS] = BDE_ERROR;
  614. }
  615. if(!ds->followedBy.empty()) {
  616. BDE list = BDE::list();
  617. // The element is GID.
  618. for(std::vector<gid_t>::const_iterator i = ds->followedBy.begin(),
  619. eoi = ds->followedBy.end(); i != eoi; ++i) {
  620. list << util::itos(*i);
  621. }
  622. entryDict[KEY_FOLLOWED_BY] = list;
  623. }
  624. if(ds->belongsTo) {
  625. entryDict[KEY_BELONGS_TO] = util::itos(ds->belongsTo);
  626. }
  627. BDE files = BDE::list();
  628. createFileEntry(files, ds->fileEntries.begin(), ds->fileEntries.end());
  629. entryDict[KEY_FILES] = files;
  630. entryDict[KEY_TOTAL_LENGTH] = util::uitos(ds->totalLength);
  631. entryDict[KEY_COMPLETED_LENGTH] = util::uitos(ds->completedLength);
  632. entryDict[KEY_UPLOAD_LENGTH] = util::uitos(ds->uploadLength);
  633. if(!ds->bitfieldStr.empty()) {
  634. entryDict[KEY_BITFIELD] = ds->bitfieldStr;
  635. }
  636. entryDict[KEY_DOWNLOAD_SPEED] = BDE_ZERO;
  637. entryDict[KEY_UPLOAD_SPEED] = BDE_ZERO;
  638. if(!ds->infoHashStr.empty()) {
  639. entryDict[KEY_INFO_HASH] = ds->infoHashStr;
  640. entryDict[KEY_NUM_SEEDERS] = BDE_ZERO;
  641. }
  642. entryDict[KEY_PIECE_LENGTH] = util::uitos(ds->pieceLength);
  643. entryDict[KEY_NUM_PIECES] = util::uitos(ds->numPieces);
  644. entryDict[KEY_CONNECTIONS] = BDE_ZERO;
  645. entryDict[KEY_DIR] = ds->dir;
  646. }
  647. BDE GetFilesXmlRpcMethod::process
  648. (const XmlRpcRequest& req, DownloadEngine* e)
  649. {
  650. const BDE& params = req._params;
  651. assert(params.isList());
  652. if(params.empty() || !params[0].isString()) {
  653. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  654. }
  655. gid_t gid = util::parseLLInt(params[0].s());
  656. BDE files = BDE::list();
  657. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  658. if(group.isNull()) {
  659. SharedHandle<DownloadResult> dr =
  660. e->_requestGroupMan->findDownloadResult(gid);
  661. if(dr.isNull()) {
  662. throw DL_ABORT_EX
  663. (StringFormat("No file data is available for GID#%s",
  664. util::itos(gid).c_str()).str());
  665. } else {
  666. createFileEntry(files, dr->fileEntries.begin(), dr->fileEntries.end());
  667. }
  668. } else {
  669. createFileEntry(files,
  670. group->getDownloadContext()->getFileEntries().begin(),
  671. group->getDownloadContext()->getFileEntries().end());
  672. }
  673. return files;
  674. }
  675. BDE GetUrisXmlRpcMethod::process
  676. (const XmlRpcRequest& req, DownloadEngine* e)
  677. {
  678. const BDE& params = req._params;
  679. assert(params.isList());
  680. if(params.empty() || !params[0].isString()) {
  681. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  682. }
  683. gid_t gid = util::parseLLInt(params[0].s());
  684. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  685. if(group.isNull()) {
  686. throw DL_ABORT_EX
  687. (StringFormat("No URI data is available for GID#%s",
  688. util::itos(gid).c_str()).str());
  689. }
  690. BDE uriList = BDE::list();
  691. // TODO Current implementation just returns first FileEntry's URIs.
  692. if(!group->getDownloadContext()->getFileEntries().empty()) {
  693. createUriEntry(uriList, group->getDownloadContext()->getFirstFileEntry());
  694. }
  695. return uriList;
  696. }
  697. #ifdef ENABLE_BITTORRENT
  698. BDE GetPeersXmlRpcMethod::process
  699. (const XmlRpcRequest& req, DownloadEngine* e)
  700. {
  701. const BDE& params = req._params;
  702. assert(params.isList());
  703. if(params.empty() || !params[0].isString()) {
  704. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  705. }
  706. gid_t gid = util::parseLLInt(params[0].s());
  707. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  708. if(group.isNull()) {
  709. throw DL_ABORT_EX
  710. (StringFormat("No peer data is available for GID#%s",
  711. util::itos(gid).c_str()).str());
  712. }
  713. BDE peers = BDE::list();
  714. BtObject btObject = e->getBtRegistry()->get(group->getGID());
  715. if(!btObject.isNull()) {
  716. assert(!btObject._peerStorage.isNull());
  717. gatherPeer(peers, btObject._peerStorage);
  718. }
  719. return peers;
  720. }
  721. #endif // ENABLE_BITTORRENT
  722. BDE TellStatusXmlRpcMethod::process
  723. (const XmlRpcRequest& req, DownloadEngine* e)
  724. {
  725. const BDE& params = req._params;
  726. assert(params.isList());
  727. if(params.empty() || !params[0].isString()) {
  728. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  729. }
  730. gid_t gid = util::parseLLInt(params[0].s());
  731. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  732. BDE entryDict = BDE::dict();
  733. if(group.isNull()) {
  734. group = e->_requestGroupMan->findReservedGroup(gid);
  735. if(group.isNull()) {
  736. SharedHandle<DownloadResult> ds =
  737. e->_requestGroupMan->findDownloadResult(gid);
  738. if(ds.isNull()) {
  739. throw DL_ABORT_EX
  740. (StringFormat("No such download for GID#%s",
  741. util::itos(gid).c_str()).str());
  742. }
  743. gatherStoppedDownload(entryDict, ds);
  744. } else {
  745. if(group->isPauseRequested()) {
  746. entryDict[KEY_STATUS] = BDE_PAUSED;
  747. } else {
  748. entryDict[KEY_STATUS] = BDE_WAITING;
  749. }
  750. gatherProgress(entryDict, group, e);
  751. }
  752. } else {
  753. entryDict[KEY_STATUS] = BDE_ACTIVE;
  754. gatherProgress(entryDict, group, e);
  755. }
  756. return entryDict;
  757. }
  758. BDE TellActiveXmlRpcMethod::process
  759. (const XmlRpcRequest& req, DownloadEngine* e)
  760. {
  761. BDE list = BDE::list();
  762. const std::deque<SharedHandle<RequestGroup> >& groups =
  763. e->_requestGroupMan->getRequestGroups();
  764. for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
  765. groups.begin(), eoi = groups.end(); i != eoi; ++i) {
  766. BDE entryDict = BDE::dict();
  767. entryDict[KEY_STATUS] = BDE_ACTIVE;
  768. gatherProgress(entryDict, *i, e);
  769. list << entryDict;
  770. }
  771. return list;
  772. }
  773. const std::deque<SharedHandle<RequestGroup> >&
  774. TellWaitingXmlRpcMethod::getItems(DownloadEngine* e) const
  775. {
  776. return e->_requestGroupMan->getReservedGroups();
  777. }
  778. void TellWaitingXmlRpcMethod::createEntry
  779. (BDE& entryDict, const SharedHandle<RequestGroup>& item,
  780. DownloadEngine* e) const
  781. {
  782. if(item->isPauseRequested()) {
  783. entryDict[KEY_STATUS] = BDE_PAUSED;
  784. } else {
  785. entryDict[KEY_STATUS] = BDE_WAITING;
  786. }
  787. gatherProgress(entryDict, item, e);
  788. }
  789. const std::deque<SharedHandle<DownloadResult> >&
  790. TellStoppedXmlRpcMethod::getItems(DownloadEngine* e) const
  791. {
  792. return e->_requestGroupMan->getDownloadResults();
  793. }
  794. void TellStoppedXmlRpcMethod::createEntry
  795. (BDE& entryDict, const SharedHandle<DownloadResult>& item,
  796. DownloadEngine* e) const
  797. {
  798. gatherStoppedDownload(entryDict, item);
  799. }
  800. BDE PurgeDownloadResultXmlRpcMethod::process
  801. (const XmlRpcRequest& req, DownloadEngine* e)
  802. {
  803. e->_requestGroupMan->purgeDownloadResult();
  804. return BDE_OK;
  805. }
  806. BDE ChangeOptionXmlRpcMethod::process
  807. (const XmlRpcRequest& req, DownloadEngine* e)
  808. {
  809. const BDE& params = req._params;
  810. assert(params.isList());
  811. if(params.empty() || !params[0].isString()) {
  812. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  813. }
  814. gid_t gid = util::parseLLInt(params[0].s());
  815. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  816. if(group.isNull()) {
  817. throw DL_ABORT_EX
  818. (StringFormat("Cannot change option for GID#%s",
  819. util::itos(gid).c_str()).str());
  820. }
  821. SharedHandle<Option> option(new Option());
  822. if(params.size() > 1 && params[1].isDict()) {
  823. gatherChangeableOption(option, params[1]);
  824. applyChangeableOption(group->getOption().get(), option.get());
  825. if(option->defined(PREF_MAX_DOWNLOAD_LIMIT)) {
  826. group->setMaxDownloadSpeedLimit
  827. (option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
  828. }
  829. if(option->defined(PREF_MAX_UPLOAD_LIMIT)) {
  830. group->setMaxUploadSpeedLimit(option->getAsInt(PREF_MAX_UPLOAD_LIMIT));
  831. }
  832. #ifdef ENABLE_BITTORRENT
  833. BtObject btObject = e->getBtRegistry()->get(group->getGID());
  834. if(!btObject.isNull()) {
  835. if(option->defined(PREF_BT_MAX_PEERS)) {
  836. btObject._btRuntime->setMaxPeers(option->getAsInt(PREF_BT_MAX_PEERS));
  837. }
  838. }
  839. #endif // ENABLE_BITTORRENT
  840. }
  841. return BDE_OK;
  842. }
  843. BDE ChangeGlobalOptionXmlRpcMethod::process
  844. (const XmlRpcRequest& req, DownloadEngine* e)
  845. {
  846. const BDE& params = req._params;
  847. assert(params.isList());
  848. if(params.empty() || !params[0].isDict()) {
  849. return BDE_OK;
  850. }
  851. SharedHandle<Option> option(new Option());
  852. gatherChangeableGlobalOption(option, params[0]);
  853. applyChangeableGlobalOption(e->option, option.get());
  854. if(option->defined(PREF_MAX_OVERALL_DOWNLOAD_LIMIT)) {
  855. e->_requestGroupMan->setMaxOverallDownloadSpeedLimit
  856. (option->getAsInt(PREF_MAX_OVERALL_DOWNLOAD_LIMIT));
  857. }
  858. if(option->defined(PREF_MAX_OVERALL_UPLOAD_LIMIT)) {
  859. e->_requestGroupMan->setMaxOverallUploadSpeedLimit
  860. (option->getAsInt(PREF_MAX_OVERALL_UPLOAD_LIMIT));
  861. }
  862. if(option->defined(PREF_MAX_CONCURRENT_DOWNLOADS)) {
  863. e->_requestGroupMan->setMaxSimultaneousDownloads
  864. (option->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
  865. e->_requestGroupMan->requestQueueCheck();
  866. }
  867. return BDE_OK;
  868. }
  869. BDE GetVersionXmlRpcMethod::process
  870. (const XmlRpcRequest& req, DownloadEngine* e)
  871. {
  872. BDE result = BDE::dict();
  873. result[KEY_VERSION] = std::string(PACKAGE_VERSION);
  874. BDE featureList = BDE::list();
  875. const FeatureMap& features = FeatureConfig::getInstance()->getFeatures();
  876. for(FeatureMap::const_iterator i = features.begin(), eoi = features.end();
  877. i != eoi;++i){
  878. if((*i).second) {
  879. featureList << (*i).first;
  880. }
  881. }
  882. result[KEY_ENABLED_FEATURES] = featureList;
  883. return result;
  884. }
  885. template<typename InputIterator>
  886. static void pushRequestOption
  887. (BDE& dict, InputIterator optionFirst, InputIterator optionLast)
  888. {
  889. const std::set<std::string>& requestOptions = listRequestOptions();
  890. for(; optionFirst != optionLast; ++optionFirst) {
  891. if(requestOptions.count((*optionFirst).first)) {
  892. dict[(*optionFirst).first] = (*optionFirst).second;
  893. }
  894. }
  895. }
  896. BDE GetOptionXmlRpcMethod::process
  897. (const XmlRpcRequest& req, DownloadEngine* e)
  898. {
  899. const BDE& params = req._params;
  900. assert(params.isList());
  901. if(params.empty() || !params[0].isString()) {
  902. throw DL_ABORT_EX(MSG_GID_NOT_PROVIDED);
  903. }
  904. gid_t gid = util::parseLLInt(params[0].s());
  905. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  906. if(group.isNull()) {
  907. throw DL_ABORT_EX
  908. (StringFormat("Cannot get option for GID#%s",
  909. util::itos(gid).c_str()).str());
  910. }
  911. BDE result = BDE::dict();
  912. SharedHandle<Option> option = group->getOption();
  913. pushRequestOption(result, option->begin(), option->end());
  914. return result;
  915. }
  916. BDE GetGlobalOptionXmlRpcMethod::process
  917. (const XmlRpcRequest& req, DownloadEngine* e)
  918. {
  919. BDE result = BDE::dict();
  920. for(std::map<std::string, std::string>::const_iterator i = e->option->begin(),
  921. eoi = e->option->end(); i != eoi; ++i) {
  922. SharedHandle<OptionHandler> h = _optionParser->findByName((*i).first);
  923. if(!h.isNull() && !h->isHidden()) {
  924. result[(*i).first] = (*i).second;
  925. }
  926. }
  927. return result;
  928. }
  929. BDE ChangePositionXmlRpcMethod::process
  930. (const XmlRpcRequest& req, DownloadEngine* e)
  931. {
  932. const BDE& params = req._params;
  933. assert(params.isList());
  934. if(params.size() != 3 ||
  935. !params[0].isString() || !params[1].isInteger() || !params[2].isString()) {
  936. throw DL_ABORT_EX("Illegal argument.");
  937. }
  938. gid_t gid = util::parseLLInt(params[0].s());
  939. int pos = params[1].i();
  940. const std::string& howStr = params[2].s();
  941. RequestGroupMan::HOW how;
  942. if(howStr == "POS_SET") {
  943. how = RequestGroupMan::POS_SET;
  944. } else if(howStr == "POS_CUR") {
  945. how = RequestGroupMan::POS_CUR;
  946. } else if(howStr == "POS_END") {
  947. how = RequestGroupMan::POS_END;
  948. } else {
  949. throw DL_ABORT_EX("Illegal argument.");
  950. }
  951. size_t destPos =
  952. e->_requestGroupMan->changeReservedGroupPosition(gid, pos, how);
  953. BDE result(destPos);
  954. return result;
  955. }
  956. BDE GetSessionInfoXmlRpcMethod::process
  957. (const XmlRpcRequest& req, DownloadEngine* e)
  958. {
  959. BDE result = BDE::dict();
  960. result[KEY_SESSION_ID] = util::toHex(e->getSessionId());
  961. return result;
  962. }
  963. BDE GetServersXmlRpcMethod::process
  964. (const XmlRpcRequest& req, DownloadEngine* e)
  965. {
  966. const BDE& params = req._params;
  967. assert(params.isList());
  968. if(params.empty() || !params[0].isString()) {
  969. throw DL_ABORT_EX("Bad request");
  970. }
  971. gid_t gid = util::parseLLInt(params[0].s());
  972. SharedHandle<RequestGroup> group = e->_requestGroupMan->findRequestGroup(gid);
  973. if(group.isNull()) {
  974. throw DL_ABORT_EX(StringFormat("No active download for GID#%s",
  975. util::itos(gid).c_str()).str());
  976. }
  977. const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
  978. const std::vector<SharedHandle<FileEntry> >& files = dctx->getFileEntries();
  979. BDE result = BDE::list();
  980. size_t index = 1;
  981. for(std::vector<SharedHandle<FileEntry> >::const_iterator fi = files.begin(),
  982. eoi = files.end(); fi != eoi; ++fi, ++index) {
  983. BDE fileEntry = BDE::dict();
  984. fileEntry[KEY_INDEX] = util::uitos(index);
  985. BDE servers = BDE::list();
  986. const std::deque<SharedHandle<Request> >& requests =
  987. (*fi)->getInFlightRequests();
  988. for(std::deque<SharedHandle<Request> >::const_iterator ri =requests.begin(),
  989. eoi = requests.end(); ri != eoi; ++ri) {
  990. SharedHandle<PeerStat> ps = (*ri)->getPeerStat();
  991. if(!ps.isNull()) {
  992. BDE serverEntry = BDE::dict();
  993. serverEntry[KEY_URI] = (*ri)->getUri();
  994. serverEntry[KEY_CURRENT_URI] = (*ri)->getCurrentUri();
  995. serverEntry[KEY_DOWNLOAD_SPEED] =
  996. util::uitos(ps->calculateDownloadSpeed());
  997. servers << serverEntry;
  998. }
  999. }
  1000. fileEntry[KEY_SERVERS] = servers;
  1001. result << fileEntry;
  1002. }
  1003. return result;
  1004. }
  1005. BDE ChangeUriXmlRpcMethod::process
  1006. (const XmlRpcRequest& req, DownloadEngine* e)
  1007. {
  1008. const BDE& params = req._params;
  1009. assert(params.isList());
  1010. if(params.size() < 4 ||
  1011. !params[0].isString() || !params[1].isInteger() ||
  1012. !params[2].isList() || !params[3].isList() ||
  1013. params[1].i() <= 0) {
  1014. throw DL_ABORT_EX("Bad request");
  1015. }
  1016. size_t pos = 0;
  1017. bool posGiven = false;
  1018. getPosParam(params, 4, posGiven, pos);
  1019. gid_t gid = util::parseLLInt(params[0].s());
  1020. size_t index = params[1].i()-1;
  1021. const BDE& deluris = params[2];
  1022. const BDE& adduris = params[3];
  1023. SharedHandle<RequestGroup> group = findRequestGroup(e->_requestGroupMan, gid);
  1024. if(group.isNull()) {
  1025. throw DL_ABORT_EX
  1026. (StringFormat("Cannot remove URIs from GID#%s",
  1027. util::itos(gid).c_str()).str());
  1028. }
  1029. const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
  1030. const std::vector<SharedHandle<FileEntry> >& files = dctx->getFileEntries();
  1031. if(files.size() <= index) {
  1032. throw DL_ABORT_EX(StringFormat("fileIndex is out of range").str());
  1033. }
  1034. SharedHandle<FileEntry> s = files[index];
  1035. size_t delcount = 0;
  1036. for(BDE::List::const_iterator i = deluris.listBegin(),
  1037. eoi = deluris.listEnd(); i != eoi; ++i) {
  1038. if(s->removeUri((*i).s())) {
  1039. ++delcount;
  1040. }
  1041. }
  1042. size_t addcount = 0;
  1043. if(posGiven) {
  1044. for(BDE::List::const_iterator i = adduris.listBegin(),
  1045. eoi = adduris.listEnd(); i != eoi; ++i) {
  1046. if(s->insertUri((*i).s(), pos)) {
  1047. ++addcount;
  1048. ++pos;
  1049. }
  1050. }
  1051. } else {
  1052. for(BDE::List::const_iterator i = adduris.listBegin(),
  1053. eoi = adduris.listEnd(); i != eoi; ++i) {
  1054. if(s->addUri((*i).s())) {
  1055. ++addcount;
  1056. }
  1057. }
  1058. }
  1059. if(addcount && !group->getPieceStorage().isNull()) {
  1060. std::vector<Command*> commands;
  1061. group->createNextCommand(commands, e);
  1062. e->addCommand(commands);
  1063. group->getSegmentMan()->recognizeSegmentFor(s);
  1064. }
  1065. BDE res = BDE::list();
  1066. res << delcount;
  1067. res << addcount;
  1068. return res;
  1069. }
  1070. static BDE goingShutdown
  1071. (const XmlRpcRequest& req, DownloadEngine* e, bool forceHalt)
  1072. {
  1073. // Schedule shutdown after 3seconds to give time to client to
  1074. // receive XML-RPC response.
  1075. e->addRoutineCommand(new TimedHaltCommand(e->newCUID(), e, 3, forceHalt));
  1076. LogFactory::getInstance()->info("Scheduled shutdown in 3 seconds.");
  1077. return BDE_OK;
  1078. }
  1079. BDE ShutdownXmlRpcMethod::process(const XmlRpcRequest& req, DownloadEngine* e)
  1080. {
  1081. return goingShutdown(req, e, false);
  1082. }
  1083. BDE ForceShutdownXmlRpcMethod::process
  1084. (const XmlRpcRequest& req, DownloadEngine* e)
  1085. {
  1086. return goingShutdown(req, e, true);
  1087. }
  1088. BDE SystemMulticallXmlRpcMethod::process
  1089. (const XmlRpcRequest& req, DownloadEngine* e)
  1090. {
  1091. const BDE& params = req._params;
  1092. assert(params.isList());
  1093. if(params.size() != 1) {
  1094. throw DL_ABORT_EX("Illegal argument. One item list is expected.");
  1095. }
  1096. const BDE& methodSpecs = params[0];
  1097. BDE list = BDE::list();
  1098. for(BDE::List::const_iterator i = methodSpecs.listBegin(),
  1099. eoi = methodSpecs.listEnd(); i != eoi; ++i) {
  1100. if(!(*i).isDict()) {
  1101. list << createErrorResponse
  1102. (DL_ABORT_EX("system.multicall expected struct."));
  1103. continue;
  1104. }
  1105. if(!(*i).containsKey(KEY_METHOD_NAME) ||
  1106. !(*i).containsKey(KEY_PARAMS)) {
  1107. list << createErrorResponse
  1108. (DL_ABORT_EX("Missing methodName or params."));
  1109. continue;
  1110. }
  1111. const std::string& methodName = (*i)[KEY_METHOD_NAME].s();
  1112. if(methodName == getMethodName()) {
  1113. list << createErrorResponse
  1114. (DL_ABORT_EX("Recursive system.multicall forbidden."));
  1115. continue;
  1116. }
  1117. SharedHandle<XmlRpcMethod> method = XmlRpcMethodFactory::create(methodName);
  1118. XmlRpcRequest innerReq(methodName, (*i)[KEY_PARAMS]);
  1119. XmlRpcResponse res = method->execute(innerReq, e);
  1120. if(res._code == 0) {
  1121. BDE l = BDE::list();
  1122. l << res._param;
  1123. list << l;
  1124. } else {
  1125. list << res._param;
  1126. }
  1127. }
  1128. return list;
  1129. }
  1130. BDE NoSuchMethodXmlRpcMethod::process
  1131. (const XmlRpcRequest& req, DownloadEngine* e)
  1132. {
  1133. throw DL_ABORT_EX
  1134. (StringFormat("No such method: %s", req._methodName.c_str()).str());
  1135. }
  1136. } // namespace xmlrpc
  1137. } // namespace aria2