diff --git a/indra/aistatemachine/aicurl.cpp b/indra/aistatemachine/aicurl.cpp index 537d12e2f..c45c6f214 100644 --- a/indra/aistatemachine/aicurl.cpp +++ b/indra/aistatemachine/aicurl.cpp @@ -430,50 +430,92 @@ std::string strerror(CURLcode errorcode) } //----------------------------------------------------------------------------- -// class Responder +// class ResponderBase // -Responder::Responder(void) : mReferenceCount(0), mFinished(false) +ResponderBase::ResponderBase(void) : mReferenceCount(0), mFinished(false) { DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this); } -Responder::~Responder() +ResponderBase::~ResponderBase() { - DoutEntering(dc::curl, "AICurlInterface::Responder::~Responder() with this = " << (void*)this << "; mReferenceCount = " << mReferenceCount); + DoutEntering(dc::curl, "AICurlInterface::ResponderBase::~ResponderBase() with this = " << (void*)this << "; mReferenceCount = " << mReferenceCount); llassert(mReferenceCount == 0); } -void Responder::setURL(std::string const& url) +void ResponderBase::setURL(std::string const& url) { // setURL is called from llhttpclient.cpp (request()), before calling any of the below (of course). // We don't need locking here therefore; it's a case of initializing before use. mURL = url; } -AIHTTPTimeoutPolicy const& Responder::getHTTPTimeoutPolicy(void) const +AIHTTPTimeoutPolicy const& ResponderBase::getHTTPTimeoutPolicy(void) const { return AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout(); } +void ResponderBase::decode_body(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer, LLSD& content) +{ + // If the status indicates success (and we get here) then we expect the body to be LLSD. + bool const should_be_llsd = (200 <= status && status < 300); + if (should_be_llsd) + { + LLBufferStream istr(channels, buffer.get()); + if (LLSDSerialize::fromXML(content, istr) == LLSDParser::PARSE_FAILURE) + { + // Unfortunately we can't show the body of the message... I think this is a pretty serious error + // though, so if this ever happens it has to be investigated by making a copy of the buffer + // before serializing it, as is done below. + llwarns << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; + } + // LLSDSerialize::fromXML destructed buffer, we can't initialize content now. + return; + } + // Put the body in content as-is. + std::stringstream ss; + buffer->writeChannelTo(ss, channels.in()); + content = ss.str(); +#ifdef SHOW_ASSERT + if (!should_be_llsd) + { + // Make sure that the server indeed never returns LLSD as body when the http status is an error. + LLSD dummy; + bool server_sent_llsd_with_http_error = LLSDSerialize::fromXML(dummy, ss) > 0; + if (server_sent_llsd_with_http_error) + { + llwarns << "The server sent us a response with http status " << status << " and LLSD(!) body: \"" << ss.str() << "\"!" << llendl; + } + llassert(!server_sent_llsd_with_http_error); + } +#endif +} + // Called with HTML body. // virtual -void Responder::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer) +void ResponderWithCompleted::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) { LLSD content; - LLBufferStream istr(channels, buffer.get()); - if (!LLSDSerialize::fromXML(content, istr)) - { - llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; - } + decode_body(status, reason, channels, buffer, content); // Allow derived class to override at this point. completed(status, reason, content); } // virtual -void Responder::completed(U32 status, std::string const& reason, LLSD const& content) +void ResponderWithCompleted::completed(U32 status, std::string const& reason, LLSD const& content) { + // Either completedRaw() or this method must be overridden by the derived class. Hence, we should never get here. + llassert_always(false); +} + +// virtual +void Responder::finished(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) +{ + LLSD content; + decode_body(status, reason, channels, buffer, content); + // HTML status good? if (200 <= status && status < 300) { @@ -485,6 +527,7 @@ void Responder::completed(U32 status, std::string const& reason, LLSD const& con // Allow derived class to override at this point. errorWithContent(status, reason, content); } + mFinished = true; } // virtual @@ -500,20 +543,14 @@ void Responder::error(U32 status, std::string const& reason) llinfos << mURL << " [" << status << "]: " << reason << llendl; } -// virtual -void Responder::result(LLSD const&) -{ - // Nothing. -} - // Friend functions. -void intrusive_ptr_add_ref(Responder* responder) +void intrusive_ptr_add_ref(ResponderBase* responder) { responder->mReferenceCount++; } -void intrusive_ptr_release(Responder* responder) +void intrusive_ptr_release(ResponderBase* responder) { if (--responder->mReferenceCount == 0) { @@ -528,7 +565,7 @@ void LegacyPolledResponder::completed_headers(U32 status, std::string const& rea mStatus = status; mReason = reason; // Call base class implementation. - Responder::completed_headers(status, reason, code, info); + ResponderBase::completed_headers(status, reason, code, info); } } // namespace AICurlInterface diff --git a/indra/aistatemachine/aicurl.h b/indra/aistatemachine/aicurl.h index 53f7af394..7a679d6f6 100644 --- a/indra/aistatemachine/aicurl.h +++ b/indra/aistatemachine/aicurl.h @@ -200,13 +200,16 @@ void setCAPath(std::string const& file); // destructed. Also, if any of those are destructed then the Responder is automatically // destructed too. // -class Responder : public AICurlResponderBufferEvents { +class ResponderBase : public AICurlResponderBufferEvents { public: typedef boost::shared_ptr buffer_ptr_t; protected: - Responder(void); - virtual ~Responder(); + ResponderBase(void); + virtual ~ResponderBase(); + + // Read body from buffer and put it into content. If status indicates success, interpret it as LLSD, otherwise copy it as-is. + void decode_body(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer, LLSD& content); protected: // Associated URL, used for debug output. @@ -227,11 +230,7 @@ class Responder : public AICurlResponderBufferEvents { std::string const& getURL(void) const { return mURL; } // Called by CurlResponderBuffer::timed_out or CurlResponderBuffer::processOutput. - void finished(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) - { - completedRaw(status, reason, channels, buffer); - mFinished = true; - } + virtual void finished(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) = 0; // Return true if the curl thread is done with this transaction. // If this returns true then it is guaranteed that none of the @@ -279,6 +278,25 @@ class Responder : public AICurlResponderBufferEvents { // The default does nothing. } + private: + // Used by ResponderPtr. Object is deleted when reference count reaches zero. + LLAtomicU32 mReferenceCount; + + friend void intrusive_ptr_add_ref(ResponderBase* p); // Called by boost::intrusive_ptr when a new copy of a boost::intrusive_ptr is made. + friend void intrusive_ptr_release(ResponderBase* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr is destroyed. + // This function must delete the ResponderBase object when the reference count reaches zero. +}; + +class ResponderWithCompleted : public ResponderBase { + protected: + virtual void finished(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) + { + // Allow classes derived from ResponderBase to override completedRaw + // (if not they should override completed or be derived from Responder instead). + completedRaw(status, reason, channels, buffer); + mFinished = true; + } + // Derived classes can override this to get the raw data of the body of the HTML message that was received. // The default is to interpret the content as LLSD and call completed(). virtual void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); @@ -287,9 +305,25 @@ class Responder : public AICurlResponderBufferEvents { // The default is to call result() (or errorWithContent() in case of a HTML status indicating an error). virtual void completed(U32 status, std::string const& reason, LLSD const& content); +#ifdef SHOW_ASSERT + // Responders derived from this class must override either completedRaw or completed. + // They may not attempt to override any of the virual functions defined by Responder. + // Define those functions here with different parameter in order to cause a compile + // warning when a class accidently tries to override them. + enum YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS { }; + virtual void result(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } + virtual void errorWithContent(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } + virtual void error(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } +#endif +}; + +class Responder : public ResponderBase { + protected: + virtual void finished(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); + // ... or, derived classes can override this to received the content of a body upon success. // The default does nothing. - virtual void result(LLSD const& content); + virtual void result(LLSD const& content) = 0; // Derived classes can override this to get informed when a bad HTML status code is received. // The default calls error(). @@ -303,27 +337,29 @@ class Responder : public AICurlResponderBufferEvents { // Called from LLSDMessage::ResponderAdapter::listener. // LLSDMessage::ResponderAdapter is a hack, showing among others by fact that these functions need to be public. - void pubErrorWithContent(U32 status, std::string const& reason, LLSD const& content) { errorWithContent(status, reason, content); } - void pubResult(LLSD const& content) { result(content); } + void pubErrorWithContent(U32 status, std::string const& reason, LLSD const& content) { errorWithContent(status, reason, content); mFinished = true; } + void pubResult(LLSD const& content) { result(content); mFinished = true; } - private: - // Used by ResponderPtr. Object is deleted when reference count reaches zero. - LLAtomicU32 mReferenceCount; - - friend void intrusive_ptr_add_ref(Responder* p); // Called by boost::intrusive_ptr when a new copy of a boost::intrusive_ptr is made. - friend void intrusive_ptr_release(Responder* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr is destroyed. - // This function must delete the Responder object when the reference count reaches zero. +#ifdef SHOW_ASSERT + // Responders derived from this class must override result, and either errorWithContent or error. + // They may not attempt to override any of the virual functions defined by ResponderWithCompleted. + // Define those functions here with different parameter in order to cause a compile + // warning when a class accidently tries to override them. + enum YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS { }; + virtual void completedRaw(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } + virtual void completed(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } +#endif }; // A Responder is passed around as ResponderPtr, which causes it to automatically // destruct when there are no pointers left pointing to it. -typedef boost::intrusive_ptr ResponderPtr; +typedef boost::intrusive_ptr ResponderPtr; // Same as above except that this class stores the result, allowing old polling // code to poll if the transaction finished by calling is_finished() (from the // main the thread) and then access the results-- as opposed to immediately // digesting the results when any of the virtual functions are called. -class LegacyPolledResponder : public Responder { +class LegacyPolledResponder : public ResponderWithCompleted { protected: CURLcode mCode; U32 mStatus; diff --git a/indra/llmessage/aihttptimeoutpolicy.cpp b/indra/llmessage/aihttptimeoutpolicy.cpp index 1a601db07..7db472f96 100644 --- a/indra/llmessage/aihttptimeoutpolicy.cpp +++ b/indra/llmessage/aihttptimeoutpolicy.cpp @@ -186,6 +186,7 @@ AIHTTPTimeoutPolicy::AIHTTPTimeoutPolicy(char const* name, AIHTTPTimeoutPolicyBa mMaximumCurlTransaction(mBase->mMaximumCurlTransaction), mMaximumTotalDelay(mBase->mMaximumTotalDelay) { + sNameMap.insert(namemap_t::value_type(name, this)); // Register for changes to the base policy. mBase->derived(this); } @@ -645,6 +646,24 @@ AIHTTPTimeoutPolicyBase connect_40s(AIHTTPTimeoutPolicyBase::getDebugSettingsCur // End of policy definitions. //======================================================================================================= +//static +AIHTTPTimeoutPolicy::namemap_t AIHTTPTimeoutPolicy::sNameMap; + +//static +AIHTTPTimeoutPolicy const* AIHTTPTimeoutPolicy::getTimeoutPolicyByName(std::string const& name) +{ + namemap_t::iterator iter = sNameMap.find(name); + if (iter == sNameMap.end()) + { + if (!name.empty()) + { + llwarns << "Cannot find AIHTTPTimeoutPolicy with name \"" << name << "\"." << llendl; + } + return &sDebugSettingsCurlTimeout; + } + return iter->second; +} + //======================================================================================================= // Start of Responder timeout policy list. @@ -674,9 +693,7 @@ P(environmentApplyResponder); P(environmentRequestResponder); P(estateChangeInfoResponder); P(eventPollResponder); -P(eventResponder); P(fetchInventoryResponder); -P(floaterRegionDebugConsole); P(fnPtrResponder); P2(groupProposalBallotResponder, transfer_300s); P(homeLocationResponder); diff --git a/indra/llmessage/aihttptimeoutpolicy.h b/indra/llmessage/aihttptimeoutpolicy.h index bb11b033a..bf333b105 100644 --- a/indra/llmessage/aihttptimeoutpolicy.h +++ b/indra/llmessage/aihttptimeoutpolicy.h @@ -33,6 +33,7 @@ #include "stdtypes.h" #include +#include class AIHTTPTimeoutPolicyBase; @@ -52,6 +53,8 @@ class AIHTTPTimeoutPolicy { char const* const mName; // The name of this policy, for debugging purposes. AIHTTPTimeoutPolicyBase* const mBase; // Policy this policy was based on. static AIHTTPTimeoutPolicyBase sDebugSettingsCurlTimeout; // CurlTimeout* debug settings. + typedef std::map namemap_t; // Type of sNameMap. + static namemap_t sNameMap; // Map of name of timeout policies (as returned by name()) to AIHTTPTimeoutPolicy* (this). private: U16 mDNSLookupGrace; // Extra connect timeout the first time we connect to a host (this is to allow for DNS lookups). @@ -97,6 +100,7 @@ class AIHTTPTimeoutPolicy { U16 getCurlTransaction(void) const { return mMaximumCurlTransaction; } U16 getTotalDelay(void) const { return mMaximumTotalDelay; } static AIHTTPTimeoutPolicy const& getDebugSettingsCurlTimeout(void); + static AIHTTPTimeoutPolicy const* getTimeoutPolicyByName(std::string const& name); // Called once at start up of viewer to set a different default timeout policy than HTTPTimeoutPolicy_default. static void setDefaultCurlTimeout(AIHTTPTimeoutPolicy const& defaultCurlTimeout); diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp index 0f31f7065..b9ca7ceb6 100644 --- a/indra/llmessage/llbuffer.cpp +++ b/indra/llmessage/llbuffer.cpp @@ -650,6 +650,20 @@ U8* LLBufferArray::readAfter( return rv; } +void LLBufferArray::writeChannelTo(std::ostream& ostr, S32 channel) const +{ + LLMemType m1(LLMemType::MTYPE_IO_BUFFER); + LLMutexLock lock(mMutexp) ; + const_segment_iterator_t const end = mSegments.end(); + for (const_segment_iterator_t it = mSegments.begin(); it != end; ++it) + { + if (it->isOnChannel(channel)) + { + ostr.write((char*)it->data(), it->size()); + } + } +} + U8* LLBufferArray::seek( S32 channel, U8* start, diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index 4940da2fe..c7624bde3 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -592,6 +592,12 @@ public: void setThreaded(bool threaded); //@} + /** + * @brief Read channel channel of LLBufferArray and write it to ostr. + * This is a Singularity extension. + */ + void writeChannelTo(std::ostream& ostr, S32 channel) const; + protected: /** * @brief Optimally put data in buffers, and reutrn segments. diff --git a/indra/llmessage/llcurlrequest.h b/indra/llmessage/llcurlrequest.h index d30418abd..4fe172b46 100644 --- a/indra/llmessage/llcurlrequest.h +++ b/indra/llmessage/llcurlrequest.h @@ -41,8 +41,8 @@ class AIHTTPHeaders; namespace AICurlInterface { // Forward declaration. -class Responder; -typedef boost::intrusive_ptr ResponderPtr; +class ResponderBase; +typedef boost::intrusive_ptr ResponderPtr; class Request { public: diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 26c7b39e0..96a38ea10 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -234,30 +234,17 @@ class BlockingResponder : public AICurlInterface::LegacyPolledResponder { private: LLCondition mSignal; LLSD mResponse; - std::ostringstream mBody; public: void wait(void); LLSD const& response(void) const { llassert(mFinished && mCode == CURLE_OK && mStatus == HTTP_OK); return mResponse; } - std::string const& body(void) const { llassert(mFinished && mCode == CURLE_OK && mStatus != HTTP_OK); return mBody.str(); } /*virtual*/ void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); }; -void BlockingResponder::completedRaw(U32, std::string const&, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) +void BlockingResponder::completedRaw(U32, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) { - if (mCode == CURLE_OK) - { - LLBufferStream istr(channels, buffer.get()); - if (mStatus == HTTP_OK) - { - LLSDSerialize::fromXML(mResponse, istr); - } - else - { - mBody << istr; - } - } + decode_body(mCode, reason, channels, buffer, mResponse); // This puts the body asString() in mResponse in case of http error. // Normally mFinished is set immediately after returning from this function, // but we do it here, because we need to set it before calling mSignal.signal(). mSignal.lock(); @@ -341,7 +328,7 @@ static LLSD blocking_request( LLSD response = LLSD::emptyMap(); CURLcode result = responder->result_code(); - if (result == CURLE_OK && (http_status = responder->http_status()) == HTTP_OK) + if (result == CURLE_OK && (http_status = responder->http_status()) >= 200 && http_status < 300) { response["body"] = responder->response(); } @@ -358,9 +345,9 @@ static LLSD blocking_request( llwarns << "CURL REQ BODY: " << body.asString() << llendl; } llwarns << "CURL HTTP_STATUS: " << http_status << llendl; - llwarns << "CURL ERROR BODY: " << responder->body() << llendl; + llwarns << "CURL ERROR BODY: " << responder->response().asString() << llendl; } - response["body"] = responder->body(); + response["body"] = responder->response().asString(); } else { diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index d6ffad888..c78917a82 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -53,8 +53,8 @@ public: typedef LLCurl::Responder Responder; typedef LLCurl::ResponderPtr ResponderPtr; - // The default actually already ignores responses. - class ResponderIgnore : public Responder { virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return responderIgnore_timeout;} }; + class ResponderIgnoreBody : public Responder { void result(LLSD const&) { } }; + class ResponderIgnore : public ResponderIgnoreBody { virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return responderIgnore_timeout;} }; /** @name non-blocking API */ //@{ diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp index 441355b3b..be968c5db 100644 --- a/indra/llmessage/llsdmessage.cpp +++ b/indra/llmessage/llsdmessage.cpp @@ -45,6 +45,7 @@ #include "llhost.h" #include "message.h" #include "llsdutil.h" +#include "aihttptimeoutpolicy.h" // Declare a static LLSDMessage instance to ensure that we have a listener as // soon as someone tries to post on our canonical LLEventPump name. @@ -62,13 +63,15 @@ LLSDMessage::LLSDMessage(): bool LLSDMessage::httpListener(const LLSD& request) { + llassert(false); // This function is never called. --Aleric + // Extract what we want from the request object. We do it all up front // partly to document what we expect. LLSD::String url(request["url"]); LLSD payload(request["payload"]); LLSD::String reply(request["reply"]); LLSD::String error(request["error"]); - LLSD::Real timeout(request["timeout"]); + LLSD::String timeoutpolicy(request["timeoutpolicy"]); // If the LLSD doesn't even have a "url" key, we doubt it was intended for // this listener. if (url.empty()) @@ -77,21 +80,25 @@ bool LLSDMessage::httpListener(const LLSD& request) out << "request event without 'url' key to '" << mEventPump.getName() << "'"; throw ArgError(out.str()); } -#if 0 // AIFIXME: ignore this for now - // Establish default timeout. This test relies on LLSD::asReal() returning - // exactly 0.0 for an undef value. - if (! timeout) - { - timeout = HTTP_REQUEST_EXPIRY_SECS; - } -#endif - LLHTTPClient::post4(url, payload, - new LLSDMessage::EventResponder(LLEventPumps::instance(), - request, - url, "POST", reply, error)); + LLSDMessage::EventResponder* responder = + new LLSDMessage::EventResponder(LLEventPumps::instance(), request, url, "POST", reply, error); + responder->setTimeoutPolicy(timeoutpolicy); + LLHTTPClient::post4(url, payload, responder); return false; } +LLSDMessage::EventResponder::EventResponder(LLEventPumps& pumps, LLSD const& request, std::string const& target, + std::string const& message, std::string const& replyPump, std::string const& errorPump) : + mPumps(pumps), mReqID(request), mTarget(target), mMessage(message), mReplyPump(replyPump), mErrorPump(errorPump), + mHTTPTimeoutPolicy(AIHTTPTimeoutPolicy::getTimeoutPolicyByName(std::string())) +{ +} + +void LLSDMessage::EventResponder::setTimeoutPolicy(std::string const& name) +{ + mHTTPTimeoutPolicy = AIHTTPTimeoutPolicy::getTimeoutPolicyByName(name); +} + void LLSDMessage::EventResponder::result(const LLSD& data) { // If our caller passed an empty replyPump name, they're not @@ -137,7 +144,7 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string } } -LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder, +LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::Responder* responder, const std::string& name): mResponder(responder), mReplyPump(name + ".reply", true), // tweak name for uniqueness @@ -147,15 +154,25 @@ LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr respo mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false)); } +std::string LLSDMessage::ResponderAdapter::getTimeoutPolicyName(void) const +{ + return mResponder->getHTTPTimeoutPolicy().name(); +} + bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success) { + AICurlInterface::Responder* responder = dynamic_cast(mResponder.get()); + // If this assertion fails then ResponderAdapter has been used for a ResponderWithCompleted derived class, + // which is not allowed because ResponderAdapter can only work for classes derived from Responder that + // implement result() and errorWithContent (or just error). + llassert_always(responder); if (success) { - mResponder->pubResult(payload); + responder->pubResult(payload); } else { - mResponder->pubErrorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]); + responder->pubErrorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]); } /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/ diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h index 3d1ae814c..b839cbc74 100644 --- a/indra/llmessage/llsdmessage.h +++ b/indra/llmessage/llsdmessage.h @@ -90,13 +90,15 @@ public: * interesting if you suspect some usage will lead to an exception or * log message. */ - ResponderAdapter(LLHTTPClient::ResponderPtr responder, + ResponderAdapter(LLHTTPClient::Responder* responder, const std::string& name="ResponderAdapter"); /// EventPump name on which LLSDMessage should post reply event std::string getReplyName() const { return mReplyPump.getName(); } /// EventPump name on which LLSDMessage should post error event std::string getErrorName() const { return mErrorPump.getName(); } + /// Name of timeout policy to use. + std::string getTimeoutPolicyName() const; private: // We have two different LLEventStreams, though we route them both to @@ -126,7 +128,7 @@ private: class EventResponder: public LLHTTPClient::Responder { public: - virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return eventResponder_timeout; } + virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return *mHTTPTimeoutPolicy; } /** * LLHTTPClient::Responder that dispatches via named LLEventPump instances. @@ -144,14 +146,9 @@ private: EventResponder(LLEventPumps& pumps, const LLSD& request, const std::string& target, const std::string& message, - const std::string& replyPump, const std::string& errorPump): - mPumps(pumps), - mReqID(request), - mTarget(target), - mMessage(message), - mReplyPump(replyPump), - mErrorPump(errorPump) - {} + const std::string& replyPump, const std::string& errorPump); + + void setTimeoutPolicy(std::string const& name); virtual void result(const LLSD& data); virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); @@ -160,6 +157,7 @@ private: LLEventPumps& mPumps; LLReqID mReqID; const std::string mTarget, mMessage, mReplyPump, mErrorPump; + AIHTTPTimeoutPolicy const* mHTTPTimeoutPolicy; }; private: diff --git a/indra/newview/lggdicdownload.cpp b/indra/newview/lggdicdownload.cpp index 7bcaaac49..154d29063 100644 --- a/indra/newview/lggdicdownload.cpp +++ b/indra/newview/lggdicdownload.cpp @@ -52,7 +52,7 @@ class lggDicDownloadFloater; class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy emeraldDicDownloader_timeout; -class EmeraldDicDownloader : public LLHTTPClient::Responder +class EmeraldDicDownloader : public AICurlInterface::ResponderWithCompleted { public: EmeraldDicDownloader(lggDicDownloadFloater* spanel, std::string sname); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3a3c38c20..b2e1c2181 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2188,6 +2188,7 @@ void LLAgent::setStartPosition( U32 location_id ) request["payload"] = body; request["reply"] = adapter->getReplyName(); request["error"] = adapter->getErrorName(); + request["timeoutpolicy"] = adapter->getTimeoutPolicyName(); gAgent.getRegion()->getCapAPI().post(request); diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp index 75934c156..2ebaffd4f 100644 --- a/indra/newview/llcapabilitylistener.cpp +++ b/indra/newview/llcapabilitylistener.cpp @@ -84,7 +84,7 @@ bool LLCapabilityListener::capListener(const LLSD& request) LLSD payload(request["payload"]); LLSD::String reply(request["reply"]); LLSD::String error(request["error"]); - LLSD::Real timeout(request["timeout"]); + LLSD::String timeoutpolicy(request["timeoutpolicy"]); // If the LLSD doesn't even have a "message" key, we doubt it was intended // for this listener. if (cap.empty()) @@ -95,24 +95,15 @@ bool LLCapabilityListener::capListener(const LLSD& request) << LL_ENDL; return false; // in case fatal-error function isn't } -#if 0 // AIFIXME: ignore this for now - // Establish default timeout. This test relies on LLSD::asReal() returning - // exactly 0.0 for an undef value. - if (! timeout) - { - timeout = HTTP_REQUEST_EXPIRY_SECS; - } -#endif // Look up the url for the requested capability name. std::string url = mProvider.getCapability(cap); if (! url.empty()) { + LLSDMessage::EventResponder* responder = + new LLSDMessage::EventResponder(LLEventPumps::instance(), request, mProvider.getDescription(), cap, reply, error); + responder->setTimeoutPolicy(timeoutpolicy); // This capability is supported by the region to which we're talking. - LLHTTPClient::post4(url, payload, - new LLSDMessage::EventResponder(LLEventPumps::instance(), - request, - mProvider.getDescription(), - cap, reply, error)); + LLHTTPClient::post4(url, payload, responder); } else { diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index e7442483f..be7ede224 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -73,14 +73,10 @@ namespace void handleMessage(const LLSD& content); - virtual void error(U32 status, const std::string& reason); + virtual void error(U32 status, const std::string& reason); virtual void result(const LLSD& content); virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return eventPollResponder_timeout; } - virtual void completedRaw(U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const buffer_ptr_t& buffer); private: bool mDone; @@ -160,24 +156,6 @@ namespace << mPollURL << llendl; } - // virtual - void LLEventPollResponder::completedRaw(U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const buffer_ptr_t& buffer) - { - if (status == HTTP_BAD_GATEWAY) - { - // These errors are not parsable as LLSD, - // which LLHTTPClient::Responder::completedRaw will try to do. - completed(status, reason, LLSD()); - } - else - { - LLHTTPClient::Responder::completedRaw(status,reason,channels,buffer); - } - } - void LLEventPollResponder::makeRequest() { LLSD request; @@ -295,7 +273,7 @@ LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender) LLEventPoll::~LLEventPoll() { - LLHTTPClient::Responder* responderp = mImpl.get(); + AICurlInterface::ResponderBase* responderp = mImpl.get(); LLEventPollResponder* event_poll_responder = dynamic_cast(responderp); if (event_poll_responder) event_poll_responder->stop(); } diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index eeb53a98d..9f1cbca6c 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -1146,7 +1146,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t { //read base log into memory S32 i = 0; std::ifstream is(base.c_str()); - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDSerialize::fromXML(cur, is) > 0) { base_data[i++] = cur; } @@ -1159,7 +1159,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t { //read current log into memory S32 i = 0; std::ifstream is(target.c_str()); - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDSerialize::fromXML(cur, is) > 0) { cur_data[i++] = cur; @@ -1450,7 +1450,7 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is) stats_map_t time_stats; stats_map_t sample_stats; - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + while (!is.eof() && LLSDSerialize::fromXML(cur, is) > 0) { for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) { diff --git a/indra/newview/llfloateractivespeakers.cpp b/indra/newview/llfloateractivespeakers.cpp index 3b8bde610..968228fb2 100644 --- a/indra/newview/llfloateractivespeakers.cpp +++ b/indra/newview/llfloateractivespeakers.cpp @@ -849,7 +849,7 @@ void LLPanelActiveSpeakers::onModeratorMuteVoice(LLUICtrl* ctrl, void* user_data // ctrl value represents ability to type, so invert data["params"]["mute_info"]["voice"] = !ctrl->getValue(); - class MuteVoiceResponder : public LLHTTPClient::Responder + class MuteVoiceResponder : public LLHTTPClient::ResponderIgnoreBody { public: MuteVoiceResponder(const LLUUID& session_id) @@ -916,7 +916,7 @@ void LLPanelActiveSpeakers::onModeratorMuteText(LLUICtrl* ctrl, void* user_data) // ctrl value represents ability to type, so invert data["params"]["mute_info"]["text"] = !ctrl->getValue(); - class MuteTextResponder : public LLHTTPClient::Responder + class MuteTextResponder : public LLHTTPClient::ResponderIgnoreBody { public: MuteTextResponder(const LLUUID& session_id) @@ -990,7 +990,7 @@ void LLPanelActiveSpeakers::onChangeModerationMode(LLUICtrl* ctrl, void* user_da data["params"]["update_info"]["moderated_mode"]["voice"] = true; } - struct ModerationModeResponder : public LLHTTPClient::Responder + struct ModerationModeResponder : public LLHTTPClient::ResponderIgnoreBody { virtual void error(U32 status, const std::string& reason) { diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp index ad3e873eb..e0720d2b0 100644 --- a/indra/newview/llfloaterregiondebugconsole.cpp +++ b/indra/newview/llfloaterregiondebugconsole.cpp @@ -77,7 +77,7 @@ namespace // we assume that the simulator has received our request. Error will be // called if this request times out. // - class AsyncConsoleResponder : public LLHTTPClient::Responder + class AsyncConsoleResponder : public LLHTTPClient::ResponderIgnoreBody { public: /* virtual */ diff --git a/indra/newview/llfloaterregiondebugconsole.h b/indra/newview/llfloaterregiondebugconsole.h index 2636b6426..fdf975c48 100644 --- a/indra/newview/llfloaterregiondebugconsole.h +++ b/indra/newview/llfloaterregiondebugconsole.h @@ -40,14 +40,12 @@ extern AIHTTPTimeoutPolicy floaterRegionDebugConsole_timeout; typedef boost::signals2::signal< void (const std::string& output)> console_reply_signal_t; -class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Responder, public LLSingleton +class LLFloaterRegionDebugConsole : public LLFloater, public LLSingleton { public: LLFloaterRegionDebugConsole(); virtual ~LLFloaterRegionDebugConsole(); - virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return floaterRegionDebugConsole_timeout; } - // virtual BOOL postBuild(); void onClose(bool app_quitting); diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index f43619553..416458617 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -53,7 +53,7 @@ static LLFloaterURLEntry* sInstance = NULL; // Move this to its own file. // helper class that tries to download a URL from a web site and calls a method // on the Panel Land Media and to discover the MIME type -class LLMediaTypeResponder : public LLHTTPClient::Responder +class LLMediaTypeResponder : public LLHTTPClient::ResponderIgnoreBody { public: LLMediaTypeResponder( const LLHandle parent ) : diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 2d5ee2293..fe1bab58a 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -184,7 +184,7 @@ void start_deprecated_conference_chat( delete[] bucket; } -class LLStartConferenceChatResponder : public LLHTTPClient::Responder +class LLStartConferenceChatResponder : public LLHTTPClient::ResponderIgnoreBody { public: LLStartConferenceChatResponder( @@ -1558,7 +1558,7 @@ void LLFloaterIMPanel::draw() LLFloater::draw(); } -class LLSessionInviteResponder : public LLHTTPClient::Responder +class LLSessionInviteResponder : public LLHTTPClient::ResponderIgnoreBody { public: LLSessionInviteResponder(const LLUUID& session_id) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index cc2b7306f..cd406e3c5 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -210,7 +210,7 @@ S32 LLMeshRepoThread::sActiveHeaderRequests = 0; S32 LLMeshRepoThread::sActiveLODRequests = 0; U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; -class LLMeshHeaderResponder : public LLCurl::Responder +class LLMeshHeaderResponder : public LLCurl::ResponderWithCompleted { public: LLVolumeParams mMeshParams; @@ -233,7 +233,7 @@ public: virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshHeaderResponder_timeout; } }; -class LLMeshLODResponder : public LLCurl::Responder +class LLMeshLODResponder : public LLCurl::ResponderWithCompleted { public: LLVolumeParams mMeshParams; @@ -259,7 +259,7 @@ public: virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshLODResponder_timeout; } }; -class LLMeshSkinInfoResponder : public LLCurl::Responder +class LLMeshSkinInfoResponder : public LLCurl::ResponderWithCompleted { public: LLUUID mMeshID; @@ -278,7 +278,7 @@ public: virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshSkinInfoResponder_timeout; } }; -class LLMeshDecompositionResponder : public LLCurl::Responder +class LLMeshDecompositionResponder : public LLCurl::ResponderWithCompleted { public: LLUUID mMeshID; @@ -297,7 +297,7 @@ public: virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshDecompositionResponder_timeout; } }; -class LLMeshPhysicsShapeResponder : public LLCurl::Responder +class LLMeshPhysicsShapeResponder : public LLCurl::ResponderWithCompleted { public: LLUUID mMeshID; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index a10e9f0cb..1bfbcc702 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -168,7 +168,7 @@ std::string gFullName; // helper class that trys to download a URL from a web site and calls a method // on parent class indicating if the web server is working or not -class LLIamHereLogin : public LLHTTPClient::Responder +class LLIamHereLogin : public AICurlInterface::ResponderWithCompleted { private: LLIamHereLogin( LLPanelLogin* parent ) : @@ -193,20 +193,11 @@ class LLIamHereLogin : public LLHTTPClient::Responder const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - completed(status, reason, LLSD()); // will call result() or error() + if (mParent) + { + mParent->setSiteIsAlive(200 <= status && status < 300); + } } - - virtual void result( const LLSD& content ) - { - if ( mParent ) - mParent->setSiteIsAlive( true ); - }; - - virtual void error( U32 status, const std::string& reason ) - { - if ( mParent ) - mParent->setSiteIsAlive( false ); - }; virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return iamHereLogin_timeout; } }; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 159110fc0..561c19129 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -292,7 +292,7 @@ private: }; ////////////////////////////////////////////////////////////////////////////// -class HTTPGetResponder : public LLCurl::Responder +class HTTPGetResponder : public AICurlInterface::ResponderWithCompleted { LOG_CLASS(HTTPGetResponder); public: diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index e5590de87..d4a89d3a4 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -58,7 +58,7 @@ namespace LLViewerDisplayName } -class LLSetDisplayNameResponder : public LLHTTPClient::Responder +class LLSetDisplayNameResponder : public LLHTTPClient::ResponderIgnoreBody { public: // only care about errors diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 25acb0b83..b818ae50c 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -71,7 +71,7 @@ const int RIGHT_BUTTON = 1; /////////////////////////////////////////////////////////////////////////////// // Helper class that tries to download a URL from a web site and calls a method // on the Panel Land Media and to discover the MIME type -class LLMimeDiscoveryResponder : public LLHTTPClient::Responder +class LLMimeDiscoveryResponder : public AICurlInterface::ResponderWithCompleted { LOG_CLASS(LLMimeDiscoveryResponder); public: @@ -111,7 +111,7 @@ public: bool mInitialized; }; -class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder +class LLViewerMediaOpenIDResponder : public AICurlInterface::ResponderWithCompleted { LOG_CLASS(LLViewerMediaOpenIDResponder); public: @@ -150,7 +150,7 @@ public: virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return viewerMediaOpenIDResponder_timeout; } }; -class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder +class LLViewerMediaWebProfileResponder : public AICurlInterface::ResponderWithCompleted { LOG_CLASS(LLViewerMediaWebProfileResponder); public: diff --git a/indra/newview/llxmlrpcresponder.h b/indra/newview/llxmlrpcresponder.h index ffb06f14d..c52756f03 100644 --- a/indra/newview/llxmlrpcresponder.h +++ b/indra/newview/llxmlrpcresponder.h @@ -105,7 +105,7 @@ public: XMLRPC_REQUEST response(void) const { return mResponse; } LLXMLRPCValue responseValue(void) const; - /*virtual*/ void received_HTTP_header(void) { mReceivedHTTPHeader = true; LLCurl::Responder::received_HTTP_header(); } + /*virtual*/ void received_HTTP_header(void) { mReceivedHTTPHeader = true; LLCurl::ResponderBase::received_HTTP_header(); } /*virtual*/ void completed_headers(U32 status, std::string const& reason, CURLcode code, AICurlInterface::TransferInfo* info); /*virtual*/ void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return XMLRPCResponder_timeout; }