llcorehttprequest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /**
  2. * @file llcorehttprequest.cpp
  3. * @brief Implementation of the HTTPRequest class
  4. *
  5. * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2012, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llcorehttprequest.h"
  28. #include "llcorehttpopcancel.h"
  29. #include "llcorehttpoperation.h"
  30. #include "llcorehttpoprequest.h"
  31. #include "llcorehttpopsetget.h"
  32. #include "llcorehttppolicy.h"
  33. #include "llcorehttpreplyqueue.h"
  34. #include "llcorehttprequestqueue.h"
  35. #include "llcorehttpservice.h"
  36. #include "lltimer.h"
  37. namespace LLCore
  38. {
  39. //static
  40. bool HttpRequest::sInitialized = false;
  41. static const HttpStatus sStatusNotDynamic(HttpStatus::LLCORE,
  42. HE_OPT_NOT_DYNAMIC);
  43. // ====================================
  44. // HttpRequest Implementation
  45. // ====================================
  46. HttpRequest::HttpRequest()
  47. : mCancelled(false)
  48. {
  49. mRequestQueue = HttpRequestQueue::instanceOf();
  50. mRequestQueue->addRef();
  51. mReplyQueue.reset(new HttpReplyQueue());
  52. }
  53. HttpRequest::~HttpRequest()
  54. {
  55. if (mRequestQueue)
  56. {
  57. mRequestQueue->release();
  58. mRequestQueue = NULL;
  59. }
  60. mReplyQueue.reset();
  61. }
  62. // ====================================
  63. // Policy Methods
  64. // ====================================
  65. HttpRequest::policy_t HttpRequest::createPolicyClass()
  66. {
  67. if (HttpService::instanceOf()->getState() == HttpService::RUNNING)
  68. {
  69. return 0;
  70. }
  71. return HttpService::instanceOf()->createPolicyClass();
  72. }
  73. HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt,
  74. policy_t pclass,
  75. long value, long* ret_value)
  76. {
  77. if (HttpService::instanceOf()->getState() == HttpService::RUNNING)
  78. {
  79. return sStatusNotDynamic;
  80. }
  81. return HttpService::instanceOf()->setPolicyOption(opt, pclass, value,
  82. ret_value);
  83. }
  84. HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt,
  85. policy_t pclass,
  86. const std::string& value,
  87. std::string* ret_value)
  88. {
  89. if (HttpService::instanceOf()->getState() == HttpService::RUNNING)
  90. {
  91. return sStatusNotDynamic;
  92. }
  93. return HttpService::instanceOf()->setPolicyOption(opt, pclass, value,
  94. ret_value);
  95. }
  96. HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt,
  97. policy_t pclass,
  98. policyCallback_t value,
  99. policyCallback_t* ret_value)
  100. {
  101. if (HttpService::instanceOf()->getState() == HttpService::RUNNING)
  102. {
  103. return sStatusNotDynamic;
  104. }
  105. return HttpService::instanceOf()->setPolicyOption(opt, pclass, value,
  106. ret_value);
  107. }
  108. HttpHandle HttpRequest::setPolicyOption(EPolicyOption opt, policy_t pclass,
  109. long value, HttpHandler::ptr_t handler)
  110. {
  111. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  112. HttpOpSetGet::ptr_t op(new HttpOpSetGet());
  113. HttpStatus status = op->setupSet(opt, pclass, value);
  114. if (!status)
  115. {
  116. mLastReqStatus = status;
  117. return handle;
  118. }
  119. op->setReplyPath(mReplyQueue, handler);
  120. status = mRequestQueue->addOp(op); // transfers refcount
  121. if (status)
  122. {
  123. handle = op->getHandle();
  124. }
  125. mLastReqStatus = status;
  126. return handle;
  127. }
  128. HttpHandle HttpRequest::setPolicyOption(EPolicyOption opt, policy_t pclass,
  129. const std::string& value,
  130. HttpHandler::ptr_t handler)
  131. {
  132. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  133. HttpOpSetGet::ptr_t op(new HttpOpSetGet());
  134. HttpStatus status = op->setupSet(opt, pclass, value);
  135. if (!status)
  136. {
  137. mLastReqStatus = status;
  138. return handle;
  139. }
  140. op->setReplyPath(mReplyQueue, handler);
  141. status = mRequestQueue->addOp(op); // transfers refcount
  142. if (status)
  143. {
  144. handle = op->getHandle();
  145. }
  146. mLastReqStatus = status;
  147. return handle;
  148. }
  149. // ====================================
  150. // Request Methods
  151. // ====================================
  152. HttpHandle HttpRequest::requestGet(policy_t policy_id, const std::string& url,
  153. const HttpOptions::ptr_t& options,
  154. const HttpHeaders::ptr_t& headers,
  155. const HttpHandler::ptr_t user_handler)
  156. {
  157. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  158. HttpOpRequest::ptr_t op(new HttpOpRequest());
  159. HttpStatus status = op->setupGet(policy_id, url, options, headers);
  160. if (!status)
  161. {
  162. mLastReqStatus = status;
  163. return handle;
  164. }
  165. op->setReplyPath(mReplyQueue, user_handler);
  166. status = mRequestQueue->addOp(op); // transfers refcount
  167. if (status)
  168. {
  169. handle = op->getHandle();
  170. }
  171. mLastReqStatus = status;
  172. return handle;
  173. }
  174. HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
  175. const std::string& url,
  176. size_t offset, size_t len,
  177. const HttpOptions::ptr_t& options,
  178. const HttpHeaders::ptr_t& headers,
  179. HttpHandler::ptr_t user_handler)
  180. {
  181. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  182. HttpOpRequest::ptr_t op(new HttpOpRequest());
  183. HttpStatus status = op->setupGetByteRange(policy_id, url, offset, len,
  184. options, headers);
  185. if (!status)
  186. {
  187. mLastReqStatus = status;
  188. return handle;
  189. }
  190. op->setReplyPath(mReplyQueue, user_handler);
  191. status = mRequestQueue->addOp(op); // transfers refcount
  192. if (status)
  193. {
  194. handle = op->getHandle();
  195. }
  196. mLastReqStatus = status;
  197. return handle;
  198. }
  199. HttpHandle HttpRequest::requestPost(policy_t policy_id, const std::string& url,
  200. BufferArray* body,
  201. const HttpOptions::ptr_t& options,
  202. const HttpHeaders::ptr_t& headers,
  203. HttpHandler::ptr_t user_handler)
  204. {
  205. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  206. HttpOpRequest::ptr_t op(new HttpOpRequest());
  207. HttpStatus status = op->setupPost(policy_id, url, body, options, headers);
  208. if (!status)
  209. {
  210. mLastReqStatus = status;
  211. return handle;
  212. }
  213. op->setReplyPath(mReplyQueue, user_handler);
  214. status = mRequestQueue->addOp(op); // transfers refcount
  215. if (status)
  216. {
  217. handle = op->getHandle();
  218. }
  219. mLastReqStatus = status;
  220. return handle;
  221. }
  222. HttpHandle HttpRequest::requestPut(policy_t policy_id, const std::string& url,
  223. BufferArray* body,
  224. const HttpOptions::ptr_t& options,
  225. const HttpHeaders::ptr_t& headers,
  226. HttpHandler::ptr_t user_handler)
  227. {
  228. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  229. HttpOpRequest::ptr_t op(new HttpOpRequest());
  230. HttpStatus status = op->setupPut(policy_id, url, body, options, headers);
  231. if (!status)
  232. {
  233. mLastReqStatus = status;
  234. return handle;
  235. }
  236. op->setReplyPath(mReplyQueue, user_handler);
  237. status = mRequestQueue->addOp(op); // transfers refcount
  238. if (status)
  239. {
  240. handle = op->getHandle();
  241. }
  242. mLastReqStatus = status;
  243. return handle;
  244. }
  245. HttpHandle HttpRequest::requestDelete(policy_t policy_id,
  246. const std::string& url,
  247. const HttpOptions::ptr_t& options,
  248. const HttpHeaders::ptr_t& headers,
  249. HttpHandler::ptr_t user_handler)
  250. {
  251. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  252. HttpOpRequest::ptr_t op(new HttpOpRequest());
  253. HttpStatus status = op->setupDelete(policy_id, url, options, headers);
  254. if (!status)
  255. {
  256. mLastReqStatus = status;
  257. return handle;
  258. }
  259. op->setReplyPath(mReplyQueue, user_handler);
  260. status = mRequestQueue->addOp(op); // transfers refcount
  261. if (status)
  262. {
  263. handle = op->getHandle();
  264. }
  265. mLastReqStatus = status;
  266. return handle;
  267. }
  268. HttpHandle HttpRequest::requestPatch(policy_t policy_id,
  269. const std::string& url, BufferArray* body,
  270. const HttpOptions::ptr_t& options,
  271. const HttpHeaders::ptr_t& headers,
  272. HttpHandler::ptr_t user_handler)
  273. {
  274. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  275. HttpOpRequest::ptr_t op(new HttpOpRequest());
  276. HttpStatus status = op->setupPatch(policy_id, url, body, options, headers);
  277. if (!status)
  278. {
  279. mLastReqStatus = status;
  280. return handle;
  281. }
  282. op->setReplyPath(mReplyQueue, user_handler);
  283. status = mRequestQueue->addOp(op); // transfers refcount
  284. if (status)
  285. {
  286. handle = op->getHandle();
  287. }
  288. mLastReqStatus = status;
  289. return handle;
  290. }
  291. HttpHandle HttpRequest::requestCopy(policy_t policy_id, const std::string& url,
  292. const HttpOptions::ptr_t& options,
  293. const HttpHeaders::ptr_t& headers,
  294. HttpHandler::ptr_t user_handler)
  295. {
  296. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  297. HttpOpRequest::ptr_t op(new HttpOpRequest());
  298. HttpStatus status = op->setupCopy(policy_id, url, options, headers);
  299. if (!status)
  300. {
  301. mLastReqStatus = status;
  302. return handle;
  303. }
  304. op->setReplyPath(mReplyQueue, user_handler);
  305. status = mRequestQueue->addOp(op); // transfers refcount
  306. if (status)
  307. {
  308. handle = op->getHandle();
  309. }
  310. mLastReqStatus = status;
  311. return handle;
  312. }
  313. HttpHandle HttpRequest::requestMove(policy_t policy_id, const std::string& url,
  314. const HttpOptions::ptr_t& options,
  315. const HttpHeaders::ptr_t& headers,
  316. HttpHandler::ptr_t user_handler)
  317. {
  318. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  319. HttpOpRequest::ptr_t op(new HttpOpRequest());
  320. HttpStatus status = op->setupMove(policy_id, url, options, headers);
  321. if (!status)
  322. {
  323. mLastReqStatus = status;
  324. return handle;
  325. }
  326. op->setReplyPath(mReplyQueue, user_handler);
  327. status = mRequestQueue->addOp(op); // transfers refcount
  328. if (status)
  329. {
  330. handle = op->getHandle();
  331. }
  332. mLastReqStatus = status;
  333. return handle;
  334. }
  335. HttpHandle HttpRequest::requestNoOp(HttpHandler::ptr_t user_handler)
  336. {
  337. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  338. HttpOperation::ptr_t op(new HttpOpNull());
  339. op->setReplyPath(mReplyQueue, user_handler);
  340. HttpStatus status = mRequestQueue->addOp(op); // transfers refcount
  341. if (status)
  342. {
  343. handle = op->getHandle();
  344. }
  345. mLastReqStatus = status;
  346. return handle;
  347. }
  348. HttpStatus HttpRequest::update(long usecs)
  349. {
  350. if (mLastReqStatus == gStatusCancelled || !mReplyQueue)
  351. {
  352. return gStatusCancelled;
  353. }
  354. HttpOperation::ptr_t op;
  355. if (usecs)
  356. {
  357. const HttpTime limit(LLTimer::totalTime() + HttpTime(usecs));
  358. while (limit >= LLTimer::totalTime() && (op = mReplyQueue->fetchOp()))
  359. {
  360. // Process operation
  361. op->visitNotifier(this);
  362. // We are done with the operation
  363. op.reset();
  364. }
  365. }
  366. else
  367. {
  368. // Same as above, just no time limit
  369. HttpReplyQueue::OpContainer replies;
  370. mReplyQueue->fetchAll(replies);
  371. if (!replies.empty())
  372. {
  373. for (HttpReplyQueue::OpContainer::iterator iter = replies.begin(),
  374. iend = replies.end();
  375. iter != iend; ++iter)
  376. {
  377. // Swap op pointer for NULL;
  378. op.reset();
  379. op.swap(*iter);
  380. if (op)
  381. {
  382. // Process operation
  383. op->visitNotifier(this);
  384. }
  385. }
  386. op.reset();
  387. }
  388. }
  389. return HttpStatus();
  390. }
  391. // ====================================
  392. // Request Management Methods
  393. // ====================================
  394. HttpHandle HttpRequest::requestCancel(HttpHandle request,
  395. HttpHandler::ptr_t user_handler)
  396. {
  397. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  398. mCancelled = true;
  399. HttpOperation::ptr_t op(new HttpOpCancel(request));
  400. op->setReplyPath(mReplyQueue, user_handler);
  401. HttpStatus status = mRequestQueue->addOp(op); // transfers refcount
  402. if (status)
  403. {
  404. handle = op->getHandle();
  405. }
  406. mLastReqStatus = status;
  407. return handle;
  408. }
  409. // ====================================
  410. // Utility Methods
  411. // ====================================
  412. HttpStatus HttpRequest::createService()
  413. {
  414. HttpStatus status;
  415. if (!sInitialized)
  416. {
  417. sInitialized = true;
  418. HttpRequestQueue::init();
  419. HttpRequestQueue* rq = HttpRequestQueue::instanceOf();
  420. HttpService::init(rq);
  421. }
  422. return status;
  423. }
  424. HttpStatus HttpRequest::destroyService()
  425. {
  426. HttpStatus status;
  427. if (sInitialized)
  428. {
  429. HttpService::term();
  430. HttpRequestQueue::term();
  431. sInitialized = false;
  432. }
  433. return status;
  434. }
  435. HttpStatus HttpRequest::startThread()
  436. {
  437. HttpService::instanceOf()->startThread();
  438. HttpStatus status;
  439. return status;
  440. }
  441. HttpHandle HttpRequest::requestStopThread(HttpHandler::ptr_t user_handler)
  442. {
  443. HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
  444. HttpOperation::ptr_t op(new HttpOpStop());
  445. op->setReplyPath(mReplyQueue, user_handler);
  446. HttpStatus status = mRequestQueue->addOp(op); // transfers refcount
  447. if (status)
  448. {
  449. handle = op->getHandle();
  450. }
  451. mLastReqStatus = status;
  452. return handle;
  453. }
  454. } // End namespace LLCore