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.
This commit is contained in:
Aleric Inglewood
2012-10-22 22:52:18 +02:00
parent daac25c343
commit 243db9a3a8
5 changed files with 34 additions and 20 deletions

View File

@@ -433,7 +433,7 @@ std::string strerror(CURLcode errorcode)
// class Responder // class Responder
// //
Responder::Responder(void) : mReferenceCount(0) Responder::Responder(void) : mReferenceCount(0), mFinished(false)
{ {
DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this); DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this);
} }
@@ -1340,7 +1340,7 @@ CurlResponderBuffer::~CurlResponderBuffer()
void CurlResponderBuffer::timed_out(void) 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; mResponder = NULL;
} }

View File

@@ -215,6 +215,9 @@ class Responder : public AICurlResponderBufferEvents {
// Headers received from the server. // Headers received from the server.
AIHTTPReceivedHeaders mReceivedHeaders; AIHTTPReceivedHeaders mReceivedHeaders;
// Set when the transaction finished (with or without errors).
bool mFinished;
public: public:
// Called to set the URL of the current request for this Responder, // Called to set the URL of the current request for this Responder,
// used only when printing debug output regarding activity of the Responder. // used only when printing debug output regarding activity of the Responder.
@@ -223,6 +226,20 @@ class Responder : public AICurlResponderBufferEvents {
// Accessor. // Accessor.
std::string const& getURL(void) const { return mURL; } 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: protected:
// Called when the "HTTP/1.x <status> <reason>" header is received. // Called when the "HTTP/1.x <status> <reason>" header is received.
/*virtual*/ void received_HTTP_header(void) /*virtual*/ void received_HTTP_header(void)
@@ -244,12 +261,6 @@ class Responder : public AICurlResponderBufferEvents {
completedHeaders(status, reason, mReceivedHeaders); 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: public:
// Derived classes that implement completed_headers()/completedHeaders() should return true here. // Derived classes that implement completed_headers()/completedHeaders() should return true here.
virtual bool needsHeaders(void) const { return false; } virtual bool needsHeaders(void) const { return false; }
@@ -257,15 +268,21 @@ class Responder : public AICurlResponderBufferEvents {
// Timeout policy to use. // Timeout policy to use.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0; 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. // A derived class should return true if curl should follow redirections.
// The default is not to follow redirections. // The default is not to follow redirections.
virtual bool followRedir(void) { return false; } virtual bool followRedir(void) { return false; }
protected: 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. // ... 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). // 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); virtual void completed(U32 status, std::string const& reason, LLSD const& content);
@@ -278,7 +295,7 @@ class Responder : public AICurlResponderBufferEvents {
// The default calls error(). // The default calls error().
virtual void errorWithContent(U32 status, std::string const& reason, LLSD const& content); 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. // The default prints the error to llinfos.
virtual void error(U32 status, std::string const& reason); virtual void error(U32 status, std::string const& reason);
@@ -311,21 +328,17 @@ class LegacyPolledResponder : public Responder {
CURLcode mCode; CURLcode mCode;
U32 mStatus; U32 mStatus;
std::string mReason; std::string mReason;
bool mFinished;
public: public:
LegacyPolledResponder(void) : mCode(CURLE_FAILED_INIT), mStatus(HTTP_INTERNAL_ERROR), mFinished(false) { } LegacyPolledResponder(void) : mCode(CURLE_FAILED_INIT), mStatus(HTTP_INTERNAL_ERROR) { }
// Accessors. // Accessors.
CURLcode result_code(void) const { return mCode; } CURLcode result_code(void) const { return mCode; }
U32 http_status(void) const { return mStatus; } U32 http_status(void) const { return mStatus; }
bool is_finished(void) const { return mFinished; }
std::string const& reason(void) const { return mReason; } std::string const& reason(void) const { return mReason; }
/*virtual*/ bool needsHeaders(void) const { return true; } /*virtual*/ bool needsHeaders(void) const { return true; }
/*virtual*/ void completed_headers(U32 status, std::string const& reason, CURLcode code, AICurlInterface::TransferInfo* info); /*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 } // namespace AICurlInterface

View File

@@ -2109,7 +2109,7 @@ void CurlResponderBuffer::processOutput(AICurlEasyRequest_wat& curl_easy_request
// the body and provide completed/result/error calls. // the body and provide completed/result/error calls.
mEventsTarget->completed_headers(responseCode, responseReason, code, (code == CURLE_FAILED_INIT) ? NULL : &info); 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; mResponder = NULL;
} }

View File

@@ -258,6 +258,8 @@ void BlockingResponder::completedRaw(U32, std::string const&, LLChannelDescripto
mBody << istr; 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(); mSignal.lock();
mFinished = true; mFinished = true;
mSignal.unlock(); mSignal.unlock();

View File

@@ -205,7 +205,6 @@ void XMLRPCResponder::completedRaw(U32 status, std::string const& reason, LLChan
} }
} }
} }
mFinished = true;
} }
LLXMLRPCValue XMLRPCResponder::responseValue(void) const LLXMLRPCValue XMLRPCResponder::responseValue(void) const