From 243db9a3a8727b0da6ac8b32805e815fdab22c47 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Mon, 22 Oct 2012 22:52:18 +0200 Subject: [PATCH] Moved mFinished/is_finished() from LegacyPolledResponder to Responder. Slightly more robust, adds one boolean to all responders, 99% of which don't need that though, and an extra call redirection, but well... We might need it this way when I add the possibility to abort a transfer. --- indra/aistatemachine/aicurl.cpp | 4 +-- indra/aistatemachine/aicurl.h | 45 +++++++++++++++++---------- indra/aistatemachine/aicurlthread.cpp | 2 +- indra/llmessage/llhttpclient.cpp | 2 ++ indra/newview/llxmlrpcresponder.cpp | 1 - 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/indra/aistatemachine/aicurl.cpp b/indra/aistatemachine/aicurl.cpp index 65457cd80..537d12e2f 100644 --- a/indra/aistatemachine/aicurl.cpp +++ b/indra/aistatemachine/aicurl.cpp @@ -433,7 +433,7 @@ std::string strerror(CURLcode errorcode) // class Responder // -Responder::Responder(void) : mReferenceCount(0) +Responder::Responder(void) : mReferenceCount(0), mFinished(false) { DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this); } @@ -1340,7 +1340,7 @@ CurlResponderBuffer::~CurlResponderBuffer() void CurlResponderBuffer::timed_out(void) { - mResponder->completedRaw(HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput); + mResponder->finished(HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput); mResponder = NULL; } diff --git a/indra/aistatemachine/aicurl.h b/indra/aistatemachine/aicurl.h index 767a6dabc..53f7af394 100644 --- a/indra/aistatemachine/aicurl.h +++ b/indra/aistatemachine/aicurl.h @@ -215,6 +215,9 @@ class Responder : public AICurlResponderBufferEvents { // Headers received from the server. AIHTTPReceivedHeaders mReceivedHeaders; + // Set when the transaction finished (with or without errors). + bool mFinished; + public: // Called to set the URL of the current request for this Responder, // used only when printing debug output regarding activity of the Responder. @@ -223,6 +226,20 @@ class Responder : public AICurlResponderBufferEvents { // Accessor. 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; + } + + // Return true if the curl thread is done with this transaction. + // If this returns true then it is guaranteed that none of the + // virtual functions will be called anymore: the curl thread + // will not access this object anymore. + // Note that normally you don't need to call this function. + bool is_finished(void) const { return mFinished; } + protected: // Called when the "HTTP/1.x " header is received. /*virtual*/ void received_HTTP_header(void) @@ -244,12 +261,6 @@ class Responder : public AICurlResponderBufferEvents { completedHeaders(status, reason, mReceivedHeaders); } - // Derived classes can override this to get the HTML headers that were received, when the message is completed. - virtual void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) - { - // The default does nothing. - } - public: // Derived classes that implement completed_headers()/completedHeaders() should return true here. virtual bool needsHeaders(void) const { return false; } @@ -257,15 +268,21 @@ class Responder : public AICurlResponderBufferEvents { // Timeout policy to use. virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0; - // 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); - // A derived class should return true if curl should follow redirections. // The default is not to follow redirections. virtual bool followRedir(void) { return false; } protected: + // Derived classes can override this to get the HTML headers that were received, when the message is completed. + virtual void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) + { + // The default does nothing. + } + + // 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); + // ... or, derived classes can override this to get the LLSD content when the message is completed. // 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); @@ -278,7 +295,7 @@ class Responder : public AICurlResponderBufferEvents { // The default calls error(). virtual void errorWithContent(U32 status, std::string const& reason, LLSD const& content); - // ... or, derived classes can override this to get informed when a bad HTML statis code is received. + // ... or, derived classes can override this to get informed when a bad HTML status code is received. // The default prints the error to llinfos. virtual void error(U32 status, std::string const& reason); @@ -311,21 +328,17 @@ class LegacyPolledResponder : public Responder { CURLcode mCode; U32 mStatus; std::string mReason; - bool mFinished; public: - LegacyPolledResponder(void) : mCode(CURLE_FAILED_INIT), mStatus(HTTP_INTERNAL_ERROR), mFinished(false) { } + LegacyPolledResponder(void) : mCode(CURLE_FAILED_INIT), mStatus(HTTP_INTERNAL_ERROR) { } // Accessors. CURLcode result_code(void) const { return mCode; } U32 http_status(void) const { return mStatus; } - bool is_finished(void) const { return mFinished; } std::string const& reason(void) const { return mReason; } /*virtual*/ bool needsHeaders(void) const { return true; } /*virtual*/ void completed_headers(U32 status, std::string const& reason, CURLcode code, AICurlInterface::TransferInfo* info); - // This must be defined by the derived class and set mFinished = true at the end. - /*virtual*/ void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) = 0; }; } // namespace AICurlInterface diff --git a/indra/aistatemachine/aicurlthread.cpp b/indra/aistatemachine/aicurlthread.cpp index e03d92e7f..61a1a1961 100644 --- a/indra/aistatemachine/aicurlthread.cpp +++ b/indra/aistatemachine/aicurlthread.cpp @@ -2109,7 +2109,7 @@ void CurlResponderBuffer::processOutput(AICurlEasyRequest_wat& curl_easy_request // the body and provide completed/result/error calls. mEventsTarget->completed_headers(responseCode, responseReason, code, (code == CURLE_FAILED_INIT) ? NULL : &info); } - mResponder->completedRaw(responseCode, responseReason, sChannels, mOutput); + mResponder->finished(responseCode, responseReason, sChannels, mOutput); mResponder = NULL; } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 6f7db978d..26c7b39e0 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -258,6 +258,8 @@ void BlockingResponder::completedRaw(U32, std::string const&, LLChannelDescripto mBody << istr; } } + // 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(); mFinished = true; mSignal.unlock(); diff --git a/indra/newview/llxmlrpcresponder.cpp b/indra/newview/llxmlrpcresponder.cpp index a19bcdd9e..a66b0a1f7 100644 --- a/indra/newview/llxmlrpcresponder.cpp +++ b/indra/newview/llxmlrpcresponder.cpp @@ -205,7 +205,6 @@ void XMLRPCResponder::completedRaw(U32 status, std::string const& reason, LLChan } } } - mFinished = true; } LLXMLRPCValue XMLRPCResponder::responseValue(void) const