LLIOPipe::EStatus LLHTTPPipe::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) { PUMP_DEBUG; lldebugs << "LLSDHTTPServer::process_impl" << llendl; // Once we have all the data, We need to read the sd on // the the in channel, and respond on the out channel 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? LLBufferStream istr(channels, buffer.get()); static LLTimer timer; if (sTimingCallback) { timer.reset(); } std::string verb = context[CONTEXT_REQUEST]["verb"]; if(verb == HTTP_VERB_GET) { mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_PUT) { LLSD input; LLSDSerialize::fromXML(input, istr); mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input); } else if(verb == HTTP_VERB_POST) { LLSD input; LLSDSerialize::fromXML(input, istr); mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input); } else if(verb == HTTP_VERB_DELETE) { mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); } else { mResponse->methodNotAllowed(); } if (sTimingCallback) { LLHTTPNode::Description desc; mNode.describe(desc); LLSD info = desc.getInfo(); std::string timing_name = info["description"]; timing_name += " "; timing_name += verb; F32 delta = timer.getElapsedTimeF32(); sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData); } // Log Internal Server Errors if(mStatusCode == 500) { llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error" << llendl; } } 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: { context["response"]["contentType"] = "application/xml"; LLBufferStream ostr(channels, buffer.get()); LLSDSerialize::toXML(mGoodResult, ostr); return STATUS_DONE; } case STATE_STATUS_RESULT: { context["response"]["contentType"] = "text/plain"; context["response"]["statusCode"] = mStatusCode; context["response"]["statusMessage"] = mStatusMessage; LLBufferStream ostr(channels, buffer.get()); ostr << mStatusMessage << std::ends; return STATUS_DONE; } default: llwarns << "LLHTTPPipe::process_impl: unexpected state " << mState << llendl; return STATUS_BREAK; } // PUMP_DEBUG; // unreachable }
LLIOPipe::EStatus LLHTTPPipe::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) { PUMP_DEBUG; lldebugs << "LLSDHTTPServer::process_impl" << llendl; // Once we have all the data, We need to read the sd on // the the in channel, and respond on the out channel 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) { LLPerfBlock getblock("http_get"); mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_PUT) { LLPerfBlock putblock("http_put"); LLSD input; LLSDSerialize::fromXML(input, istr); mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input); } else if(verb == HTTP_VERB_POST) { LLPerfBlock postblock("http_post"); LLSD input; LLSDSerialize::fromXML(input, istr); mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input); } else if(verb == HTTP_VERB_DELETE) { LLPerfBlock delblock("http_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. lldebugs << verb << " " << context[CONTEXT_REQUEST]["path"].asString() << " " << mStatusCode << " " << mStatusMessage << " " << delta << "s" << llendl; // Log Internal Server Errors //if(mStatusCode == 500) //{ // llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error" // << llendl; //} } 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["Content-Type"] = "application/llsd+xml"; context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers; LLBufferStream ostr(channels, buffer.get()); LLSDSerialize::toXML(mGoodResult, ostr); return STATUS_DONE; } case STATE_STATUS_RESULT: { LLSD headers = mHeaders; headers["Content-Type"] = "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 << std::ends; return STATUS_DONE; } default: llwarns << "LLHTTPPipe::process_impl: unexpected state " << mState << llendl; return STATUS_BREAK; } // PUMP_DEBUG; // unreachable }