/indra/llmessage/lliohttpserver.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 998 lines · 739 code · 112 blank · 147 comment · 109 complexity · 4175039ee1b4a682e7d4d21c37fa7720 MD5 · raw file

  1. /**
  2. * @file lliohttpserver.cpp
  3. * @author Phoenix
  4. * @date 2005-10-05
  5. * @brief Implementation of the http server classes
  6. *
  7. * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #include "linden_common.h"
  29. #include "lliohttpserver.h"
  30. #include "llapr.h"
  31. #include "llbuffer.h"
  32. #include "llbufferstream.h"
  33. #include "llhttpnode.h"
  34. #include "lliopipe.h"
  35. #include "lliosocket.h"
  36. #include "llioutil.h"
  37. #include "llmemtype.h"
  38. #include "llmemorystream.h"
  39. #include "llpumpio.h"
  40. #include "llsd.h"
  41. #include "llsdserialize_xml.h"
  42. #include "llstat.h"
  43. #include "llstl.h"
  44. #include "lltimer.h"
  45. #include <sstream>
  46. #include <boost/tokenizer.hpp>
  47. static const char HTTP_VERSION_STR[] = "HTTP/1.0";
  48. const std::string CONTEXT_REQUEST("request");
  49. const std::string CONTEXT_RESPONSE("response");
  50. const std::string CONTEXT_VERB("verb");
  51. const std::string CONTEXT_HEADERS("headers");
  52. const std::string HTTP_VERB_GET("GET");
  53. const std::string HTTP_VERB_PUT("PUT");
  54. const std::string HTTP_VERB_POST("POST");
  55. const std::string HTTP_VERB_DELETE("DELETE");
  56. const std::string HTTP_VERB_OPTIONS("OPTIONS");
  57. static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL;
  58. static void* sTimingCallbackData = NULL;
  59. class LLHTTPPipe : public LLIOPipe
  60. {
  61. public:
  62. LLHTTPPipe(const LLHTTPNode& node)
  63. : mNode(node),
  64. mResponse(NULL),
  65. mState(STATE_INVOKE),
  66. mChainLock(0),
  67. mLockedPump(NULL),
  68. mStatusCode(0)
  69. { }
  70. virtual ~LLHTTPPipe()
  71. {
  72. if (mResponse.notNull())
  73. {
  74. mResponse->nullPipe();
  75. }
  76. }
  77. private:
  78. // LLIOPipe API implementation.
  79. virtual EStatus process_impl(
  80. const LLChannelDescriptors& channels,
  81. LLIOPipe::buffer_ptr_t& buffer,
  82. bool& eos,
  83. LLSD& context,
  84. LLPumpIO* pump);
  85. const LLHTTPNode& mNode;
  86. class Response : public LLHTTPNode::Response
  87. {
  88. public:
  89. static LLPointer<Response> create(LLHTTPPipe* pipe);
  90. virtual ~Response();
  91. // from LLHTTPNode::Response
  92. virtual void result(const LLSD&);
  93. virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
  94. virtual void status(S32 code, const std::string& message);
  95. void nullPipe();
  96. private:
  97. Response() : mPipe(NULL) {} // Must be accessed through LLPointer.
  98. LLHTTPPipe* mPipe;
  99. };
  100. friend class Response;
  101. LLPointer<Response> mResponse;
  102. enum State
  103. {
  104. STATE_INVOKE,
  105. STATE_DELAYED,
  106. STATE_LOCKED,
  107. STATE_GOOD_RESULT,
  108. STATE_STATUS_RESULT,
  109. STATE_EXTENDED_RESULT
  110. };
  111. State mState;
  112. S32 mChainLock;
  113. LLPumpIO* mLockedPump;
  114. void lockChain(LLPumpIO*);
  115. void unlockChain();
  116. LLSD mGoodResult;
  117. S32 mStatusCode;
  118. std::string mStatusMessage;
  119. LLSD mHeaders;
  120. };
  121. static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe");
  122. LLIOPipe::EStatus LLHTTPPipe::process_impl(
  123. const LLChannelDescriptors& channels,
  124. buffer_ptr_t& buffer,
  125. bool& eos,
  126. LLSD& context,
  127. LLPumpIO* pump)
  128. {
  129. LLFastTimer t(FTM_PROCESS_HTTP_PIPE);
  130. PUMP_DEBUG;
  131. lldebugs << "LLSDHTTPServer::process_impl" << llendl;
  132. // Once we have all the data, We need to read the sd on
  133. // the the in channel, and respond on the out channel
  134. if(!eos) return STATUS_BREAK;
  135. if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
  136. PUMP_DEBUG;
  137. if (mState == STATE_INVOKE)
  138. {
  139. PUMP_DEBUG;
  140. mState = STATE_DELAYED;
  141. // assume deferred unless mResponse does otherwise
  142. mResponse = Response::create(this);
  143. // *TODO: Babbage: Parameterize parser?
  144. // *TODO: We should look at content-type and do the right
  145. // thing. Phoenix 2007-12-31
  146. LLBufferStream istr(channels, buffer.get());
  147. static LLTimer timer;
  148. timer.reset();
  149. std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
  150. if(verb == HTTP_VERB_GET)
  151. {
  152. LLPerfBlock getblock("http_get");
  153. mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
  154. }
  155. else if(verb == HTTP_VERB_PUT)
  156. {
  157. LLPerfBlock putblock("http_put");
  158. LLSD input;
  159. if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
  160. {
  161. LLSDSerialize::fromXML(input, istr);
  162. }
  163. else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
  164. {
  165. std::stringstream strstrm;
  166. strstrm << istr.rdbuf();
  167. input = strstrm.str();
  168. }
  169. mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
  170. }
  171. else if(verb == HTTP_VERB_POST)
  172. {
  173. LLPerfBlock postblock("http_post");
  174. LLSD input;
  175. if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
  176. {
  177. LLSDSerialize::fromXML(input, istr);
  178. }
  179. else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
  180. {
  181. std::stringstream strstrm;
  182. strstrm << istr.rdbuf();
  183. input = strstrm.str();
  184. }
  185. mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
  186. }
  187. else if(verb == HTTP_VERB_DELETE)
  188. {
  189. LLPerfBlock delblock("http_delete");
  190. mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
  191. }
  192. else if(verb == HTTP_VERB_OPTIONS)
  193. {
  194. mNode.options(LLHTTPNode::ResponsePtr(mResponse), context);
  195. }
  196. else
  197. {
  198. mResponse->methodNotAllowed();
  199. }
  200. F32 delta = timer.getElapsedTimeF32();
  201. if (sTimingCallback)
  202. {
  203. LLHTTPNode::Description desc;
  204. mNode.describe(desc);
  205. LLSD info = desc.getInfo();
  206. std::string timing_name = info["description"];
  207. timing_name += " ";
  208. timing_name += verb;
  209. sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
  210. }
  211. // Log all HTTP transactions.
  212. // TODO: Add a way to log these to their own file instead of indra.log
  213. // It is just too spammy to be in indra.log.
  214. lldebugs << verb << " " << context[CONTEXT_REQUEST]["path"].asString()
  215. << " " << mStatusCode << " " << mStatusMessage << " " << delta
  216. << "s" << llendl;
  217. // Log Internal Server Errors
  218. //if(mStatusCode == 500)
  219. //{
  220. // llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error"
  221. // << llendl;
  222. //}
  223. }
  224. PUMP_DEBUG;
  225. switch (mState)
  226. {
  227. case STATE_DELAYED:
  228. lockChain(pump);
  229. mState = STATE_LOCKED;
  230. return STATUS_BREAK;
  231. case STATE_LOCKED:
  232. // should never ever happen!
  233. return STATUS_ERROR;
  234. case STATE_GOOD_RESULT:
  235. {
  236. LLSD headers = mHeaders;
  237. headers["Content-Type"] = "application/llsd+xml";
  238. context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
  239. LLBufferStream ostr(channels, buffer.get());
  240. LLSDSerialize::toXML(mGoodResult, ostr);
  241. return STATUS_DONE;
  242. }
  243. case STATE_STATUS_RESULT:
  244. {
  245. LLSD headers = mHeaders;
  246. headers["Content-Type"] = "text/plain";
  247. context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
  248. context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
  249. context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
  250. LLBufferStream ostr(channels, buffer.get());
  251. ostr << mStatusMessage;
  252. return STATUS_DONE;
  253. }
  254. case STATE_EXTENDED_RESULT:
  255. {
  256. context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = mHeaders;
  257. context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
  258. LLBufferStream ostr(channels, buffer.get());
  259. ostr << mStatusMessage;
  260. return STATUS_DONE;
  261. }
  262. default:
  263. llwarns << "LLHTTPPipe::process_impl: unexpected state "
  264. << mState << llendl;
  265. return STATUS_BREAK;
  266. }
  267. // PUMP_DEBUG; // unreachable
  268. }
  269. LLPointer<LLHTTPPipe::Response> LLHTTPPipe::Response::create(LLHTTPPipe* pipe)
  270. {
  271. LLPointer<Response> result = new Response();
  272. result->mPipe = pipe;
  273. return result;
  274. }
  275. // virtual
  276. LLHTTPPipe::Response::~Response()
  277. {
  278. }
  279. void LLHTTPPipe::Response::nullPipe()
  280. {
  281. mPipe = NULL;
  282. }
  283. // virtual
  284. void LLHTTPPipe::Response::result(const LLSD& r)
  285. {
  286. if(! mPipe)
  287. {
  288. llwarns << "LLHTTPPipe::Response::result: NULL pipe" << llendl;
  289. return;
  290. }
  291. mPipe->mStatusCode = 200;
  292. mPipe->mStatusMessage = "OK";
  293. mPipe->mGoodResult = r;
  294. mPipe->mState = STATE_GOOD_RESULT;
  295. mPipe->mHeaders = mHeaders;
  296. mPipe->unlockChain();
  297. }
  298. void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
  299. {
  300. if(! mPipe)
  301. {
  302. llwarns << "LLHTTPPipe::Response::status: NULL pipe" << llendl;
  303. return;
  304. }
  305. mPipe->mStatusCode = code;
  306. mPipe->mStatusMessage = body;
  307. mPipe->mHeaders = headers;
  308. mPipe->mState = STATE_EXTENDED_RESULT;
  309. mPipe->unlockChain();
  310. }
  311. // virtual
  312. void LLHTTPPipe::Response::status(S32 code, const std::string& message)
  313. {
  314. if(! mPipe)
  315. {
  316. llwarns << "LLHTTPPipe::Response::status: NULL pipe" << llendl;
  317. return;
  318. }
  319. mPipe->mStatusCode = code;
  320. mPipe->mStatusMessage = message;
  321. mPipe->mState = STATE_STATUS_RESULT;
  322. mPipe->mHeaders = mHeaders;
  323. mPipe->unlockChain();
  324. }
  325. void LLHTTPPipe::lockChain(LLPumpIO* pump)
  326. {
  327. if (mChainLock != 0) { return; }
  328. mLockedPump = pump;
  329. mChainLock = pump->setLock();
  330. }
  331. void LLHTTPPipe::unlockChain()
  332. {
  333. if (mChainLock == 0) { return; }
  334. mLockedPump->clearLock(mChainLock);
  335. mLockedPump = NULL;
  336. mChainLock = 0;
  337. }
  338. /**
  339. * @class LLHTTPResponseHeader
  340. * @brief Class which correctly builds HTTP headers on a pipe
  341. * @see LLIOPipe
  342. *
  343. * An instance of this class can be placed in a chain where it will
  344. * wait for an end of stream. Once it gets that, it will count the
  345. * bytes on CHANNEL_OUT (or the size of the buffer in io pipe versions
  346. * prior to 2) prepend that data to the request in an HTTP format, and
  347. * supply all normal HTTP response headers.
  348. */
  349. class LLHTTPResponseHeader : public LLIOPipe
  350. {
  351. public:
  352. LLHTTPResponseHeader() : mCode(0) {}
  353. virtual ~LLHTTPResponseHeader() {}
  354. protected:
  355. /* @name LLIOPipe virtual implementations
  356. */
  357. //@{
  358. /**
  359. * @brief Process the data in buffer
  360. */
  361. EStatus process_impl(
  362. const LLChannelDescriptors& channels,
  363. buffer_ptr_t& buffer,
  364. bool& eos,
  365. LLSD& context,
  366. LLPumpIO* pump);
  367. //@}
  368. protected:
  369. S32 mCode;
  370. };
  371. /**
  372. * LLHTTPResponseHeader
  373. */
  374. static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_HEADER("HTTP Header");
  375. // virtual
  376. LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
  377. const LLChannelDescriptors& channels,
  378. buffer_ptr_t& buffer,
  379. bool& eos,
  380. LLSD& context,
  381. LLPumpIO* pump)
  382. {
  383. LLFastTimer t(FTM_PROCESS_HTTP_HEADER);
  384. PUMP_DEBUG;
  385. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  386. if(eos)
  387. {
  388. PUMP_DEBUG;
  389. //mGotEOS = true;
  390. std::ostringstream ostr;
  391. std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
  392. int code = context[CONTEXT_RESPONSE]["statusCode"];
  393. if (code < 200)
  394. {
  395. code = 200;
  396. message = "OK";
  397. }
  398. ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n";
  399. S32 content_length = buffer->countAfter(channels.in(), NULL);
  400. if(0 < content_length)
  401. {
  402. ostr << "Content-Length: " << content_length << "\r\n";
  403. }
  404. // *NOTE: This guard can go away once the LLSD static map
  405. // iterator is available. Phoenix. 2008-05-09
  406. LLSD headers = context[CONTEXT_RESPONSE][CONTEXT_HEADERS];
  407. if(headers.isDefined())
  408. {
  409. LLSD::map_iterator iter = headers.beginMap();
  410. LLSD::map_iterator end = headers.endMap();
  411. for(; iter != end; ++iter)
  412. {
  413. ostr << (*iter).first << ": " << (*iter).second.asString()
  414. << "\r\n";
  415. }
  416. }
  417. ostr << "\r\n";
  418. LLChangeChannel change(channels.in(), channels.out());
  419. std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
  420. std::string header = ostr.str();
  421. buffer->prepend(channels.out(), (U8*)header.c_str(), header.size());
  422. PUMP_DEBUG;
  423. return STATUS_DONE;
  424. }
  425. PUMP_DEBUG;
  426. return STATUS_OK;
  427. }
  428. /**
  429. * @class LLHTTPResponder
  430. * @brief This class
  431. * @see LLIOPipe
  432. *
  433. * <b>NOTE:</b> You should not need to create or use one of these, the
  434. * details are handled by the HTTPResponseFactory.
  435. */
  436. class LLHTTPResponder : public LLIOPipe
  437. {
  438. public:
  439. LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
  440. ~LLHTTPResponder();
  441. protected:
  442. /**
  443. * @brief Read data off of CHANNEL_IN keeping track of last read position.
  444. *
  445. * This is a quick little hack to read headers. It is not IO
  446. * optimal, but it makes it easier for me to implement the header
  447. * parsing. Plus, there should never be more than a few headers.
  448. * This method will tend to read more than necessary, find the
  449. * newline, make the front part of dest look like a c string, and
  450. * move the read head back to where the newline was found. Thus,
  451. * the next read will pick up on the next line.
  452. * @param channel The channel to read in the buffer
  453. * @param buffer The heap array of processed data
  454. * @param dest Destination for the data to be read
  455. * @param[in,out] len <b>in</b> The size of the buffer. <b>out</b> how
  456. * much was read. This value is not useful for determining where to
  457. * seek orfor string assignment.
  458. * @returns Returns true if a line was found.
  459. */
  460. bool readHeaderLine(
  461. const LLChannelDescriptors& channels,
  462. buffer_ptr_t buffer,
  463. U8* dest,
  464. S32& len);
  465. /**
  466. * @brief Mark the request as bad, and handle appropriately
  467. *
  468. * @param channels The channels to use in the buffer.
  469. * @param buffer The heap array of processed data.
  470. */
  471. void markBad(const LLChannelDescriptors& channels, buffer_ptr_t buffer);
  472. protected:
  473. /* @name LLIOPipe virtual implementations
  474. */
  475. //@{
  476. /**
  477. * @brief Process the data in buffer
  478. */
  479. EStatus process_impl(
  480. const LLChannelDescriptors& channels,
  481. buffer_ptr_t& buffer,
  482. bool& eos,
  483. LLSD& context,
  484. LLPumpIO* pump);
  485. //@}
  486. protected:
  487. enum EState
  488. {
  489. STATE_NOTHING,
  490. STATE_READING_HEADERS,
  491. STATE_LOOKING_FOR_EOS,
  492. STATE_DONE,
  493. STATE_SHORT_CIRCUIT
  494. };
  495. LLSD mBuildContext;
  496. EState mState;
  497. U8* mLastRead;
  498. std::string mVerb;
  499. std::string mAbsPathAndQuery;
  500. std::string mPath;
  501. std::string mQuery;
  502. std::string mVersion;
  503. S32 mContentLength;
  504. LLSD mHeaders;
  505. // handle the urls
  506. const LLHTTPNode& mRootNode;
  507. };
  508. LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx) :
  509. mBuildContext(ctx),
  510. mState(STATE_NOTHING),
  511. mLastRead(NULL),
  512. mContentLength(0),
  513. mRootNode(tree)
  514. {
  515. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  516. }
  517. // virtual
  518. LLHTTPResponder::~LLHTTPResponder()
  519. {
  520. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  521. //lldebugs << "destroying LLHTTPResponder" << llendl;
  522. }
  523. bool LLHTTPResponder::readHeaderLine(
  524. const LLChannelDescriptors& channels,
  525. buffer_ptr_t buffer,
  526. U8* dest,
  527. S32& len)
  528. {
  529. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  530. --len;
  531. U8* last = buffer->readAfter(channels.in(), mLastRead, dest, len);
  532. dest[len] = '\0';
  533. U8* newline = (U8*)strchr((char*)dest, '\n');
  534. if(!newline)
  535. {
  536. if(len)
  537. {
  538. lldebugs << "readLine failed - too long maybe?" << llendl;
  539. markBad(channels, buffer);
  540. }
  541. return false;
  542. }
  543. S32 offset = -((len - 1) - (newline - dest));
  544. ++newline;
  545. *newline = '\0';
  546. mLastRead = buffer->seek(channels.in(), last, offset);
  547. return true;
  548. }
  549. void LLHTTPResponder::markBad(
  550. const LLChannelDescriptors& channels,
  551. buffer_ptr_t buffer)
  552. {
  553. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  554. mState = STATE_SHORT_CIRCUIT;
  555. LLBufferStream out(channels, buffer.get());
  556. out << HTTP_VERSION_STR << " 400 Bad Request\r\n\r\n<html>\n"
  557. << "<title>Bad Request</title>\n<body>\nBad Request.\n"
  558. << "</body>\n</html>\n";
  559. }
  560. static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_RESPONDER("HTTP Responder");
  561. // virtual
  562. LLIOPipe::EStatus LLHTTPResponder::process_impl(
  563. const LLChannelDescriptors& channels,
  564. buffer_ptr_t& buffer,
  565. bool& eos,
  566. LLSD& context,
  567. LLPumpIO* pump)
  568. {
  569. LLFastTimer t(FTM_PROCESS_HTTP_RESPONDER);
  570. PUMP_DEBUG;
  571. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  572. LLIOPipe::EStatus status = STATUS_OK;
  573. // parsing headers
  574. if((STATE_NOTHING == mState) || (STATE_READING_HEADERS == mState))
  575. {
  576. PUMP_DEBUG;
  577. status = STATUS_BREAK;
  578. mState = STATE_READING_HEADERS;
  579. const S32 HEADER_BUFFER_SIZE = 1024;
  580. char buf[HEADER_BUFFER_SIZE + 1]; /*Flawfinder: ignore*/
  581. S32 len = HEADER_BUFFER_SIZE;
  582. #if 0
  583. if(true)
  584. {
  585. LLBufferArray::segment_iterator_t seg_iter = buffer->beginSegment();
  586. char buf[1024]; /*Flawfinder: ignore*/
  587. while(seg_iter != buffer->endSegment())
  588. {
  589. memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
  590. buf[(*seg_iter).size()] = '\0';
  591. llinfos << (*seg_iter).getChannel() << ": " << buf
  592. << llendl;
  593. ++seg_iter;
  594. }
  595. }
  596. #endif
  597. PUMP_DEBUG;
  598. if(readHeaderLine(channels, buffer, (U8*)buf, len))
  599. {
  600. bool read_next_line = false;
  601. bool parse_all = true;
  602. if(mVerb.empty())
  603. {
  604. read_next_line = true;
  605. LLMemoryStream header((U8*)buf, len);
  606. header >> mVerb;
  607. if((HTTP_VERB_GET == mVerb)
  608. || (HTTP_VERB_POST == mVerb)
  609. || (HTTP_VERB_PUT == mVerb)
  610. || (HTTP_VERB_DELETE == mVerb)
  611. || (HTTP_VERB_OPTIONS == mVerb))
  612. {
  613. header >> mAbsPathAndQuery;
  614. header >> mVersion;
  615. lldebugs << "http request: "
  616. << mVerb
  617. << " " << mAbsPathAndQuery
  618. << " " << mVersion << llendl;
  619. std::string::size_type delimiter
  620. = mAbsPathAndQuery.find('?');
  621. if (delimiter == std::string::npos)
  622. {
  623. mPath = mAbsPathAndQuery;
  624. mQuery = "";
  625. }
  626. else
  627. {
  628. mPath = mAbsPathAndQuery.substr(0, delimiter);
  629. mQuery = mAbsPathAndQuery.substr(delimiter+1);
  630. }
  631. if(!mAbsPathAndQuery.empty())
  632. {
  633. if(mVersion.empty())
  634. {
  635. // simple request.
  636. parse_all = false;
  637. mState = STATE_DONE;
  638. mVersion.assign("HTTP/1.0");
  639. }
  640. }
  641. }
  642. else
  643. {
  644. read_next_line = false;
  645. parse_all = false;
  646. lldebugs << "unknown http verb: " << mVerb << llendl;
  647. markBad(channels, buffer);
  648. }
  649. }
  650. if(parse_all)
  651. {
  652. bool keep_parsing = true;
  653. while(keep_parsing)
  654. {
  655. if(read_next_line)
  656. {
  657. len = HEADER_BUFFER_SIZE;
  658. if (!readHeaderLine(channels, buffer, (U8*)buf, len))
  659. {
  660. // Failed to read the header line, probably too long.
  661. // readHeaderLine already marked the channel/buffer as bad.
  662. keep_parsing = false;
  663. break;
  664. }
  665. }
  666. if(0 == len)
  667. {
  668. return status;
  669. }
  670. if(buf[0] == '\r' && buf[1] == '\n')
  671. {
  672. // end-o-headers
  673. keep_parsing = false;
  674. mState = STATE_LOOKING_FOR_EOS;
  675. break;
  676. }
  677. char* pos_colon = strchr(buf, ':');
  678. if(NULL == pos_colon)
  679. {
  680. keep_parsing = false;
  681. lldebugs << "bad header: " << buf << llendl;
  682. markBad(channels, buffer);
  683. break;
  684. }
  685. // we've found a header
  686. read_next_line = true;
  687. std::string name(buf, pos_colon - buf);
  688. std::string value(pos_colon + 2);
  689. LLStringUtil::toLower(name);
  690. if("content-length" == name)
  691. {
  692. lldebugs << "Content-Length: " << value << llendl;
  693. mContentLength = atoi(value.c_str());
  694. }
  695. else
  696. {
  697. LLStringUtil::trimTail(value);
  698. mHeaders[name] = value;
  699. }
  700. }
  701. }
  702. }
  703. }
  704. PUMP_DEBUG;
  705. // look for the end of stream based on
  706. if(STATE_LOOKING_FOR_EOS == mState)
  707. {
  708. if(0 == mContentLength)
  709. {
  710. mState = STATE_DONE;
  711. }
  712. else if(buffer->countAfter(channels.in(), mLastRead) >= mContentLength)
  713. {
  714. mState = STATE_DONE;
  715. }
  716. // else more bytes should be coming.
  717. }
  718. PUMP_DEBUG;
  719. if(STATE_DONE == mState)
  720. {
  721. // hey, hey, we should have everything now, so we pass it to
  722. // a content handler.
  723. context[CONTEXT_REQUEST][CONTEXT_VERB] = mVerb;
  724. const LLHTTPNode* node = mRootNode.traverse(mPath, context);
  725. if(node)
  726. {
  727. //llinfos << "LLHTTPResponder::process_impl found node for "
  728. // << mAbsPathAndQuery << llendl;
  729. // Copy everything after mLast read to the out.
  730. LLBufferArray::segment_iterator_t seg_iter;
  731. buffer->lock();
  732. seg_iter = buffer->splitAfter(mLastRead);
  733. if(seg_iter != buffer->endSegment())
  734. {
  735. LLChangeChannel change(channels.in(), channels.out());
  736. ++seg_iter;
  737. std::for_each(seg_iter, buffer->endSegment(), change);
  738. #if 0
  739. seg_iter = buffer->beginSegment();
  740. char buf[1024]; /*Flawfinder: ignore*/
  741. while(seg_iter != buffer->endSegment())
  742. {
  743. memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
  744. buf[(*seg_iter).size()] = '\0';
  745. llinfos << (*seg_iter).getChannel() << ": " << buf
  746. << llendl;
  747. ++seg_iter;
  748. }
  749. #endif
  750. }
  751. buffer->unlock();
  752. //
  753. // *FIX: get rid of extra bytes off the end
  754. //
  755. // Set up a chain which will prepend a content length and
  756. // HTTP headers.
  757. LLPumpIO::chain_t chain;
  758. chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
  759. context[CONTEXT_REQUEST]["path"] = mPath;
  760. context[CONTEXT_REQUEST]["query-string"] = mQuery;
  761. context[CONTEXT_REQUEST]["remote-host"]
  762. = mBuildContext["remote-host"];
  763. context[CONTEXT_REQUEST]["remote-port"]
  764. = mBuildContext["remote-port"];
  765. context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
  766. const LLChainIOFactory* protocolHandler
  767. = node->getProtocolHandler();
  768. if (protocolHandler)
  769. {
  770. lldebugs << "HTTP context: " << context << llendl;
  771. protocolHandler->build(chain, context);
  772. }
  773. else
  774. {
  775. // this is a simple LLHTTPNode, so use LLHTTPPipe
  776. chain.push_back(LLIOPipe::ptr_t(new LLHTTPPipe(*node)));
  777. }
  778. // Add the header - which needs to have the same
  779. // channel information as the link before it since it
  780. // is part of the response.
  781. LLIOPipe* header = new LLHTTPResponseHeader;
  782. chain.push_back(LLIOPipe::ptr_t(header));
  783. // We need to copy all of the pipes _after_ this so
  784. // that the response goes out correctly.
  785. LLPumpIO::links_t current_links;
  786. pump->copyCurrentLinkInfo(current_links);
  787. LLPumpIO::links_t::iterator link_iter = current_links.begin();
  788. LLPumpIO::links_t::iterator links_end = current_links.end();
  789. bool after_this = false;
  790. for(; link_iter < links_end; ++link_iter)
  791. {
  792. if(after_this)
  793. {
  794. chain.push_back((*link_iter).mPipe);
  795. }
  796. else if(this == (*link_iter).mPipe.get())
  797. {
  798. after_this = true;
  799. }
  800. }
  801. // Do the final build of the chain, and send it on
  802. // it's way.
  803. LLChannelDescriptors chnl = channels;
  804. LLPumpIO::LLLinkInfo link;
  805. LLPumpIO::links_t links;
  806. LLPumpIO::chain_t::iterator it = chain.begin();
  807. LLPumpIO::chain_t::iterator end = chain.end();
  808. while(it != end)
  809. {
  810. link.mPipe = *it;
  811. link.mChannels = chnl;
  812. links.push_back(link);
  813. chnl = LLBufferArray::makeChannelConsumer(chnl);
  814. ++it;
  815. }
  816. pump->addChain(
  817. links,
  818. buffer,
  819. context,
  820. DEFAULT_CHAIN_EXPIRY_SECS);
  821. status = STATUS_STOP;
  822. }
  823. else
  824. {
  825. llwarns << "LLHTTPResponder::process_impl didn't find a node for "
  826. << mAbsPathAndQuery << llendl;
  827. LLBufferStream str(channels, buffer.get());
  828. mState = STATE_SHORT_CIRCUIT;
  829. str << HTTP_VERSION_STR << " 404 Not Found\r\n\r\n<html>\n"
  830. << "<title>Not Found</title>\n<body>\nNode '" << mAbsPathAndQuery
  831. << "' not found.\n</body>\n</html>\n";
  832. }
  833. }
  834. if(STATE_SHORT_CIRCUIT == mState)
  835. {
  836. //status = mNext->process(buffer, true, pump, context);
  837. status = STATUS_DONE;
  838. }
  839. PUMP_DEBUG;
  840. return status;
  841. }
  842. // static
  843. void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain,
  844. const LLHTTPNode& root, const LLSD& ctx)
  845. {
  846. chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
  847. }
  848. class LLHTTPResponseFactory : public LLChainIOFactory
  849. {
  850. public:
  851. bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
  852. {
  853. LLIOHTTPServer::createPipe(chain, mTree, ctx);
  854. return true;
  855. }
  856. LLHTTPNode& getRootNode() { return mTree; }
  857. private:
  858. LLHTTPNode mTree;
  859. };
  860. // static
  861. LLHTTPNode& LLIOHTTPServer::create(
  862. apr_pool_t* pool, LLPumpIO& pump, U16 port)
  863. {
  864. LLSocket::ptr_t socket = LLSocket::create(
  865. pool,
  866. LLSocket::STREAM_TCP,
  867. port);
  868. if(!socket)
  869. {
  870. llerrs << "Unable to initialize socket" << llendl;
  871. }
  872. LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
  873. boost::shared_ptr<LLChainIOFactory> factory_ptr(factory);
  874. LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr);
  875. LLPumpIO::chain_t chain;
  876. chain.push_back(LLIOPipe::ptr_t(server));
  877. pump.addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  878. return factory->getRootNode();
  879. }
  880. // static
  881. void LLIOHTTPServer::setTimingCallback(timing_callback_t callback,
  882. void* data)
  883. {
  884. sTimingCallback = callback;
  885. sTimingCallbackData = data;
  886. }