ResponderAdapter stuff

Renamed AICurlInterface::Responder to AICurlInterface::ResponderBase,
but without the virtual 'event' methods.
Derived from that: Responder and ReponderWithCompleted, where the
first defines result = 0, ErrorWithContent and error, and the latter
completedRaw and completed.
Added HttpClient::IgnoreBody, derived from Responder and implementing
'result' doing nothing; HttpClient::Ignore is now derived from
IgnoreBody and defines the still pure virtual getHTTPTimeoutPolicy.

Added ResponderBase::decode_body, which is now the sole place
where the code makes the decision wether some response data might be
LLSD or not based on the http status result. Before it just tried
to decode everything as LLSD, which seems a bit nonsense.

ResponderWithCompleted::completed no longer does anything, since
classes derived from ResponderWithCompleted are expected to override it,
or never call it by overriding completedRaw.

Entry point is now ResponderBase::finished = 0, instead of
completedRaw, where ResponderWithCompleted implements finished by
called completedRaw, but Responder doesn't: that directly calls
result/errorWithContent/error. Or, for the hack ResponderAdapter,
the entry points are pubResult/pubErrorWithContent.
Those are now the ONLY public methods, so more confusion.
mFinished is now set in all cases.

As a result of all that, it is no longer possible to accidently
pass a responder to ResponderAdapter that would break because it
expects completed() and completedRaw() to be called.

Added LLBufferArray::writeChannelTo.

Fixed bug for BlockingResponder::body (returned reference to temporary).

LLSDMessage::ResponderAdapter now allows a "timeoutpolicy" name
to be passed (not doing so results in the default timings), so
that the timeout policy of the used responder is retained.

Fixed llfasttimerview.cpp to test LLSDSerialize::fromXML() to return
a positive value instead of non-zero, because it may return -1 when the
parsing fails (three places).

Removed LLHTTPClient::Responder as base class from
LLFloaterRegionDebugConsole completely: it isn't a responder!

Several other responder classes were simplified a bit in order to
compile again with the above changes.
This commit is contained in:
Aleric Inglewood
2012-10-26 03:47:05 +02:00
parent 33809f56c5
commit 2a88f7d7c4
27 changed files with 244 additions and 169 deletions

View File

@@ -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

View File

@@ -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<LLBufferArray> 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<ResponderBase> is made.
friend void intrusive_ptr_release(ResponderBase* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr<ResponderBase> 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<Responder> is made.
friend void intrusive_ptr_release(Responder* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr<Responder> 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<Responder> ResponderPtr;
typedef boost::intrusive_ptr<ResponderBase> 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;

View File

@@ -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);

View File

@@ -33,6 +33,7 @@
#include "stdtypes.h"
#include <string>
#include <map>
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<std::string, AIHTTPTimeoutPolicy*> 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);

View File

@@ -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,

View File

@@ -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.

View File

@@ -41,8 +41,8 @@ class AIHTTPHeaders;
namespace AICurlInterface {
// Forward declaration.
class Responder;
typedef boost::intrusive_ptr<Responder> ResponderPtr;
class ResponderBase;
typedef boost::intrusive_ptr<ResponderBase> ResponderPtr;
class Request {
public:

View File

@@ -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
{

View File

@@ -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 */
//@{

View File

@@ -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<AICurlInterface::Responder*>(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 ----------------*/

View File

@@ -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:

View File

@@ -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);

View File

@@ -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);

View File

@@ -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
{

View File

@@ -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<LLEventPollResponder*>(responderp);
if (event_poll_responder) event_poll_responder->stop();
}

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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 */

View File

@@ -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<LLFloaterRegionDebugConsole>
class LLFloaterRegionDebugConsole : public LLFloater, public LLSingleton<LLFloaterRegionDebugConsole>
{
public:
LLFloaterRegionDebugConsole();
virtual ~LLFloaterRegionDebugConsole();
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return floaterRegionDebugConsole_timeout; }
// virtual
BOOL postBuild();
void onClose(bool app_quitting);

View File

@@ -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<LLFloater> parent ) :

View File

@@ -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)

View File

@@ -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;

View File

@@ -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; }
};

View File

@@ -292,7 +292,7 @@ private:
};
//////////////////////////////////////////////////////////////////////////////
class HTTPGetResponder : public LLCurl::Responder
class HTTPGetResponder : public AICurlInterface::ResponderWithCompleted
{
LOG_CLASS(HTTPGetResponder);
public:

View File

@@ -58,7 +58,7 @@ namespace LLViewerDisplayName
}
class LLSetDisplayNameResponder : public LLHTTPClient::Responder
class LLSetDisplayNameResponder : public LLHTTPClient::ResponderIgnoreBody
{
public:
// only care about errors

View File

@@ -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:

View File

@@ -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; }