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

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