// virtual LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) { PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER); if(eos) { PUMP_DEBUG; //mGotEOS = true; std::ostringstream ostr; std::string message = context[CONTEXT_RESPONSE]["statusMessage"]; int code = context[CONTEXT_RESPONSE]["statusCode"]; if (code < 200) { code = 200; message = "OK"; } ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n"; S32 content_length = buffer->countAfter(channels.in(), NULL); if(0 < content_length) { ostr << "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; }
// virtual LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) { PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER); if(eos) { PUMP_DEBUG; //mGotEOS = true; std::ostringstream ostr; std::string message = context["response"]["statusMessage"]; int code = context["response"]["statusCode"]; if (code < 200) { code = 200; message = "OK"; } ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n"; std::string type = context["response"]["contentType"].asString(); if (!type.empty()) { ostr << "Content-Type: " << type << "\r\n"; } S32 content_length = buffer->countAfter(channels.in(), NULL); if(0 < content_length) { ostr << "Content-Length: " << content_length << "\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; }
LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) { LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_REQUEST); PUMP_DEBUG; if(!eos) return STATUS_BREAK; if(!buffer) return STATUS_ERROR; PUMP_DEBUG; // *FIX: This technique for reading data is far from optimal. We // need to have some kind of istream interface into the xml // parser... S32 bytes = buffer->countAfter(channels.in(), NULL); if(!bytes) return STATUS_ERROR; char* buf = new char[bytes + 1]; buf[bytes] = '\0'; buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes); //lldebugs << "xmlrpc request: " << buf << llendl; // Check the value in the buffer. XMLRPC_REQUEST_FromXML will report a error code 4 if // values that are less than 0x20 are passed to it, except // 0x09: Horizontal tab; 0x0a: New Line; 0x0d: Carriage U8* cur_pBuf = (U8*)buf; U8 cur_char; for (S32 i=0; i<bytes; i++) { cur_char = *cur_pBuf; if ( cur_char < 0x20 && 0x09 != cur_char && 0x0a != cur_char && 0x0d != cur_char ) { *cur_pBuf = '?'; } ++cur_pBuf; } PUMP_DEBUG; XMLRPC_REQUEST request = XMLRPC_REQUEST_FromXML( buf, bytes, NULL); if(!request) { llwarns << "XML -> SD Request process parse error." << llendl; delete[] buf; return STATUS_ERROR; } PUMP_DEBUG; LLBufferStream stream(channels, buffer.get()); stream.precision(DEFAULT_PRECISION); const char* name = XMLRPC_RequestGetMethodName(request); stream << LLSDRPC_REQUEST_HEADER_1 << (name ? name : "") << LLSDRPC_REQUEST_HEADER_2; XMLRPC_VALUE param = XMLRPC_RequestGetData(request); if(param) { PUMP_DEBUG; S32 size = XMLRPC_VectorSize(param); if(size > 1) { // if there are multiple parameters, stuff the values into // an array so that the next step in the chain can read them. stream << "["; } XMLRPC_VALUE current = XMLRPC_VectorRewind(param); bool needs_comma = false; while(current) { if(needs_comma) { stream << ","; } needs_comma = true; stream_out(stream, current); current = XMLRPC_VectorNext(param); } if(size > 1) { // close the array stream << "]"; } } stream << LLSDRPC_REQUEST_FOOTER << std::flush; XMLRPC_RequestFree(request, 1); delete[] buf; PUMP_DEBUG; return STATUS_DONE; }
LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) { LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_RESPONSE); PUMP_DEBUG; if(!eos) return STATUS_BREAK; if(!buffer) return STATUS_ERROR; PUMP_DEBUG; // *FIX: This technique for reading data is far from optimal. We // need to have some kind of istream interface into the xml // parser... S32 bytes = buffer->countAfter(channels.in(), NULL); if(!bytes) return STATUS_ERROR; char* buf = new char[bytes + 1]; buf[bytes] = '\0'; buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes); //lldebugs << "xmlrpc response: " << buf << llendl; PUMP_DEBUG; XMLRPC_REQUEST response = XMLRPC_REQUEST_FromXML( buf, bytes, NULL); if(!response) { llwarns << "XML -> SD Response unable to parse xml." << llendl; delete[] buf; return STATUS_ERROR; } PUMP_DEBUG; LLBufferStream stream(channels, buffer.get()); stream.precision(DEFAULT_PRECISION); if(XMLRPC_ResponseIsFault(response)) { PUMP_DEBUG; stream << LLSDRPC_FAULT_HADER_1 << XMLRPC_GetResponseFaultCode(response) << LLSDRPC_FAULT_HADER_2; const char* fault_str = XMLRPC_GetResponseFaultString(response); std::string fault_string; if(fault_str) { fault_string.assign(fault_str); } stream << "'" << LLSDNotationFormatter::escapeString(fault_string) << "'" <<LLSDRPC_FAULT_FOOTER << std::flush; } else { PUMP_DEBUG; stream << LLSDRPC_RESPONSE_HEADER; XMLRPC_VALUE param = XMLRPC_RequestGetData(response); if(param) { stream_out(stream, param); } stream << LLSDRPC_RESPONSE_FOOTER << std::flush; } PUMP_DEBUG; XMLRPC_RequestFree(response, 1); delete[] buf; PUMP_DEBUG; return STATUS_DONE; }