summaryrefslogtreecommitdiff
path: root/indra/llmessage/lliohttpserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/lliohttpserver.cpp')
-rw-r--r--indra/llmessage/lliohttpserver.cpp1520
1 files changed, 760 insertions, 760 deletions
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index e302dd2b5e..9791a20743 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliohttpserver.cpp
* @author Phoenix
* @date 2005-10-05
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -58,89 +58,89 @@ static void* sTimingCallbackData = NULL;
class LLHTTPPipe : public LLIOPipe
{
public:
- LLHTTPPipe(const LLHTTPNode& node)
- : mNode(node),
- mResponse(NULL),
- mState(STATE_INVOKE),
- mChainLock(0),
- mLockedPump(NULL),
- mStatusCode(0)
- { }
- virtual ~LLHTTPPipe()
- {
- if (mResponse.notNull())
- {
- mResponse->nullPipe();
- }
- }
+ LLHTTPPipe(const LLHTTPNode& node)
+ : mNode(node),
+ mResponse(NULL),
+ mState(STATE_INVOKE),
+ mChainLock(0),
+ mLockedPump(NULL),
+ mStatusCode(0)
+ { }
+ virtual ~LLHTTPPipe()
+ {
+ if (mResponse.notNull())
+ {
+ mResponse->nullPipe();
+ }
+ }
private:
- // LLIOPipe API implementation.
- virtual EStatus process_impl(
+ // LLIOPipe API implementation.
+ virtual EStatus process_impl(
const LLChannelDescriptors& channels,
LLIOPipe::buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
- const LLHTTPNode& mNode;
-
- class Response : public LLHTTPNode::Response
- {
- public:
-
- static LLPointer<Response> create(LLHTTPPipe* pipe);
- virtual ~Response();
-
- // from LLHTTPNode::Response
- virtual void result(const LLSD&);
- virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
- virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
- virtual void status(S32 code, const std::string& message);
-
- void nullPipe();
-
- private:
- Response() : mPipe(NULL) {} // Must be accessed through LLPointer.
- LLHTTPPipe* mPipe;
- };
- friend class Response;
-
- LLPointer<Response> mResponse;
-
- enum State
- {
- STATE_INVOKE,
- STATE_DELAYED,
- STATE_LOCKED,
- STATE_GOOD_RESULT,
- STATE_STATUS_RESULT,
- STATE_EXTENDED_RESULT,
- STATE_EXTENDED_LLSD_RESULT
- };
- State mState;
-
- S32 mChainLock;
- LLPumpIO* mLockedPump;
-
- void lockChain(LLPumpIO*);
- void unlockChain();
-
- LLSD mResult;
- S32 mStatusCode;
- std::string mStatusMessage;
- LLSD mHeaders;
+ const LLHTTPNode& mNode;
+
+ class Response : public LLHTTPNode::Response
+ {
+ public:
+
+ static LLPointer<Response> create(LLHTTPPipe* pipe);
+ virtual ~Response();
+
+ // from LLHTTPNode::Response
+ virtual void result(const LLSD&);
+ virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
+ virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
+ virtual void status(S32 code, const std::string& message);
+
+ void nullPipe();
+
+ private:
+ Response() : mPipe(NULL) {} // Must be accessed through LLPointer.
+ LLHTTPPipe* mPipe;
+ };
+ friend class Response;
+
+ LLPointer<Response> mResponse;
+
+ enum State
+ {
+ STATE_INVOKE,
+ STATE_DELAYED,
+ STATE_LOCKED,
+ STATE_GOOD_RESULT,
+ STATE_STATUS_RESULT,
+ STATE_EXTENDED_RESULT,
+ STATE_EXTENDED_LLSD_RESULT
+ };
+ State mState;
+
+ S32 mChainLock;
+ LLPumpIO* mLockedPump;
+
+ void lockChain(LLPumpIO*);
+ void unlockChain();
+
+ LLSD mResult;
+ S32 mStatusCode;
+ std::string mStatusMessage;
+ LLSD mHeaders;
};
LLIOPipe::EStatus LLHTTPPipe::process_impl(
- const LLChannelDescriptors& channels,
+ const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
+ PUMP_DEBUG;
LL_DEBUGS() << "LLSDHTTPServer::process_impl" << LL_ENDL;
// Once we have all the data, We need to read the sd on
@@ -149,166 +149,166 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
if(!eos) return STATUS_BREAK;
if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
- PUMP_DEBUG;
- if (mState == STATE_INVOKE)
- {
- PUMP_DEBUG;
- mState = STATE_DELAYED;
- // assume deferred unless mResponse does otherwise
- mResponse = Response::create(this);
-
- // *TODO: Babbage: Parameterize parser?
- // *TODO: We should look at content-type and do the right
- // thing. Phoenix 2007-12-31
- LLBufferStream istr(channels, buffer.get());
-
- static LLTimer timer;
- timer.reset();
-
- std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
- if(verb == HTTP_VERB_GET)
- {
- mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else if(verb == HTTP_VERB_PUT)
- {
- LLSD input;
- if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
- {
- LLSDSerialize::fromXML(input, istr);
- }
- else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
- {
- std::ostringstream strstrm;
- strstrm << istr.rdbuf();
- input = strstrm.str();
- }
- mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
- }
- else if(verb == HTTP_VERB_POST)
- {
- LLSD input;
- if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
- {
- LLSDSerialize::fromXML(input, istr);
- }
- else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
- {
- std::ostringstream strstrm;
- strstrm << istr.rdbuf();
- input = strstrm.str();
- }
- mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
- }
- else if(verb == HTTP_VERB_DELETE)
- {
- mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else if(verb == HTTP_VERB_OPTIONS)
- {
- mNode.options(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else
- {
- mResponse->methodNotAllowed();
- }
-
- F32 delta = timer.getElapsedTimeF32();
- if (sTimingCallback)
- {
- LLHTTPNode::Description desc;
- mNode.describe(desc);
- LLSD info = desc.getInfo();
- std::string timing_name = info["description"];
- timing_name += " ";
- timing_name += verb;
- sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
- }
-
- // Log all HTTP transactions.
- // TODO: Add a way to log these to their own file instead of indra.log
- // It is just too spammy to be in indra.log.
- LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
- << " " << mStatusCode << " " << mStatusMessage << " " << delta
- << "s" << LL_ENDL;
-
- // Log Internal Server Errors
- //if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
- //{
- // LL_WARNS() << "LLHTTPPipe::process_impl:500:Internal Server Error"
- // << LL_ENDL;
- //}
- }
-
- PUMP_DEBUG;
- switch (mState)
- {
- case STATE_DELAYED:
- lockChain(pump);
- mState = STATE_LOCKED;
- return STATUS_BREAK;
-
- case STATE_LOCKED:
- // should never ever happen!
- return STATUS_ERROR;
-
- case STATE_GOOD_RESULT:
- {
- LLSD headers = mHeaders;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
- LLBufferStream ostr(channels, buffer.get());
- LLSDSerialize::toXML(mResult, ostr);
-
- return STATUS_DONE;
- }
-
- case STATE_STATUS_RESULT:
- {
- LLSD headers = mHeaders;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
- context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
- context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
- LLBufferStream ostr(channels, buffer.get());
- ostr << mStatusMessage;
-
- return STATUS_DONE;
- }
- case STATE_EXTENDED_RESULT:
- {
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = mHeaders;
- context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
- LLBufferStream ostr(channels, buffer.get());
- ostr << mStatusMessage;
-
- return STATUS_DONE;
- }
- case STATE_EXTENDED_LLSD_RESULT:
- {
- LLSD headers = mHeaders;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
- context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
- LLBufferStream ostr(channels, buffer.get());
- LLSDSerialize::toXML(mResult, ostr);
-
- return STATUS_DONE;
- }
- default:
- LL_WARNS() << "LLHTTPPipe::process_impl: unexpected state "
- << mState << LL_ENDL;
-
- return STATUS_BREAK;
- }
-// PUMP_DEBUG; // unreachable
+ PUMP_DEBUG;
+ if (mState == STATE_INVOKE)
+ {
+ PUMP_DEBUG;
+ mState = STATE_DELAYED;
+ // assume deferred unless mResponse does otherwise
+ mResponse = Response::create(this);
+
+ // *TODO: Babbage: Parameterize parser?
+ // *TODO: We should look at content-type and do the right
+ // thing. Phoenix 2007-12-31
+ LLBufferStream istr(channels, buffer.get());
+
+ static LLTimer timer;
+ timer.reset();
+
+ std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
+ if(verb == HTTP_VERB_GET)
+ {
+ mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else if(verb == HTTP_VERB_PUT)
+ {
+ LLSD input;
+ if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
+ {
+ LLSDSerialize::fromXML(input, istr);
+ }
+ else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
+ {
+ std::ostringstream strstrm;
+ strstrm << istr.rdbuf();
+ input = strstrm.str();
+ }
+ mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
+ }
+ else if(verb == HTTP_VERB_POST)
+ {
+ LLSD input;
+ if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
+ {
+ LLSDSerialize::fromXML(input, istr);
+ }
+ else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
+ {
+ std::ostringstream strstrm;
+ strstrm << istr.rdbuf();
+ input = strstrm.str();
+ }
+ mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
+ }
+ else if(verb == HTTP_VERB_DELETE)
+ {
+ mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else if(verb == HTTP_VERB_OPTIONS)
+ {
+ mNode.options(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else
+ {
+ mResponse->methodNotAllowed();
+ }
+
+ F32 delta = timer.getElapsedTimeF32();
+ if (sTimingCallback)
+ {
+ LLHTTPNode::Description desc;
+ mNode.describe(desc);
+ LLSD info = desc.getInfo();
+ std::string timing_name = info["description"];
+ timing_name += " ";
+ timing_name += verb;
+ sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
+ }
+
+ // Log all HTTP transactions.
+ // TODO: Add a way to log these to their own file instead of indra.log
+ // It is just too spammy to be in indra.log.
+ LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
+ << " " << mStatusCode << " " << mStatusMessage << " " << delta
+ << "s" << LL_ENDL;
+
+ // Log Internal Server Errors
+ //if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
+ //{
+ // LL_WARNS() << "LLHTTPPipe::process_impl:500:Internal Server Error"
+ // << LL_ENDL;
+ //}
+ }
+
+ PUMP_DEBUG;
+ switch (mState)
+ {
+ case STATE_DELAYED:
+ lockChain(pump);
+ mState = STATE_LOCKED;
+ return STATUS_BREAK;
+
+ case STATE_LOCKED:
+ // should never ever happen!
+ return STATUS_ERROR;
+
+ case STATE_GOOD_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ LLBufferStream ostr(channels, buffer.get());
+ LLSDSerialize::toXML(mResult, ostr);
+
+ return STATUS_DONE;
+ }
+
+ case STATE_STATUS_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << mStatusMessage;
+
+ return STATUS_DONE;
+ }
+ case STATE_EXTENDED_RESULT:
+ {
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = mHeaders;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << mStatusMessage;
+
+ return STATUS_DONE;
+ }
+ case STATE_EXTENDED_LLSD_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ LLBufferStream ostr(channels, buffer.get());
+ LLSDSerialize::toXML(mResult, ostr);
+
+ return STATUS_DONE;
+ }
+ default:
+ LL_WARNS() << "LLHTTPPipe::process_impl: unexpected state "
+ << mState << LL_ENDL;
+
+ return STATUS_BREAK;
+ }
+// PUMP_DEBUG; // unreachable
}
LLPointer<LLHTTPPipe::Response> LLHTTPPipe::Response::create(LLHTTPPipe* pipe)
{
- LLPointer<Response> result = new Response();
- result->mPipe = pipe;
- return result;
+ LLPointer<Response> result = new Response();
+ result->mPipe = pipe;
+ return result;
}
// virtual
@@ -318,93 +318,93 @@ LLHTTPPipe::Response::~Response()
void LLHTTPPipe::Response::nullPipe()
{
- mPipe = NULL;
+ mPipe = NULL;
}
// virtual
void LLHTTPPipe::Response::result(const LLSD& r)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::result: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = HTTP_OK;
- mPipe->mStatusMessage = "OK";
- mPipe->mResult = r;
- mPipe->mState = STATE_GOOD_RESULT;
- mPipe->mHeaders = mHeaders;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::result: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = HTTP_OK;
+ mPipe->mStatusMessage = "OK";
+ mPipe->mResult = r;
+ mPipe->mState = STATE_GOOD_RESULT;
+ mPipe->mHeaders = mHeaders;
+ mPipe->unlockChain();
}
void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = code;
- mPipe->mStatusMessage = "(LLSD)";
- mPipe->mResult = r;
- mPipe->mHeaders = headers;
- mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = "(LLSD)";
+ mPipe->mResult = r;
+ mPipe->mHeaders = headers;
+ mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
+ mPipe->unlockChain();
}
void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = code;
- mPipe->mStatusMessage = body;
- mPipe->mHeaders = headers;
- mPipe->mState = STATE_EXTENDED_RESULT;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = body;
+ mPipe->mHeaders = headers;
+ mPipe->mState = STATE_EXTENDED_RESULT;
+ mPipe->unlockChain();
}
// virtual
void LLHTTPPipe::Response::status(S32 code, const std::string& message)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = code;
- mPipe->mStatusMessage = message;
- mPipe->mState = STATE_STATUS_RESULT;
- mPipe->mHeaders = mHeaders;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = message;
+ mPipe->mState = STATE_STATUS_RESULT;
+ mPipe->mHeaders = mHeaders;
+ mPipe->unlockChain();
}
void LLHTTPPipe::lockChain(LLPumpIO* pump)
{
- if (mChainLock != 0) { return; }
+ if (mChainLock != 0) { return; }
- mLockedPump = pump;
- mChainLock = pump->setLock();
+ mLockedPump = pump;
+ mChainLock = pump->setLock();
}
void LLHTTPPipe::unlockChain()
{
- if (mChainLock == 0) { return; }
+ if (mChainLock == 0) { return; }
- mLockedPump->clearLock(mChainLock);
- mLockedPump = NULL;
- mChainLock = 0;
+ mLockedPump->clearLock(mChainLock);
+ mLockedPump = NULL;
+ mChainLock = 0;
}
-/**
+/**
* @class LLHTTPResponseHeader
* @brief Class which correctly builds HTTP headers on a pipe
* @see LLIOPipe
@@ -418,26 +418,26 @@ void LLHTTPPipe::unlockChain()
class LLHTTPResponseHeader : public LLIOPipe
{
public:
- LLHTTPResponseHeader() : mCode(0) {}
- virtual ~LLHTTPResponseHeader() {}
+ LLHTTPResponseHeader() : mCode(0) {}
+ virtual ~LLHTTPResponseHeader() {}
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- S32 mCode;
+ S32 mCode;
};
@@ -447,66 +447,66 @@ protected:
// virtual
LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(eos)
- {
- PUMP_DEBUG;
- //mGotEOS = true;
- std::ostringstream ostr;
- std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
-
- int code = context[CONTEXT_RESPONSE]["statusCode"];
- if (code < HTTP_OK)
- {
- code = HTTP_OK;
- message = "OK";
- }
-
- ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n";
-
- S32 content_length = buffer->countAfter(channels.in(), NULL);
- if(0 < content_length)
- {
- ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
- }
- // *NOTE: This guard can go away once the LLSD static map
- // iterator is available. Phoenix. 2008-05-09
- LLSD headers = context[CONTEXT_RESPONSE][CONTEXT_HEADERS];
- if(headers.isDefined())
- {
- LLSD::map_iterator iter = headers.beginMap();
- LLSD::map_iterator end = headers.endMap();
- for(; iter != end; ++iter)
- {
- ostr << (*iter).first << ": " << (*iter).second.asString()
- << "\r\n";
- }
- }
- ostr << "\r\n";
-
- LLChangeChannel change(channels.in(), channels.out());
- std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
- std::string header = ostr.str();
- buffer->prepend(channels.out(), (U8*)header.c_str(), header.size());
- PUMP_DEBUG;
- return STATUS_DONE;
- }
- PUMP_DEBUG;
- return STATUS_OK;
+ PUMP_DEBUG;
+ if(eos)
+ {
+ PUMP_DEBUG;
+ //mGotEOS = true;
+ std::ostringstream ostr;
+ std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
+
+ int code = context[CONTEXT_RESPONSE]["statusCode"];
+ if (code < HTTP_OK)
+ {
+ code = HTTP_OK;
+ message = "OK";
+ }
+
+ ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n";
+
+ S32 content_length = buffer->countAfter(channels.in(), NULL);
+ if(0 < content_length)
+ {
+ ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
+ }
+ // *NOTE: This guard can go away once the LLSD static map
+ // iterator is available. Phoenix. 2008-05-09
+ LLSD headers = context[CONTEXT_RESPONSE][CONTEXT_HEADERS];
+ if(headers.isDefined())
+ {
+ LLSD::map_iterator iter = headers.beginMap();
+ LLSD::map_iterator end = headers.endMap();
+ for(; iter != end; ++iter)
+ {
+ ostr << (*iter).first << ": " << (*iter).second.asString()
+ << "\r\n";
+ }
+ }
+ ostr << "\r\n";
+
+ LLChangeChannel change(channels.in(), channels.out());
+ std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
+ std::string header = ostr.str();
+ buffer->prepend(channels.out(), (U8*)header.c_str(), header.size());
+ PUMP_DEBUG;
+ return STATUS_DONE;
+ }
+ PUMP_DEBUG;
+ return STATUS_OK;
}
-/**
+/**
* @class LLHTTPResponder
- * @brief This class
+ * @brief This class
* @see LLIOPipe
*
* <b>NOTE:</b> You should not need to create or use one of these, the
@@ -515,464 +515,464 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
class LLHTTPResponder : public LLIOPipe
{
public:
- LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
- ~LLHTTPResponder();
+ LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
+ ~LLHTTPResponder();
protected:
- /**
- * @brief Read data off of CHANNEL_IN keeping track of last read position.
- *
- * This is a quick little hack to read headers. It is not IO
- * optimal, but it makes it easier for me to implement the header
- * parsing. Plus, there should never be more than a few headers.
- * This method will tend to read more than necessary, find the
- * newline, make the front part of dest look like a c string, and
- * move the read head back to where the newline was found. Thus,
- * the next read will pick up on the next line.
- * @param channel The channel to read in the buffer
- * @param buffer The heap array of processed data
- * @param dest Destination for the data to be read
- * @param[in,out] len <b>in</b> The size of the buffer. <b>out</b> how
- * much was read. This value is not useful for determining where to
- * seek orfor string assignment.
- * @returns Returns true if a line was found.
- */
- bool readHeaderLine(
- const LLChannelDescriptors& channels,
- buffer_ptr_t buffer,
- U8* dest,
- S32& len);
-
- /**
- * @brief Mark the request as bad, and handle appropriately
- *
- * @param channels The channels to use in the buffer.
- * @param buffer The heap array of processed data.
- */
- void markBad(const LLChannelDescriptors& channels, buffer_ptr_t buffer);
+ /**
+ * @brief Read data off of CHANNEL_IN keeping track of last read position.
+ *
+ * This is a quick little hack to read headers. It is not IO
+ * optimal, but it makes it easier for me to implement the header
+ * parsing. Plus, there should never be more than a few headers.
+ * This method will tend to read more than necessary, find the
+ * newline, make the front part of dest look like a c string, and
+ * move the read head back to where the newline was found. Thus,
+ * the next read will pick up on the next line.
+ * @param channel The channel to read in the buffer
+ * @param buffer The heap array of processed data
+ * @param dest Destination for the data to be read
+ * @param[in,out] len <b>in</b> The size of the buffer. <b>out</b> how
+ * much was read. This value is not useful for determining where to
+ * seek orfor string assignment.
+ * @returns Returns true if a line was found.
+ */
+ bool readHeaderLine(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t buffer,
+ U8* dest,
+ S32& len);
+
+ /**
+ * @brief Mark the request as bad, and handle appropriately
+ *
+ * @param channels The channels to use in the buffer.
+ * @param buffer The heap array of processed data.
+ */
+ void markBad(const LLChannelDescriptors& channels, buffer_ptr_t buffer);
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- enum EState
- {
- STATE_NOTHING,
- STATE_READING_HEADERS,
- STATE_LOOKING_FOR_EOS,
- STATE_DONE,
- STATE_SHORT_CIRCUIT
- };
-
- LLSD mBuildContext;
- EState mState;
- U8* mLastRead;
- std::string mVerb;
- std::string mAbsPathAndQuery;
- std::string mPath;
- std::string mQuery;
- std::string mVersion;
- S32 mContentLength;
- LLSD mHeaders;
-
- // handle the urls
- const LLHTTPNode& mRootNode;
+ enum EState
+ {
+ STATE_NOTHING,
+ STATE_READING_HEADERS,
+ STATE_LOOKING_FOR_EOS,
+ STATE_DONE,
+ STATE_SHORT_CIRCUIT
+ };
+
+ LLSD mBuildContext;
+ EState mState;
+ U8* mLastRead;
+ std::string mVerb;
+ std::string mAbsPathAndQuery;
+ std::string mPath;
+ std::string mQuery;
+ std::string mVersion;
+ S32 mContentLength;
+ LLSD mHeaders;
+
+ // handle the urls
+ const LLHTTPNode& mRootNode;
};
LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx) :
- mBuildContext(ctx),
- mState(STATE_NOTHING),
- mLastRead(NULL),
- mContentLength(0),
- mRootNode(tree)
+ mBuildContext(ctx),
+ mState(STATE_NOTHING),
+ mLastRead(NULL),
+ mContentLength(0),
+ mRootNode(tree)
{
}
// virtual
LLHTTPResponder::~LLHTTPResponder()
{
- //LL_DEBUGS() << "destroying LLHTTPResponder" << LL_ENDL;
+ //LL_DEBUGS() << "destroying LLHTTPResponder" << LL_ENDL;
}
bool LLHTTPResponder::readHeaderLine(
- const LLChannelDescriptors& channels,
- buffer_ptr_t buffer,
- U8* dest,
- S32& len)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t buffer,
+ U8* dest,
+ S32& len)
{
- --len;
- U8* last = buffer->readAfter(channels.in(), mLastRead, dest, len);
- dest[len] = '\0';
- U8* newline = (U8*)strchr((char*)dest, '\n');
- if(!newline)
- {
- if(len)
- {
- LL_DEBUGS() << "readLine failed - too long maybe?" << LL_ENDL;
- markBad(channels, buffer);
- }
- return false;
- }
- S32 offset = -((len - 1) - (newline - dest));
- ++newline;
- *newline = '\0';
- mLastRead = buffer->seek(channels.in(), last, offset);
- return true;
+ --len;
+ U8* last = buffer->readAfter(channels.in(), mLastRead, dest, len);
+ dest[len] = '\0';
+ U8* newline = (U8*)strchr((char*)dest, '\n');
+ if(!newline)
+ {
+ if(len)
+ {
+ LL_DEBUGS() << "readLine failed - too long maybe?" << LL_ENDL;
+ markBad(channels, buffer);
+ }
+ return false;
+ }
+ S32 offset = -((len - 1) - (newline - dest));
+ ++newline;
+ *newline = '\0';
+ mLastRead = buffer->seek(channels.in(), last, offset);
+ return true;
}
void LLHTTPResponder::markBad(
- const LLChannelDescriptors& channels,
- buffer_ptr_t buffer)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t buffer)
{
- mState = STATE_SHORT_CIRCUIT;
- LLBufferStream out(channels, buffer.get());
- out << HTTP_VERSION_STR << " 400 Bad Request\r\n\r\n<html>\n"
- << "<title>Bad Request</title>\n<body>\nBad Request.\n"
- << "</body>\n</html>\n";
+ mState = STATE_SHORT_CIRCUIT;
+ LLBufferStream out(channels, buffer.get());
+ out << HTTP_VERSION_STR << " 400 Bad Request\r\n\r\n<html>\n"
+ << "<title>Bad Request</title>\n<body>\nBad Request.\n"
+ << "</body>\n</html>\n";
}
// virtual
LLIOPipe::EStatus LLHTTPResponder::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- LLIOPipe::EStatus status = STATUS_OK;
-
- // parsing headers
- if((STATE_NOTHING == mState) || (STATE_READING_HEADERS == mState))
- {
- PUMP_DEBUG;
- status = STATUS_BREAK;
- mState = STATE_READING_HEADERS;
- const S32 HEADER_BUFFER_SIZE = 1024;
- char buf[HEADER_BUFFER_SIZE + 1]; /*Flawfinder: ignore*/
- S32 len = HEADER_BUFFER_SIZE;
+ PUMP_DEBUG;
+ LLIOPipe::EStatus status = STATUS_OK;
+
+ // parsing headers
+ if((STATE_NOTHING == mState) || (STATE_READING_HEADERS == mState))
+ {
+ PUMP_DEBUG;
+ status = STATUS_BREAK;
+ mState = STATE_READING_HEADERS;
+ const S32 HEADER_BUFFER_SIZE = 1024;
+ char buf[HEADER_BUFFER_SIZE + 1]; /*Flawfinder: ignore*/
+ S32 len = HEADER_BUFFER_SIZE;
#if 0
- if(true)
- {
- LLBufferArray::segment_iterator_t seg_iter = buffer->beginSegment();
- char buf[1024]; /*Flawfinder: ignore*/
- while(seg_iter != buffer->endSegment())
- {
- memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
- buf[(*seg_iter).size()] = '\0';
- LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
- << LL_ENDL;
- ++seg_iter;
- }
- }
+ if(true)
+ {
+ LLBufferArray::segment_iterator_t seg_iter = buffer->beginSegment();
+ char buf[1024]; /*Flawfinder: ignore*/
+ while(seg_iter != buffer->endSegment())
+ {
+ memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
+ buf[(*seg_iter).size()] = '\0';
+ LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
+ << LL_ENDL;
+ ++seg_iter;
+ }
+ }
#endif
-
- PUMP_DEBUG;
- if(readHeaderLine(channels, buffer, (U8*)buf, len))
- {
- bool read_next_line = false;
- bool parse_all = true;
- if(mVerb.empty())
- {
- read_next_line = true;
- LLMemoryStream header((U8*)buf, len);
- header >> mVerb;
-
- if((HTTP_VERB_GET == mVerb)
- || (HTTP_VERB_POST == mVerb)
- || (HTTP_VERB_PUT == mVerb)
- || (HTTP_VERB_DELETE == mVerb)
- || (HTTP_VERB_OPTIONS == mVerb))
- {
- header >> mAbsPathAndQuery;
- header >> mVersion;
-
- LL_DEBUGS() << "http request: "
- << mVerb
- << " " << mAbsPathAndQuery
- << " " << mVersion << LL_ENDL;
-
- std::string::size_type delimiter
- = mAbsPathAndQuery.find('?');
- if (delimiter == std::string::npos)
- {
- mPath = mAbsPathAndQuery;
- mQuery = "";
- }
- else
- {
- mPath = mAbsPathAndQuery.substr(0, delimiter);
- mQuery = mAbsPathAndQuery.substr(delimiter+1);
- }
-
- if(!mAbsPathAndQuery.empty())
- {
- if(mVersion.empty())
- {
- // simple request.
- parse_all = false;
- mState = STATE_DONE;
- mVersion.assign("HTTP/1.0");
- }
- }
- }
- else
- {
- read_next_line = false;
- parse_all = false;
- LL_DEBUGS() << "unknown http verb: " << mVerb << LL_ENDL;
- markBad(channels, buffer);
- }
- }
- if(parse_all)
- {
- bool keep_parsing = true;
- while(keep_parsing)
- {
- if(read_next_line)
- {
- len = HEADER_BUFFER_SIZE;
- if (!readHeaderLine(channels, buffer, (U8*)buf, len))
- {
- // Failed to read the header line, probably too long.
- // readHeaderLine already marked the channel/buffer as bad.
- keep_parsing = false;
- break;
- }
- }
- if(0 == len)
- {
- return status;
- }
- if(buf[0] == '\r' && buf[1] == '\n')
- {
- // end-o-headers
- keep_parsing = false;
- mState = STATE_LOOKING_FOR_EOS;
- break;
- }
- char* pos_colon = strchr(buf, ':');
- if(NULL == pos_colon)
- {
- keep_parsing = false;
- LL_DEBUGS() << "bad header: " << buf << LL_ENDL;
- markBad(channels, buffer);
- break;
- }
- // we've found a header
- read_next_line = true;
- std::string name(buf, pos_colon - buf);
- std::string value(pos_colon + 2);
- LLStringUtil::toLower(name);
- if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
- {
- LL_DEBUGS() << "Content-Length: " << value << LL_ENDL;
- mContentLength = atoi(value.c_str());
- }
- else
- {
- LLStringUtil::trimTail(value);
- mHeaders[name] = value;
- }
- }
- }
- }
- }
-
- PUMP_DEBUG;
- // look for the end of stream based on
- if(STATE_LOOKING_FOR_EOS == mState)
- {
- if(0 == mContentLength)
- {
- mState = STATE_DONE;
- }
- else if(buffer->countAfter(channels.in(), mLastRead) >= mContentLength)
- {
- mState = STATE_DONE;
- }
- // else more bytes should be coming.
- }
-
- PUMP_DEBUG;
- if(STATE_DONE == mState)
- {
- // hey, hey, we should have everything now, so we pass it to
- // a content handler.
- context[CONTEXT_REQUEST][CONTEXT_VERB] = mVerb;
- const LLHTTPNode* node = mRootNode.traverse(mPath, context);
- if(node)
- {
- //LL_INFOS() << "LLHTTPResponder::process_impl found node for "
- // << mAbsPathAndQuery << LL_ENDL;
-
- // Copy everything after mLast read to the out.
- LLBufferArray::segment_iterator_t seg_iter;
-
- buffer->lock();
- seg_iter = buffer->splitAfter(mLastRead);
- if(seg_iter != buffer->endSegment())
- {
- LLChangeChannel change(channels.in(), channels.out());
- ++seg_iter;
- std::for_each(seg_iter, buffer->endSegment(), change);
+
+ PUMP_DEBUG;
+ if(readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ bool read_next_line = false;
+ bool parse_all = true;
+ if(mVerb.empty())
+ {
+ read_next_line = true;
+ LLMemoryStream header((U8*)buf, len);
+ header >> mVerb;
+
+ if((HTTP_VERB_GET == mVerb)
+ || (HTTP_VERB_POST == mVerb)
+ || (HTTP_VERB_PUT == mVerb)
+ || (HTTP_VERB_DELETE == mVerb)
+ || (HTTP_VERB_OPTIONS == mVerb))
+ {
+ header >> mAbsPathAndQuery;
+ header >> mVersion;
+
+ LL_DEBUGS() << "http request: "
+ << mVerb
+ << " " << mAbsPathAndQuery
+ << " " << mVersion << LL_ENDL;
+
+ std::string::size_type delimiter
+ = mAbsPathAndQuery.find('?');
+ if (delimiter == std::string::npos)
+ {
+ mPath = mAbsPathAndQuery;
+ mQuery = "";
+ }
+ else
+ {
+ mPath = mAbsPathAndQuery.substr(0, delimiter);
+ mQuery = mAbsPathAndQuery.substr(delimiter+1);
+ }
+
+ if(!mAbsPathAndQuery.empty())
+ {
+ if(mVersion.empty())
+ {
+ // simple request.
+ parse_all = false;
+ mState = STATE_DONE;
+ mVersion.assign("HTTP/1.0");
+ }
+ }
+ }
+ else
+ {
+ read_next_line = false;
+ parse_all = false;
+ LL_DEBUGS() << "unknown http verb: " << mVerb << LL_ENDL;
+ markBad(channels, buffer);
+ }
+ }
+ if(parse_all)
+ {
+ bool keep_parsing = true;
+ while(keep_parsing)
+ {
+ if(read_next_line)
+ {
+ len = HEADER_BUFFER_SIZE;
+ if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ // Failed to read the header line, probably too long.
+ // readHeaderLine already marked the channel/buffer as bad.
+ keep_parsing = false;
+ break;
+ }
+ }
+ if(0 == len)
+ {
+ return status;
+ }
+ if(buf[0] == '\r' && buf[1] == '\n')
+ {
+ // end-o-headers
+ keep_parsing = false;
+ mState = STATE_LOOKING_FOR_EOS;
+ break;
+ }
+ char* pos_colon = strchr(buf, ':');
+ if(NULL == pos_colon)
+ {
+ keep_parsing = false;
+ LL_DEBUGS() << "bad header: " << buf << LL_ENDL;
+ markBad(channels, buffer);
+ break;
+ }
+ // we've found a header
+ read_next_line = true;
+ std::string name(buf, pos_colon - buf);
+ std::string value(pos_colon + 2);
+ LLStringUtil::toLower(name);
+ if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
+ {
+ LL_DEBUGS() << "Content-Length: " << value << LL_ENDL;
+ mContentLength = atoi(value.c_str());
+ }
+ else
+ {
+ LLStringUtil::trimTail(value);
+ mHeaders[name] = value;
+ }
+ }
+ }
+ }
+ }
+
+ PUMP_DEBUG;
+ // look for the end of stream based on
+ if(STATE_LOOKING_FOR_EOS == mState)
+ {
+ if(0 == mContentLength)
+ {
+ mState = STATE_DONE;
+ }
+ else if(buffer->countAfter(channels.in(), mLastRead) >= mContentLength)
+ {
+ mState = STATE_DONE;
+ }
+ // else more bytes should be coming.
+ }
+
+ PUMP_DEBUG;
+ if(STATE_DONE == mState)
+ {
+ // hey, hey, we should have everything now, so we pass it to
+ // a content handler.
+ context[CONTEXT_REQUEST][CONTEXT_VERB] = mVerb;
+ const LLHTTPNode* node = mRootNode.traverse(mPath, context);
+ if(node)
+ {
+ //LL_INFOS() << "LLHTTPResponder::process_impl found node for "
+ // << mAbsPathAndQuery << LL_ENDL;
+
+ // Copy everything after mLast read to the out.
+ LLBufferArray::segment_iterator_t seg_iter;
+
+ buffer->lock();
+ seg_iter = buffer->splitAfter(mLastRead);
+ if(seg_iter != buffer->endSegment())
+ {
+ LLChangeChannel change(channels.in(), channels.out());
+ ++seg_iter;
+ std::for_each(seg_iter, buffer->endSegment(), change);
#if 0
- seg_iter = buffer->beginSegment();
- char buf[1024]; /*Flawfinder: ignore*/
- while(seg_iter != buffer->endSegment())
- {
- memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
- buf[(*seg_iter).size()] = '\0';
- LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
- << LL_ENDL;
- ++seg_iter;
- }
+ seg_iter = buffer->beginSegment();
+ char buf[1024]; /*Flawfinder: ignore*/
+ while(seg_iter != buffer->endSegment())
+ {
+ memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
+ buf[(*seg_iter).size()] = '\0';
+ LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
+ << LL_ENDL;
+ ++seg_iter;
+ }
#endif
- }
- buffer->unlock();
- //
- // *FIX: get rid of extra bytes off the end
- //
-
- // Set up a chain which will prepend a content length and
- // HTTP headers.
- LLPumpIO::chain_t chain;
- chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
- context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
- context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
- context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
- = mBuildContext[CONTEXT_REMOTE_HOST];
- context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
- = mBuildContext[CONTEXT_REMOTE_PORT];
- context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
-
- const LLChainIOFactory* protocolHandler
- = node->getProtocolHandler();
- if (protocolHandler)
- {
- LL_DEBUGS() << "HTTP context: " << context << LL_ENDL;
- protocolHandler->build(chain, context);
- }
- else
- {
- // this is a simple LLHTTPNode, so use LLHTTPPipe
- chain.push_back(LLIOPipe::ptr_t(new LLHTTPPipe(*node)));
- }
-
- // Add the header - which needs to have the same
- // channel information as the link before it since it
- // is part of the response.
- LLIOPipe* header = new LLHTTPResponseHeader;
- chain.push_back(LLIOPipe::ptr_t(header));
-
- // We need to copy all of the pipes _after_ this so
- // that the response goes out correctly.
- LLPumpIO::links_t current_links;
- pump->copyCurrentLinkInfo(current_links);
- LLPumpIO::links_t::iterator link_iter = current_links.begin();
- LLPumpIO::links_t::iterator links_end = current_links.end();
- bool after_this = false;
- for(; link_iter < links_end; ++link_iter)
- {
- if(after_this)
- {
- chain.push_back((*link_iter).mPipe);
- }
- else if(this == (*link_iter).mPipe.get())
- {
- after_this = true;
- }
- }
-
- // Do the final build of the chain, and send it on
- // it's way.
- LLChannelDescriptors chnl = channels;
- LLPumpIO::LLLinkInfo link;
- LLPumpIO::links_t links;
- LLPumpIO::chain_t::iterator it = chain.begin();
- LLPumpIO::chain_t::iterator end = chain.end();
- while(it != end)
- {
- link.mPipe = *it;
- link.mChannels = chnl;
- links.push_back(link);
- chnl = LLBufferArray::makeChannelConsumer(chnl);
- ++it;
- }
- pump->addChain(
- links,
- buffer,
- context,
- DEFAULT_CHAIN_EXPIRY_SECS);
-
- status = STATUS_STOP;
- }
- else
- {
- LL_WARNS() << "LLHTTPResponder::process_impl didn't find a node for "
- << mAbsPathAndQuery << LL_ENDL;
- LLBufferStream str(channels, buffer.get());
- mState = STATE_SHORT_CIRCUIT;
- str << HTTP_VERSION_STR << " 404 Not Found\r\n\r\n<html>\n"
- << "<title>Not Found</title>\n<body>\nNode '" << mAbsPathAndQuery
- << "' not found.\n</body>\n</html>\n";
- }
- }
-
- if(STATE_SHORT_CIRCUIT == mState)
- {
- //status = mNext->process(buffer, true, pump, context);
- status = STATUS_DONE;
- }
- PUMP_DEBUG;
- return status;
+ }
+ buffer->unlock();
+ //
+ // *FIX: get rid of extra bytes off the end
+ //
+
+ // Set up a chain which will prepend a content length and
+ // HTTP headers.
+ LLPumpIO::chain_t chain;
+ chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
+ context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
+ context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
+ context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
+ = mBuildContext[CONTEXT_REMOTE_HOST];
+ context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
+ = mBuildContext[CONTEXT_REMOTE_PORT];
+ context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
+
+ const LLChainIOFactory* protocolHandler
+ = node->getProtocolHandler();
+ if (protocolHandler)
+ {
+ LL_DEBUGS() << "HTTP context: " << context << LL_ENDL;
+ protocolHandler->build(chain, context);
+ }
+ else
+ {
+ // this is a simple LLHTTPNode, so use LLHTTPPipe
+ chain.push_back(LLIOPipe::ptr_t(new LLHTTPPipe(*node)));
+ }
+
+ // Add the header - which needs to have the same
+ // channel information as the link before it since it
+ // is part of the response.
+ LLIOPipe* header = new LLHTTPResponseHeader;
+ chain.push_back(LLIOPipe::ptr_t(header));
+
+ // We need to copy all of the pipes _after_ this so
+ // that the response goes out correctly.
+ LLPumpIO::links_t current_links;
+ pump->copyCurrentLinkInfo(current_links);
+ LLPumpIO::links_t::iterator link_iter = current_links.begin();
+ LLPumpIO::links_t::iterator links_end = current_links.end();
+ bool after_this = false;
+ for(; link_iter < links_end; ++link_iter)
+ {
+ if(after_this)
+ {
+ chain.push_back((*link_iter).mPipe);
+ }
+ else if(this == (*link_iter).mPipe.get())
+ {
+ after_this = true;
+ }
+ }
+
+ // Do the final build of the chain, and send it on
+ // it's way.
+ LLChannelDescriptors chnl = channels;
+ LLPumpIO::LLLinkInfo link;
+ LLPumpIO::links_t links;
+ LLPumpIO::chain_t::iterator it = chain.begin();
+ LLPumpIO::chain_t::iterator end = chain.end();
+ while(it != end)
+ {
+ link.mPipe = *it;
+ link.mChannels = chnl;
+ links.push_back(link);
+ chnl = LLBufferArray::makeChannelConsumer(chnl);
+ ++it;
+ }
+ pump->addChain(
+ links,
+ buffer,
+ context,
+ DEFAULT_CHAIN_EXPIRY_SECS);
+
+ status = STATUS_STOP;
+ }
+ else
+ {
+ LL_WARNS() << "LLHTTPResponder::process_impl didn't find a node for "
+ << mAbsPathAndQuery << LL_ENDL;
+ LLBufferStream str(channels, buffer.get());
+ mState = STATE_SHORT_CIRCUIT;
+ str << HTTP_VERSION_STR << " 404 Not Found\r\n\r\n<html>\n"
+ << "<title>Not Found</title>\n<body>\nNode '" << mAbsPathAndQuery
+ << "' not found.\n</body>\n</html>\n";
+ }
+ }
+
+ if(STATE_SHORT_CIRCUIT == mState)
+ {
+ //status = mNext->process(buffer, true, pump, context);
+ status = STATUS_DONE;
+ }
+ PUMP_DEBUG;
+ return status;
}
-// static
-void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain,
+// static
+void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain,
const LLHTTPNode& root, const LLSD& ctx)
{
- chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
+ chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
}
class LLHTTPResponseFactory : public LLChainIOFactory
{
public:
- bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
- {
- LLIOHTTPServer::createPipe(chain, mTree, ctx);
- return true;
- }
+ bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
+ {
+ LLIOHTTPServer::createPipe(chain, mTree, ctx);
+ return true;
+ }
- LLHTTPNode& getRootNode() { return mTree; }
+ LLHTTPNode& getRootNode() { return mTree; }
private:
- LLHTTPNode mTree;
+ LLHTTPNode mTree;
};
// static
LLHTTPNode& LLIOHTTPServer::create(
- apr_pool_t* pool, LLPumpIO& pump, U16 port)
+ apr_pool_t* pool, LLPumpIO& pump, U16 port)
{
- LLSocket::ptr_t socket = LLSocket::create(
+ LLSocket::ptr_t socket = LLSocket::create(
pool,
LLSocket::STREAM_TCP,
port);
@@ -982,21 +982,21 @@ LLHTTPNode& LLIOHTTPServer::create(
}
LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
- std::shared_ptr<LLChainIOFactory> factory_ptr(factory);
+ std::shared_ptr<LLChainIOFactory> factory_ptr(factory);
LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr);
- LLPumpIO::chain_t chain;
+ LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(server));
pump.addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
- return factory->getRootNode();
+ return factory->getRootNode();
}
// static
void LLIOHTTPServer::setTimingCallback(timing_callback_t callback,
- void* data)
+ void* data)
{
- sTimingCallback = callback;
- sTimingCallbackData = data;
+ sTimingCallback = callback;
+ sTimingCallbackData = data;
}