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; }
void LLXMLRPCTransaction::Impl::curlEasyRequestCallback(bool success) { llassert(mStatus == LLXMLRPCTransaction::StatusStarted || mStatus == LLXMLRPCTransaction::StatusDownloading); AICurlEasyRequestStateMachine* state_machine = mCurlEasyRequestStateMachinePtr; // We're done with the statemachine, one way or another. // Set mCurlEasyRequestStateMachinePtr to NULL so we won't call mCurlEasyRequestStateMachinePtr->running() in the destructor. // Note that the state machine auto-cleaning: it will be deleted by the main-thread after this function returns. mCurlEasyRequestStateMachinePtr = NULL; if (!success) { // AICurlEasyRequestStateMachine did abort. // This currently only happens when libcurl didn't finish before the timer expired. std::ostringstream msg; F32 timeout_value = gSavedSettings.getF32("CurlRequestTimeOut"); msg << "Connection to " << mURI << " timed out (" << timeout_value << " s)!"; if (timeout_value < 40) { msg << "\nTry increasing CurlRequestTimeOut in Debug Settings."; } setStatus(LLXMLRPCTransaction::StatusOtherError, msg.str()); return; } AICurlEasyRequest_wat curlEasyRequest_w(*state_machine->mCurlEasyRequest); CURLcode result; curlEasyRequest_w->getResult(&result, &mTransferInfo); if (result != CURLE_OK) { setCurlStatus(result); llwarns << "LLXMLRPCTransaction CURL error " << mCurlCode << ": " << curlEasyRequest_w->getErrorString() << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; return; } setStatus(LLXMLRPCTransaction::StatusComplete); mResponse = XMLRPC_REQUEST_FromXML( mResponseText.data(), mResponseText.size(), NULL); bool hasError = false; bool hasFault = false; int faultCode = 0; std::string faultString; LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse)); if (error.isValid()) { hasError = true; faultCode = error["faultCode"].asInt(); faultString = error["faultString"].asString(); } else if (XMLRPC_ResponseIsFault(mResponse)) { hasFault = true; faultCode = XMLRPC_GetResponseFaultCode(mResponse); faultString = XMLRPC_GetResponseFaultString(mResponse); } if (hasError || hasFault) { setStatus(LLXMLRPCTransaction::StatusXMLRPCError); llwarns << "LLXMLRPCTransaction XMLRPC " << (hasError ? "error " : "fault ") << faultCode << ": " << faultString << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; } }
bool LLXMLRPCTransaction::Impl::process() { if(!mCurlRequest || !mCurlRequest->isValid()) { llwarns << "transaction failed." << llendl ; delete mCurlRequest ; mCurlRequest = NULL ; return true ; //failed, quit. } switch(mStatus) { case LLXMLRPCTransaction::StatusComplete: case LLXMLRPCTransaction::StatusCURLError: case LLXMLRPCTransaction::StatusXMLRPCError: case LLXMLRPCTransaction::StatusOtherError: { return true; } case LLXMLRPCTransaction::StatusNotStarted: { setStatus(LLXMLRPCTransaction::StatusStarted); break; } default: { // continue onward } } if(!mCurlRequest->wait()) { return false ; } while(1) { CURLcode result; bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo); if (newmsg) { if (result != CURLE_OK) { if ((result != CURLE_SSL_PEER_CERTIFICATE) && (result != CURLE_SSL_CACERT)) { // if we have a curl error that's not already been handled // (a non cert error), then generate the error message as // appropriate setCurlStatus(result); llwarns << "LLXMLRPCTransaction CURL error " << mCurlCode << ": " << mCurlRequest->getErrorString() << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; } return true; } setStatus(LLXMLRPCTransaction::StatusComplete); mResponse = XMLRPC_REQUEST_FromXML( mResponseText.data(), mResponseText.size(), NULL); bool hasError = false; bool hasFault = false; int faultCode = 0; std::string faultString; LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse)); if (error.isValid()) { hasError = true; faultCode = error["faultCode"].asInt(); faultString = error["faultString"].asString(); } else if (XMLRPC_ResponseIsFault(mResponse)) { hasFault = true; faultCode = XMLRPC_GetResponseFaultCode(mResponse); faultString = XMLRPC_GetResponseFaultString(mResponse); } if (hasError || hasFault) { setStatus(LLXMLRPCTransaction::StatusXMLRPCError); llwarns << "LLXMLRPCTransaction XMLRPC " << (hasError ? "error " : "fault ") << faultCode << ": " << faultString << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; } return true; } else { break; // done } } return false; }
bool LLXMLRPCTransaction::Impl::process() { switch(mStatus) { case LLXMLRPCTransaction::StatusComplete: case LLXMLRPCTransaction::StatusCURLError: case LLXMLRPCTransaction::StatusXMLRPCError: case LLXMLRPCTransaction::StatusOtherError: { return true; } case LLXMLRPCTransaction::StatusNotStarted: { setStatus(LLXMLRPCTransaction::StatusStarted); break; } default: { // continue onward } } const F32 MAX_PROCESSING_TIME = 0.05f; LLTimer timer; int count; while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(mCurlMulti, &count)) { if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME) { return false; } } while(CURLMsg* curl_msg = curl_multi_info_read(mCurlMulti, &count)) { if (CURLMSG_DONE == curl_msg->msg) { if (curl_msg->data.result != CURLE_OK) { setCurlStatus(curl_msg->data.result); llwarns << "LLXMLRPCTransaction CURL error " << mCurlCode << ": " << mCurlErrorBuffer << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; return true; } setStatus(LLXMLRPCTransaction::StatusComplete); mResponse = XMLRPC_REQUEST_FromXML( mResponseText.data(), mResponseText.size(), NULL); bool hasError = false; bool hasFault = false; int faultCode = 0; std::string faultString; LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse)); if (error.isValid()) { hasError = true; faultCode = error["faultCode"].asInt(); faultString = error["faultString"].asString(); } else if (XMLRPC_ResponseIsFault(mResponse)) { hasFault = true; faultCode = XMLRPC_GetResponseFaultCode(mResponse); faultString = XMLRPC_GetResponseFaultString(mResponse); } if (hasError || hasFault) { setStatus(LLXMLRPCTransaction::StatusXMLRPCError); llwarns << "LLXMLRPCTransaction XMLRPC " << (hasError ? "error " : "fault ") << faultCode << ": " << faultString << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; } return true; } } return false; }
bool LLXMLRPCTransaction::Impl::process() { switch(mStatus) { case LLXMLRPCTransaction::StatusComplete: case LLXMLRPCTransaction::StatusCURLError: case LLXMLRPCTransaction::StatusXMLRPCError: case LLXMLRPCTransaction::StatusOtherError: { return true; } case LLXMLRPCTransaction::StatusNotStarted: { setStatus(LLXMLRPCTransaction::StatusStarted); break; } default: { // continue onward } } const F32 MAX_PROCESSING_TIME = 0.05f; LLTimer timer; while (mCurlRequest->perform() > 0) { if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME) { return false; } } while(1) { CURLcode result; bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo); if (newmsg) { if (result != CURLE_OK) { setCurlStatus(result); llwarns << "LLXMLRPCTransaction CURL error " << mCurlCode << ": " << mCurlRequest->getErrorString() << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; return true; } setStatus(LLXMLRPCTransaction::StatusComplete); mResponse = XMLRPC_REQUEST_FromXML( mResponseText.data(), mResponseText.size(), NULL); bool hasError = false; bool hasFault = false; int faultCode = 0; std::string faultString; LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse)); if (error.isValid()) { hasError = true; faultCode = error["faultCode"].asInt(); faultString = error["faultString"].asString(); } else if (XMLRPC_ResponseIsFault(mResponse)) { hasFault = true; faultCode = XMLRPC_GetResponseFaultCode(mResponse); faultString = XMLRPC_GetResponseFaultString(mResponse); } if (hasError || hasFault) { setStatus(LLXMLRPCTransaction::StatusXMLRPCError); llwarns << "LLXMLRPCTransaction XMLRPC " << (hasError ? "error " : "fault ") << faultCode << ": " << faultString << llendl; llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; } return true; } else { break; // done } } return false; }