lliohttpserver.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:24k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  8.  * 
  9.  * Copyright (c) 2005-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #include "linden_common.h"
  35. #include "lliohttpserver.h"
  36. #include "llapr.h"
  37. #include "llbuffer.h"
  38. #include "llbufferstream.h"
  39. #include "llhttpnode.h"
  40. #include "lliopipe.h"
  41. #include "lliosocket.h"
  42. #include "llioutil.h"
  43. #include "llmemtype.h"
  44. #include "llmemorystream.h"
  45. #include "llpumpio.h"
  46. #include "llsd.h"
  47. #include "llsdserialize_xml.h"
  48. #include "llstat.h"
  49. #include "llstl.h"
  50. #include "lltimer.h"
  51. #include <sstream>
  52. #include <boost/tokenizer.hpp>
  53. static const char HTTP_VERSION_STR[] = "HTTP/1.0";
  54. const std::string CONTEXT_REQUEST("request");
  55. const std::string CONTEXT_RESPONSE("response");
  56. const std::string CONTEXT_VERB("verb");
  57. const std::string CONTEXT_HEADERS("headers");
  58. const std::string HTTP_VERB_GET("GET");
  59. const std::string HTTP_VERB_PUT("PUT");
  60. const std::string HTTP_VERB_POST("POST");
  61. const std::string HTTP_VERB_DELETE("DELETE");
  62. const std::string HTTP_VERB_OPTIONS("OPTIONS");
  63. static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL;
  64. static void* sTimingCallbackData = NULL;
  65. class LLHTTPPipe : public LLIOPipe
  66. {
  67. public:
  68. LLHTTPPipe(const LLHTTPNode& node)
  69. : mNode(node),
  70.   mResponse(NULL),
  71.   mState(STATE_INVOKE),
  72.   mChainLock(0),
  73.   mLockedPump(NULL),
  74.   mStatusCode(0)
  75. { }
  76. virtual ~LLHTTPPipe()
  77. {
  78. if (mResponse.notNull())
  79. {
  80. mResponse->nullPipe();
  81. }
  82. }
  83. private:
  84. // LLIOPipe API implementation.
  85. virtual EStatus process_impl(
  86.         const LLChannelDescriptors& channels,
  87.         LLIOPipe::buffer_ptr_t& buffer,
  88.         bool& eos,
  89.         LLSD& context,
  90.         LLPumpIO* pump);
  91. const LLHTTPNode& mNode;
  92. class Response : public LLHTTPNode::Response
  93. {
  94. public:
  95. static LLPointer<Response> create(LLHTTPPipe* pipe);
  96. virtual ~Response();
  97. // from LLHTTPNode::Response
  98. virtual void result(const LLSD&);
  99. virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
  100. virtual void status(S32 code, const std::string& message);
  101. void nullPipe();
  102. private:
  103. Response() : mPipe(NULL) {} // Must be accessed through LLPointer.
  104. LLHTTPPipe* mPipe;
  105. };
  106. friend class Response;
  107. LLPointer<Response> mResponse;
  108. enum State
  109. {
  110. STATE_INVOKE,
  111. STATE_DELAYED,
  112. STATE_LOCKED,
  113. STATE_GOOD_RESULT,
  114. STATE_STATUS_RESULT,
  115. STATE_EXTENDED_RESULT
  116. };
  117. State mState;
  118. S32 mChainLock;
  119. LLPumpIO* mLockedPump;
  120. void lockChain(LLPumpIO*);
  121. void unlockChain();
  122. LLSD mGoodResult;
  123. S32 mStatusCode;
  124. std::string mStatusMessage;
  125. LLSD mHeaders;
  126. };
  127. LLIOPipe::EStatus LLHTTPPipe::process_impl(
  128. const LLChannelDescriptors& channels,
  129.     buffer_ptr_t& buffer,
  130.     bool& eos,
  131.     LLSD& context,
  132.     LLPumpIO* pump)
  133. {
  134. PUMP_DEBUG;
  135.     lldebugs << "LLSDHTTPServer::process_impl" << llendl;
  136.     // Once we have all the data, We need to read the sd on
  137.     // the the in channel, and respond on  the out channel
  138.     if(!eos) return STATUS_BREAK;
  139.     if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
  140. PUMP_DEBUG;
  141. if (mState == STATE_INVOKE)
  142. {
  143. PUMP_DEBUG;
  144. mState = STATE_DELAYED;
  145. // assume deferred unless mResponse does otherwise
  146. mResponse = Response::create(this);
  147. // *TODO: Babbage: Parameterize parser?
  148. // *TODO: We should look at content-type and do the right
  149. // thing. Phoenix 2007-12-31
  150. LLBufferStream istr(channels, buffer.get());
  151. static LLTimer timer;
  152. timer.reset();
  153. std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
  154. if(verb == HTTP_VERB_GET)
  155. {
  156.             LLPerfBlock getblock("http_get");   
  157. mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
  158. }
  159. else if(verb == HTTP_VERB_PUT)
  160. {
  161.             LLPerfBlock putblock("http_put");
  162. LLSD input;
  163. if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
  164. {
  165. LLSDSerialize::fromXML(input, istr);
  166. }
  167. else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
  168. {
  169. std::stringstream strstrm;
  170. strstrm << istr.rdbuf();
  171. input = strstrm.str();
  172. }
  173. mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
  174. }
  175. else if(verb == HTTP_VERB_POST)
  176. {
  177.             LLPerfBlock postblock("http_post");
  178. LLSD input;
  179. if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
  180. {
  181. LLSDSerialize::fromXML(input, istr);
  182. }
  183. else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
  184. {
  185. std::stringstream strstrm;
  186. strstrm << istr.rdbuf();
  187. input = strstrm.str();
  188. }
  189. mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
  190. }
  191. else if(verb == HTTP_VERB_DELETE)
  192. {
  193.             LLPerfBlock delblock("http_delete");
  194. mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
  195. }
  196. else if(verb == HTTP_VERB_OPTIONS)
  197. {
  198. mNode.options(LLHTTPNode::ResponsePtr(mResponse), context);
  199. }
  200. else 
  201. {
  202.     mResponse->methodNotAllowed();
  203. }
  204. F32 delta = timer.getElapsedTimeF32();
  205. if (sTimingCallback)
  206. {
  207. LLHTTPNode::Description desc;
  208. mNode.describe(desc);
  209. LLSD info = desc.getInfo();
  210. std::string timing_name = info["description"];
  211. timing_name += " ";
  212. timing_name += verb;
  213. sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
  214. }
  215. // Log all HTTP transactions.
  216. // TODO: Add a way to log these to their own file instead of indra.log
  217. // It is just too spammy to be in indra.log.
  218. lldebugs << verb << " " << context[CONTEXT_REQUEST]["path"].asString()
  219. << " " << mStatusCode << " " <<  mStatusMessage << " " << delta
  220. << "s" << llendl;
  221. // Log Internal Server Errors
  222. //if(mStatusCode == 500)
  223. //{
  224. // llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error" 
  225. // << llendl;
  226. //}
  227. }
  228. PUMP_DEBUG;
  229. switch (mState)
  230. {
  231. case STATE_DELAYED:
  232. lockChain(pump);
  233. mState = STATE_LOCKED;
  234. return STATUS_BREAK;
  235. case STATE_LOCKED:
  236. // should never ever happen!
  237. return STATUS_ERROR;
  238. case STATE_GOOD_RESULT:
  239. {
  240. LLSD headers = mHeaders;
  241. headers["Content-Type"] = "application/llsd+xml";
  242. context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
  243. LLBufferStream ostr(channels, buffer.get());
  244. LLSDSerialize::toXML(mGoodResult, ostr);
  245. return STATUS_DONE;
  246. }
  247. case STATE_STATUS_RESULT:
  248. {
  249. LLSD headers = mHeaders;
  250. headers["Content-Type"] = "text/plain";
  251. context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
  252. context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
  253. context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
  254. LLBufferStream ostr(channels, buffer.get());
  255. ostr << mStatusMessage;
  256. return STATUS_DONE;
  257. }
  258. case STATE_EXTENDED_RESULT:
  259. {
  260. context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = mHeaders;
  261. context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
  262. LLBufferStream ostr(channels, buffer.get());
  263. ostr << mStatusMessage;
  264. return STATUS_DONE;
  265. }
  266. default:
  267. llwarns << "LLHTTPPipe::process_impl: unexpected state "
  268. << mState << llendl;
  269. return STATUS_BREAK;
  270. }
  271. //  PUMP_DEBUG; // unreachable
  272. }
  273. LLPointer<LLHTTPPipe::Response> LLHTTPPipe::Response::create(LLHTTPPipe* pipe)
  274. {
  275. LLPointer<Response> result = new Response();
  276. result->mPipe = pipe;
  277. return result;
  278. }
  279. // virtual
  280. LLHTTPPipe::Response::~Response()
  281. {
  282. }
  283. void LLHTTPPipe::Response::nullPipe()
  284. {
  285. mPipe = NULL;
  286. }
  287. // virtual
  288. void LLHTTPPipe::Response::result(const LLSD& r)
  289. {
  290. if(! mPipe)
  291. {
  292. llwarns << "LLHTTPPipe::Response::result: NULL pipe" << llendl;
  293. return;
  294. }
  295. mPipe->mStatusCode = 200;
  296. mPipe->mStatusMessage = "OK";
  297. mPipe->mGoodResult = r;
  298. mPipe->mState = STATE_GOOD_RESULT;
  299. mPipe->mHeaders = mHeaders;
  300. mPipe->unlockChain();
  301. }
  302. void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
  303. {
  304. if(! mPipe)
  305. {
  306. llwarns << "LLHTTPPipe::Response::status: NULL pipe" << llendl;
  307. return;
  308. }
  309. mPipe->mStatusCode = code;
  310. mPipe->mStatusMessage = body;
  311. mPipe->mHeaders = headers;
  312. mPipe->mState = STATE_EXTENDED_RESULT;
  313. mPipe->unlockChain();
  314. }
  315. // virtual
  316. void LLHTTPPipe::Response::status(S32 code, const std::string& message)
  317. {
  318. if(! mPipe)
  319. {
  320. llwarns << "LLHTTPPipe::Response::status: NULL pipe" << llendl;
  321. return;
  322. }
  323. mPipe->mStatusCode = code;
  324. mPipe->mStatusMessage = message;
  325. mPipe->mState = STATE_STATUS_RESULT;
  326. mPipe->mHeaders = mHeaders;
  327. mPipe->unlockChain();
  328. }
  329. void LLHTTPPipe::lockChain(LLPumpIO* pump)
  330. {
  331. if (mChainLock != 0) { return; }
  332. mLockedPump = pump;
  333. mChainLock = pump->setLock();
  334. }
  335. void LLHTTPPipe::unlockChain()
  336. {
  337. if (mChainLock == 0) { return; }
  338. mLockedPump->clearLock(mChainLock);
  339. mLockedPump = NULL;
  340. mChainLock = 0;
  341. }
  342. /** 
  343.  * @class LLHTTPResponseHeader
  344.  * @brief Class which correctly builds HTTP headers on a pipe
  345.  * @see LLIOPipe
  346.  *
  347.  * An instance of this class can be placed in a chain where it will
  348.  * wait for an end of stream. Once it gets that, it will count the
  349.  * bytes on CHANNEL_OUT (or the size of the buffer in io pipe versions
  350.  * prior to 2) prepend that data to the request in an HTTP format, and
  351.  * supply all normal HTTP response headers.
  352.  */
  353. class LLHTTPResponseHeader : public LLIOPipe
  354. {
  355. public:
  356. LLHTTPResponseHeader() : mCode(0) {}
  357. virtual ~LLHTTPResponseHeader() {}
  358. protected:
  359. /* @name LLIOPipe virtual implementations
  360.  */
  361. //@{
  362. /** 
  363.  * @brief Process the data in buffer
  364.  */
  365. EStatus process_impl(
  366. const LLChannelDescriptors& channels,
  367. buffer_ptr_t& buffer,
  368. bool& eos,
  369. LLSD& context,
  370. LLPumpIO* pump);
  371. //@}
  372. protected:
  373. S32 mCode;
  374. };
  375. /**
  376.  * LLHTTPResponseHeader
  377.  */
  378. // virtual
  379. LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
  380. const LLChannelDescriptors& channels,
  381. buffer_ptr_t& buffer,
  382. bool& eos,
  383. LLSD& context,
  384. LLPumpIO* pump)
  385. {
  386. PUMP_DEBUG;
  387. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  388. if(eos)
  389. {
  390. PUMP_DEBUG;
  391. //mGotEOS = true;
  392. std::ostringstream ostr;
  393. std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
  394. int code = context[CONTEXT_RESPONSE]["statusCode"];
  395. if (code < 200)
  396. {
  397. code = 200;
  398. message = "OK";
  399. }
  400. ostr << HTTP_VERSION_STR << " " << code << " " << message << "rn";
  401. S32 content_length = buffer->countAfter(channels.in(), NULL);
  402. if(0 < content_length)
  403. {
  404. ostr << "Content-Length: " << content_length << "rn";
  405. }
  406. // *NOTE: This guard can go away once the LLSD static map
  407. // iterator is available. Phoenix. 2008-05-09
  408. LLSD headers = context[CONTEXT_RESPONSE][CONTEXT_HEADERS];
  409. if(headers.isDefined())
  410. {
  411. LLSD::map_iterator iter = headers.beginMap();
  412. LLSD::map_iterator end = headers.endMap();
  413. for(; iter != end; ++iter)
  414. {
  415. ostr << (*iter).first << ": " << (*iter).second.asString()
  416. << "rn";
  417. }
  418. }
  419. ostr << "rn";
  420. LLChangeChannel change(channels.in(), channels.out());
  421. std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
  422. std::string header = ostr.str();
  423. buffer->prepend(channels.out(), (U8*)header.c_str(), header.size());
  424. PUMP_DEBUG;
  425. return STATUS_DONE;
  426. }
  427. PUMP_DEBUG;
  428. return STATUS_OK;
  429. }
  430. /** 
  431.  * @class LLHTTPResponder
  432.  * @brief This class 
  433.  * @see LLIOPipe
  434.  *
  435.  * <b>NOTE:</b> You should not need to create or use one of these, the
  436.  * details are handled by the HTTPResponseFactory.
  437.  */
  438. class LLHTTPResponder : public LLIOPipe
  439. {
  440. public:
  441. LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
  442. ~LLHTTPResponder();
  443. protected:
  444. /** 
  445.  * @brief Read data off of CHANNEL_IN keeping track of last read position.
  446.  *
  447.  * This is a quick little hack to read headers. It is not IO
  448.  * optimal, but it makes it easier for me to implement the header
  449.  * parsing. Plus, there should never be more than a few headers.
  450.  * This method will tend to read more than necessary, find the
  451.  * newline, make the front part of dest look like a c string, and
  452.  * move the read head back to where the newline was found. Thus,
  453.  * the next read will pick up on the next line.
  454.  * @param channel The channel to read in the buffer
  455.  * @param buffer The heap array of processed data
  456.  * @param dest Destination for the data to be read
  457.  * @param[in,out] len <b>in</b> The size of the buffer. <b>out</b> how 
  458.  * much was read. This value is not useful for determining where to 
  459.  * seek orfor string assignment.
  460.  * @returns Returns true if a line was found.
  461.  */
  462. bool readHeaderLine(
  463. const LLChannelDescriptors& channels,
  464. buffer_ptr_t buffer,
  465. U8* dest,
  466. S32& len);
  467. /** 
  468.  * @brief Mark the request as bad, and handle appropriately
  469.  *
  470.  * @param channels The channels to use in the buffer.
  471.  * @param buffer The heap array of processed data.
  472.  */
  473. void markBad(const LLChannelDescriptors& channels, buffer_ptr_t buffer);
  474. protected:
  475. /* @name LLIOPipe virtual implementations
  476.  */
  477. //@{
  478. /** 
  479.  * @brief Process the data in buffer
  480.  */
  481. EStatus process_impl(
  482. const LLChannelDescriptors& channels,
  483. buffer_ptr_t& buffer,
  484. bool& eos,
  485. LLSD& context,
  486. LLPumpIO* pump);
  487. //@}
  488. protected:
  489. enum EState
  490. {
  491. STATE_NOTHING,
  492. STATE_READING_HEADERS,
  493. STATE_LOOKING_FOR_EOS,
  494. STATE_DONE,
  495. STATE_SHORT_CIRCUIT
  496. };
  497. LLSD mBuildContext;
  498. EState mState;
  499. U8* mLastRead;
  500. std::string mVerb;
  501. std::string mAbsPathAndQuery;
  502. std::string mPath;
  503. std::string mQuery;
  504. std::string mVersion;
  505. S32 mContentLength;
  506. LLSD mHeaders;
  507. // handle the urls
  508. const LLHTTPNode& mRootNode;
  509. };
  510. LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx) :
  511. mBuildContext(ctx),
  512. mState(STATE_NOTHING),
  513. mLastRead(NULL),
  514. mContentLength(0),
  515. mRootNode(tree)
  516. {
  517. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  518. }
  519. // virtual
  520. LLHTTPResponder::~LLHTTPResponder()
  521. {
  522. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  523. //lldebugs << "destroying LLHTTPResponder" << llendl;
  524. }
  525. bool LLHTTPResponder::readHeaderLine(
  526. const LLChannelDescriptors& channels,
  527. buffer_ptr_t buffer,
  528. U8* dest,
  529. S32& len)
  530. {
  531. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  532. --len;
  533. U8* last = buffer->readAfter(channels.in(), mLastRead, dest, len);
  534. dest[len] = '';
  535. U8* newline = (U8*)strchr((char*)dest, 'n');
  536. if(!newline)
  537. {
  538. if(len)
  539. {
  540. lldebugs << "readLine failed - too long maybe?" << llendl;
  541. markBad(channels, buffer);
  542. }
  543. return false;
  544. }
  545. S32 offset = -((len - 1) - (newline - dest));
  546. ++newline;
  547. *newline = '';
  548. mLastRead = buffer->seek(channels.in(), last, offset);
  549. return true;
  550. }
  551. void LLHTTPResponder::markBad(
  552. const LLChannelDescriptors& channels,
  553. buffer_ptr_t buffer)
  554. {
  555. LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
  556. mState = STATE_SHORT_CIRCUIT;
  557. LLBufferStream out(channels, buffer.get());
  558. out << HTTP_VERSION_STR << " 400 Bad Requestrnrn<html>n"
  559. << "<title>Bad Request</title>n<body>nBad Request.n"
  560. << "</body>n</html>n";
  561. }
  562. // virtual
  563. LLIOPipe::EStatus LLHTTPResponder::process_impl(
  564. const LLChannelDescriptors& channels,
  565. buffer_ptr_t& buffer,
  566. bool& eos,
  567. LLSD& context,
  568. LLPumpIO* pump)
  569. {
  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()] = '';
  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. seg_iter = buffer->splitAfter(mLastRead);
  732. if(seg_iter != buffer->endSegment())
  733. {
  734. LLChangeChannel change(channels.in(), channels.out());
  735. ++seg_iter;
  736. std::for_each(seg_iter, buffer->endSegment(), change);
  737. #if 0
  738. seg_iter = buffer->beginSegment();
  739. char buf[1024];   /*Flawfinder: ignore*/
  740. while(seg_iter != buffer->endSegment())
  741. {
  742. memcpy(buf, (*seg_iter).data(), (*seg_iter).size());   /*Flawfinder: ignore*/
  743. buf[(*seg_iter).size()] = '';
  744. llinfos << (*seg_iter).getChannel() << ": " << buf
  745. << llendl;
  746. ++seg_iter;
  747. }
  748. #endif
  749. }
  750. //
  751. // *FIX: get rid of extra bytes off the end
  752. //
  753. // Set up a chain which will prepend a content length and
  754. // HTTP headers.
  755. LLPumpIO::chain_t chain;
  756. chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
  757. context[CONTEXT_REQUEST]["path"] = mPath;
  758. context[CONTEXT_REQUEST]["query-string"] = mQuery;
  759. context[CONTEXT_REQUEST]["remote-host"]
  760. = mBuildContext["remote-host"];
  761. context[CONTEXT_REQUEST]["remote-port"]
  762. = mBuildContext["remote-port"];
  763. context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
  764. const LLChainIOFactory* protocolHandler
  765. = node->getProtocolHandler();
  766. if (protocolHandler)
  767. {
  768. lldebugs << "HTTP context: " << context << llendl;
  769. protocolHandler->build(chain, context);
  770. }
  771. else
  772. {
  773. // this is a simple LLHTTPNode, so use LLHTTPPipe
  774. chain.push_back(LLIOPipe::ptr_t(new LLHTTPPipe(*node)));
  775. }
  776. // Add the header - which needs to have the same
  777. // channel information as the link before it since it
  778. // is part of the response.
  779. LLIOPipe* header = new LLHTTPResponseHeader;
  780. chain.push_back(LLIOPipe::ptr_t(header));
  781. // We need to copy all of the pipes _after_ this so
  782. // that the response goes out correctly.
  783. LLPumpIO::links_t current_links;
  784. pump->copyCurrentLinkInfo(current_links);
  785. LLPumpIO::links_t::iterator link_iter = current_links.begin();
  786. LLPumpIO::links_t::iterator links_end = current_links.end();
  787. bool after_this = false;
  788. for(; link_iter < links_end; ++link_iter)
  789. {
  790. if(after_this)
  791. {
  792. chain.push_back((*link_iter).mPipe);
  793. }
  794. else if(this == (*link_iter).mPipe.get())
  795. {
  796. after_this = true;
  797. }
  798. }
  799. // Do the final build of the chain, and send it on
  800. // it's way.
  801. LLChannelDescriptors chnl = channels;
  802. LLPumpIO::LLLinkInfo link;
  803. LLPumpIO::links_t links;
  804. LLPumpIO::chain_t::iterator it = chain.begin();
  805. LLPumpIO::chain_t::iterator end = chain.end();
  806. while(it != end)
  807. {
  808. link.mPipe = *it;
  809. link.mChannels = chnl;
  810. links.push_back(link);
  811. chnl = LLBufferArray::makeChannelConsumer(chnl);
  812. ++it;
  813. }
  814. pump->addChain(
  815. links,
  816. buffer,
  817. context,
  818. DEFAULT_CHAIN_EXPIRY_SECS);
  819. status = STATUS_STOP;
  820. }
  821. else
  822. {
  823. llwarns << "LLHTTPResponder::process_impl didn't find a node for "
  824. << mAbsPathAndQuery << llendl;
  825. LLBufferStream str(channels, buffer.get());
  826. mState = STATE_SHORT_CIRCUIT;
  827. str << HTTP_VERSION_STR << " 404 Not Foundrnrn<html>n"
  828. << "<title>Not Found</title>n<body>nNode '" << mAbsPathAndQuery
  829. << "' not found.n</body>n</html>n";
  830. }
  831. }
  832. if(STATE_SHORT_CIRCUIT == mState)
  833. {
  834. //status = mNext->process(buffer, true, pump, context);
  835. status = STATUS_DONE;
  836. }
  837. PUMP_DEBUG;
  838. return status;
  839. }
  840. // static 
  841. void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain, 
  842.         const LLHTTPNode& root, const LLSD& ctx)
  843. {
  844. chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
  845. }
  846. class LLHTTPResponseFactory : public LLChainIOFactory
  847. {
  848. public:
  849. bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
  850. {
  851. LLIOHTTPServer::createPipe(chain, mTree, ctx);
  852. return true;
  853. }
  854. LLHTTPNode& getRootNode() { return mTree; }
  855. private:
  856. LLHTTPNode mTree;
  857. };
  858. // static
  859. LLHTTPNode& LLIOHTTPServer::create(
  860. apr_pool_t* pool, LLPumpIO& pump, U16 port)
  861. {
  862. LLSocket::ptr_t socket = LLSocket::create(
  863.         pool,
  864.         LLSocket::STREAM_TCP,
  865.         port);
  866.     if(!socket)
  867.     {
  868.         llerrs << "Unable to initialize socket" << llendl;
  869.     }
  870.     LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
  871. boost::shared_ptr<LLChainIOFactory> factory_ptr(factory);
  872.     LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr);
  873. LLPumpIO::chain_t chain;
  874.     chain.push_back(LLIOPipe::ptr_t(server));
  875.     pump.addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
  876. return factory->getRootNode();
  877. }
  878. // static
  879. void LLIOHTTPServer::setTimingCallback(timing_callback_t callback,
  880.    void* data)
  881. {
  882. sTimingCallback = callback;
  883. sTimingCallbackData = data;
  884. }