XmlRpcMethodImpl.cc 43 KB

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