diff options
Diffstat (limited to 'indra/newview/llmediadataclient.cpp')
-rwxr-xr-x | indra/newview/llmediadataclient.cpp | 563 |
1 files changed, 296 insertions, 267 deletions
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 2fb9e60b29..bfd0700a2f 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -33,6 +33,7 @@ #pragma warning (disable:4702) #endif +#include <algorithm> #include <boost/lexical_cast.hpp> #include "llhttpconstants.h" @@ -40,6 +41,7 @@ #include "llmediaentry.h" #include "lltextureentry.h" #include "llviewerregion.h" +#include "llcorehttputil.h" // // When making a request @@ -91,52 +93,74 @@ const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000; std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q); std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &q); -template <typename T> -typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type) + +//========================================================================= +/// Uniary Predicate for matching requests in collections by either the request +/// or by UUID +/// +class PredicateMatchRequest { - for(typename T::iterator iter = c.begin(); iter != c.end(); ++iter) - { - if(request->isMatch(*iter, match_type)) - { - return iter; - } - } - - return c.end(); +public: + PredicateMatchRequest(const LLMediaDataClient::Request::ptr_t &request, LLMediaDataClient::Request::Type matchType = LLMediaDataClient::Request::ANY); + PredicateMatchRequest(const LLUUID &id, LLMediaDataClient::Request::Type matchType = LLMediaDataClient::Request::ANY); + + PredicateMatchRequest(const PredicateMatchRequest &other); + + bool operator()(const LLMediaDataClient::Request::ptr_t &test) const; + +private: + LLMediaDataClient::Request::ptr_t mRequest; + LLMediaDataClient::Request::Type mMatchType; + LLUUID mId; +}; + + +PredicateMatchRequest::PredicateMatchRequest(const LLMediaDataClient::Request::ptr_t &request, LLMediaDataClient::Request::Type matchType) : + mRequest(request), + mMatchType(matchType), + mId() +{} + +PredicateMatchRequest::PredicateMatchRequest(const LLUUID &id, LLMediaDataClient::Request::Type matchType) : + mRequest(), + mMatchType(matchType), + mId(id) +{} + +PredicateMatchRequest::PredicateMatchRequest(const PredicateMatchRequest &other) +{ + mRequest = other.mRequest; + mMatchType = other.mMatchType; + mId = other.mId; } -template <typename T> -typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type) +bool PredicateMatchRequest::operator()(const LLMediaDataClient::Request::ptr_t &test) const { - for(typename T::iterator iter = c.begin(); iter != c.end(); ++iter) - { - if(((*iter)->getID() == id) && ((match_type == LLMediaDataClient::Request::ANY) || (match_type == (*iter)->getType()))) - { - return iter; - } - } - - return c.end(); + if (mRequest) + return (mRequest->isMatch(test, mMatchType)); + else if (!mId.isNull()) + return ((test->getID() == mId) && ((mMatchType == LLMediaDataClient::Request::ANY) || (mMatchType == test->getType()))); + return false; } -// NOTE: remove_matching_requests will not work correctly for containers where deleting an element may invalidate iterators -// to other elements in the container (such as std::vector). -// If the implementation is changed to use a container with this property, this will need to be revisited. +//========================================================================= +/// template <typename T> -void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type) +void mark_dead_and_remove_if(T &c, const PredicateMatchRequest &matchPred) { - for(typename T::iterator iter = c.begin(); iter != c.end();) - { - typename T::value_type i = *iter; - typename T::iterator next = iter; - next++; - if((i->getID() == id) && ((match_type == LLMediaDataClient::Request::ANY) || (match_type == i->getType()))) - { - i->markDead(); - c.erase(iter); - } - iter = next; - } + for (typename T::iterator it = c.begin(); it != c.end();) + { + if (matchPred(*it)) + { + (*it)->markDead(); + // *TDOO: When C++11 is in change the following line to: it = c.erase(it); + c.erase(it++); + } + else + { + ++it; + } + } } ////////////////////////////////////////////////////////////////////////////////////// @@ -145,18 +169,20 @@ void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request // ////////////////////////////////////////////////////////////////////////////////////// -LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, - F32 retry_timer_delay, - U32 max_retries, - U32 max_sorted_queue_size, - U32 max_round_robin_queue_size) - : mQueueTimerDelay(queue_timer_delay), - mRetryTimerDelay(retry_timer_delay), - mMaxNumRetries(max_retries), - mMaxSortedQueueSize(max_sorted_queue_size), - mMaxRoundRobinQueueSize(max_round_robin_queue_size), - mQueueTimerIsRunning(false) +LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, F32 retry_timer_delay, + U32 max_retries, U32 max_sorted_queue_size, U32 max_round_robin_queue_size): + mQueueTimerDelay(queue_timer_delay), + mRetryTimerDelay(retry_timer_delay), + mMaxNumRetries(max_retries), + mMaxSortedQueueSize(max_sorted_queue_size), + mMaxRoundRobinQueueSize(max_round_robin_queue_size), + mQueueTimerIsRunning(false), + mHttpRequest(new LLCore::HttpRequest()), + mHttpHeaders(new LLCore::HttpHeaders()), + mHttpOpts(new LLCore::HttpOptions()), + mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) { + // *TODO: Look up real Policy ID } LLMediaDataClient::~LLMediaDataClient() @@ -171,20 +197,23 @@ bool LLMediaDataClient::isEmpty() const bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object) { - if(find_matching_request(mQueue, object->getID(), LLMediaDataClient::Request::ANY) != mQueue.end()) - return true; - - if(find_matching_request(mUnQueuedRequests, object->getID(), LLMediaDataClient::Request::ANY) != mUnQueuedRequests.end()) - return true; - + PredicateMatchRequest upred(object->getID()); + + if (std::find_if(mQueue.begin(), mQueue.end(), upred) != mQueue.end()) + return true; + if (std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred) != mUnQueuedRequests.end()) + return true; + return false; } void LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object) { LL_DEBUGS("LLMediaDataClient") << "removing requests matching ID " << object->getID() << LL_ENDL; - remove_matching_requests(mQueue, object->getID(), LLMediaDataClient::Request::ANY); - remove_matching_requests(mUnQueuedRequests, object->getID(), LLMediaDataClient::Request::ANY); + PredicateMatchRequest upred(object->getID()); + + mark_dead_and_remove_if(mQueue, upred); + mark_dead_and_remove_if(mUnQueuedRequests, upred); } void LLMediaDataClient::startQueueTimer() @@ -207,23 +236,24 @@ void LLMediaDataClient::stopQueueTimer() bool LLMediaDataClient::processQueueTimer() { - if(isEmpty()) + if (isDoneProcessing()) return true; LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue size is: " << mQueue.size() << LL_ENDL; LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, SORTED queue is: " << mQueue << LL_ENDL; serviceQueue(); - + serviceHttp(); + LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue size is: " << mQueue.size() << LL_ENDL; LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, SORTED queue is: " << mQueue << LL_ENDL; - return isEmpty(); + return isDoneProcessing(); } -LLMediaDataClient::request_ptr_t LLMediaDataClient::dequeue() +LLMediaDataClient::Request::ptr_t LLMediaDataClient::dequeue() { - request_ptr_t request; + Request::ptr_t request; request_queue_t *queue_p = getQueue(); if (queue_p->empty()) @@ -242,20 +272,20 @@ LLMediaDataClient::request_ptr_t LLMediaDataClient::dequeue() else { // Don't return this request -- it's not ready to be serviced. - request = NULL; + request.reset(); } } return request; } -void LLMediaDataClient::pushBack(request_ptr_t request) +void LLMediaDataClient::pushBack(Request::ptr_t request) { request_queue_t *queue_p = getQueue(); queue_p->push_front(request); } -void LLMediaDataClient::trackRequest(request_ptr_t request) +void LLMediaDataClient::trackRequest(Request::ptr_t request) { request_set_t::iterator iter = mUnQueuedRequests.find(request); @@ -269,7 +299,7 @@ void LLMediaDataClient::trackRequest(request_ptr_t request) } } -void LLMediaDataClient::stopTrackingRequest(request_ptr_t request) +void LLMediaDataClient::stopTrackingRequest(Request::ptr_t request) { request_set_t::iterator iter = mUnQueuedRequests.find(request); @@ -283,16 +313,22 @@ void LLMediaDataClient::stopTrackingRequest(request_ptr_t request) } } +bool LLMediaDataClient::isDoneProcessing() const +{ + return (isEmpty() && mUnQueuedRequests.empty()); +} + + void LLMediaDataClient::serviceQueue() { // Peel one off of the items from the queue and execute it - request_ptr_t request; + Request::ptr_t request; do { request = dequeue(); - if(request.isNull()) + if(!request) { // Queue is empty. return; @@ -317,7 +353,18 @@ void LLMediaDataClient::serviceQueue() trackRequest(request); // and make the post - LLHTTPClient::post(url, sd_payload, request->createResponder()); + LLHttpSDHandler *handler = request->createHandler(); + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, 0, + url, sd_payload, mHttpOpts, mHttpHeaders, handler); + + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP + delete handler; + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_WARNS("LLMediaDataClient") << "'" << url << "' request POST failed. Reason " + << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL; + } } else { @@ -332,13 +379,17 @@ void LLMediaDataClient::serviceQueue() } else { - // This request has exceeded its maxumim retry count. It will be dropped. + // This request has exceeded its maximum retry count. It will be dropped. LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " << mMaxNumRetries << " tries, dropping request." << LL_ENDL; } } } +void LLMediaDataClient::serviceHttp() +{ + mHttpRequest->update(0); +} // dump the queue std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q) @@ -395,7 +446,7 @@ BOOL LLMediaDataClient::QueueTimer::tick() // ////////////////////////////////////////////////////////////////////////////////////// -LLMediaDataClient::RetryTimer::RetryTimer(F32 time, request_ptr_t request) +LLMediaDataClient::RetryTimer::RetryTimer(F32 time, Request::ptr_t request) : LLEventTimer(time), mRequest(request) { mRequest->startTracking(); @@ -417,7 +468,7 @@ BOOL LLMediaDataClient::RetryTimer::tick() } // Release the ref to the request. - mRequest = NULL; + mRequest.reset(); // Don't fire again return TRUE; @@ -490,7 +541,7 @@ void LLMediaDataClient::Request::reEnqueue() { if(mMDC) { - mMDC->enqueue(this); + mMDC->enqueue(shared_from_this()); } } @@ -533,13 +584,13 @@ bool LLMediaDataClient::Request::isDead() void LLMediaDataClient::Request::startTracking() { if(mMDC) - mMDC->trackRequest(this); + mMDC->trackRequest(shared_from_this()); } void LLMediaDataClient::Request::stopTracking() { if(mMDC) - mMDC->stopTrackingRequest(this); + mMDC->stopTrackingRequest(shared_from_this()); } std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) @@ -551,79 +602,61 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r) << " #retries=" << r.getRetryCount(); return s; } - -////////////////////////////////////////////////////////////////////////////////////// -// -// LLMediaDataClient::Responder -// -////////////////////////////////////////////////////////////////////////////////////// -LLMediaDataClient::Responder::Responder(const request_ptr_t &request) -: mRequest(request) +//======================================================================== + +LLMediaDataClient::Handler::Handler(const Request::ptr_t &request): + mRequest(request) { } -/*virtual*/ -void LLMediaDataClient::Responder::httpFailure() + +void LLMediaDataClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { - mRequest->stopTracking(); + mRequest->stopTracking(); - if(mRequest->isDead()) - { - LL_WARNS("LLMediaDataClient") << "dead request " << *mRequest << LL_ENDL; - return; - } - - if (getStatus() == HTTP_SERVICE_UNAVAILABLE) - { - F32 retry_timeout; -#if 0 - // *TODO: Honor server Retry-After header. - if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER) - || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout)) -#endif - { - retry_timeout = mRequest->getRetryTimerDelay(); - } - - mRequest->incRetryCount(); - - if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) - { - LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; - - // Start timer (instances are automagically tracked by - // InstanceTracker<> and LLEventTimer) - new RetryTimer(F32(retry_timeout/*secs*/), mRequest); - } - else - { - LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " - << mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; - } - } - // *TODO: Redirect on 3xx status codes. - else - { - LL_WARNS("LLMediaDataClient") << *mRequest << " http failure " - << dumpResponse() << LL_ENDL; - } + if (mRequest->isDead()) + { + LL_WARNS("LLMediaDataClient") << "dead request " << *mRequest << LL_ENDL; + return; + } + + LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << LL_ENDL; } -/*virtual*/ -void LLMediaDataClient::Responder::httpSuccess() +void LLMediaDataClient::Handler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) { - mRequest->stopTracking(); + mRequest->stopTracking(); - if(mRequest->isDead()) - { - LL_WARNS("LLMediaDataClient") << "dead request " << *mRequest << LL_ENDL; - return; - } + if (status == LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE)) + { + F32 retry_timeout; + + retry_timeout = mRequest->getRetryTimerDelay(); + + mRequest->incRetryCount(); + + if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) + { + LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL; - LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " " << dumpResponse() << LL_ENDL; + // Start timer (instances are automagically tracked by + // InstanceTracker<> and LLEventTimer) + new RetryTimer(F32(retry_timeout/*secs*/), mRequest); + } + else + { + LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " + << mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; + } + } + else + { + LL_WARNS("LLMediaDataClient") << *mRequest << " HTTP failure " << LL_ENDL; + } } + ////////////////////////////////////////////////////////////////////////////////////// // // LLObjectMediaDataClient @@ -634,7 +667,7 @@ void LLMediaDataClient::Responder::httpSuccess() void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object) { // Create a get request and put it in the queue. - enqueue(new RequestGet(object, this)); + enqueue(Request::ptr_t(new RequestGet(object, this))); } const char *LLObjectMediaDataClient::getCapabilityName() const @@ -678,14 +711,14 @@ void LLObjectMediaDataClient::sortQueue() } // static -bool LLObjectMediaDataClient::compareRequestScores(const request_ptr_t &o1, const request_ptr_t &o2) +bool LLObjectMediaDataClient::compareRequestScores(const Request::ptr_t &o1, const Request::ptr_t &o2) { - if (o2.isNull()) return true; - if (o1.isNull()) return false; + if (!o2) return true; + if (!o1) return false; return ( o1->getScore() > o2->getScore() ); } -void LLObjectMediaDataClient::enqueue(Request *request) +void LLObjectMediaDataClient::enqueue(Request::ptr_t request) { if(request->isDead()) { @@ -703,9 +736,10 @@ void LLObjectMediaDataClient::enqueue(Request *request) { // For GET requests that are not new, if a matching request is already in the round robin queue, // in flight, or being retried, leave it at its current position. - request_queue_t::iterator iter = find_matching_request(mRoundRobinQueue, request->getID(), Request::GET); - request_set_t::iterator iter2 = find_matching_request(mUnQueuedRequests, request->getID(), Request::GET); - + PredicateMatchRequest upred(request->getID(), Request::GET); + request_queue_t::iterator iter = std::find_if(mRoundRobinQueue.begin(), mRoundRobinQueue.end(), upred); + request_set_t::iterator iter2 = std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred); + if( (iter != mRoundRobinQueue.end()) || (iter2 != mUnQueuedRequests.end()) ) { LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL; @@ -718,9 +752,11 @@ void LLObjectMediaDataClient::enqueue(Request *request) // IF the update will cause an object update message to be sent out at some point in the future, it probably should. // Remove any existing requests of this type for this object - remove_matching_requests(mQueue, request->getID(), request->getType()); - remove_matching_requests(mRoundRobinQueue, request->getID(), request->getType()); - remove_matching_requests(mUnQueuedRequests, request->getID(), request->getType()); + PredicateMatchRequest upred(request->getID(), request->getType()); + + mark_dead_and_remove_if(mQueue, upred); + mark_dead_and_remove_if(mRoundRobinQueue, upred); + mark_dead_and_remove_if(mUnQueuedRequests, upred); if (is_new) { @@ -749,7 +785,7 @@ void LLObjectMediaDataClient::enqueue(Request *request) startQueueTimer(); } -bool LLObjectMediaDataClient::canServiceRequest(request_ptr_t request) +bool LLObjectMediaDataClient::canServiceRequest(Request::ptr_t request) { if(mCurrentQueueIsTheSortedQueue) { @@ -785,9 +821,9 @@ bool LLObjectMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &ob if(LLMediaDataClient::isInQueue(object)) return true; - if(find_matching_request(mRoundRobinQueue, object->getID(), LLMediaDataClient::Request::ANY) != mRoundRobinQueue.end()) - return true; - + if (std::find_if(mRoundRobinQueue.begin(), mRoundRobinQueue.end(), PredicateMatchRequest(object->getID())) != mRoundRobinQueue.end()) + return true; + return false; } @@ -796,12 +832,12 @@ void LLObjectMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr // First, call parent impl. LLMediaDataClient::removeFromQueue(object); - remove_matching_requests(mRoundRobinQueue, object->getID(), LLMediaDataClient::Request::ANY); + mark_dead_and_remove_if(mRoundRobinQueue, PredicateMatchRequest(object->getID())); } bool LLObjectMediaDataClient::processQueueTimer() { - if(isEmpty()) + if (isDoneProcessing()) return true; LL_DEBUGS("LLMediaDataClient") << "started, SORTED queue size is: " << mQueue.size() @@ -816,6 +852,7 @@ bool LLObjectMediaDataClient::processQueueTimer() LL_DEBUGS("LLMediaDataClientQueue") << "after sort, SORTED queue is: " << mQueue << LL_ENDL; serviceQueue(); + serviceHttp(); swapCurrentQueue(); @@ -824,7 +861,7 @@ bool LLObjectMediaDataClient::processQueueTimer() LL_DEBUGS("LLMediaDataClientQueue") << " SORTED queue is: " << mQueue << LL_ENDL; LL_DEBUGS("LLMediaDataClientQueue") << " RR queue is: " << mRoundRobinQueue << LL_ENDL; - return isEmpty(); + return isDoneProcessing(); } LLObjectMediaDataClient::RequestGet::RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc): @@ -841,16 +878,16 @@ LLSD LLObjectMediaDataClient::RequestGet::getPayload() const return result; } -LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestGet::createResponder() +LLHttpSDHandler *LLObjectMediaDataClient::RequestGet::createHandler() { - return new LLObjectMediaDataClient::Responder(this); + return new LLObjectMediaDataClient::Handler(shared_from_this()); } void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object) { // Create an update request and put it in the queue. - enqueue(new RequestUpdate(object, this)); + enqueue(Request::ptr_t(new RequestUpdate(object, this))); } LLObjectMediaDataClient::RequestUpdate::RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc): @@ -877,60 +914,58 @@ LLSD LLObjectMediaDataClient::RequestUpdate::getPayload() const return result; } -LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestUpdate::createResponder() +LLHttpSDHandler *LLObjectMediaDataClient::RequestUpdate::createHandler() { // This just uses the base class's responder. - return new LLMediaDataClient::Responder(this); + return new LLMediaDataClient::Handler(shared_from_this()); } - -/*virtual*/ -void LLObjectMediaDataClient::Responder::httpSuccess() +void LLObjectMediaDataClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { - getRequest()->stopTracking(); + LLMediaDataClient::Handler::onSuccess(response, content); + + if (getRequest()->isDead()) + { // warning emitted from base method. + return; + } + + if (!content.isMap()) + { + onFailure(response, LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Malformed response contents")); + return; + } + + // This responder is only used for GET requests, not UPDATE. + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << LL_ENDL; + + // Look for an error + if (content.has("error")) + { + const LLSD &error = content["error"]; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << + error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; + + // XXX Warn user? + } + else + { + // Check the data + const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY]; + if (object_id != getRequest()->getObject()->getID()) + { + // NOT good, wrong object id!! + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; + return; + } + + // Otherwise, update with object media data + getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY], + content[LLTextureEntry::MEDIA_VERSION_KEY]); + } - if(getRequest()->isDead()) - { - LL_WARNS("LLMediaDataClient") << "dead request " << *(getRequest()) << LL_ENDL; - return; - } - - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - - // This responder is only used for GET requests, not UPDATE. - LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL; - - // Look for an error - if (content.has("error")) - { - const LLSD &error = content["error"]; - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << - error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; - - // XXX Warn user? - } - else - { - // Check the data - const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY]; - if (object_id != getRequest()->getObject()->getID()) - { - // NOT good, wrong object id!! - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL; - return; - } - - // Otherwise, update with object media data - getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY], - content[LLTextureEntry::MEDIA_VERSION_KEY]); - } } + ////////////////////////////////////////////////////////////////////////////////////// // // LLObjectMediaNavigateClient @@ -943,16 +978,18 @@ const char *LLObjectMediaNavigateClient::getCapabilityName() const return "ObjectMediaNavigate"; } -void LLObjectMediaNavigateClient::enqueue(Request *request) +void LLObjectMediaNavigateClient::enqueue(Request::ptr_t request) { if(request->isDead()) { - LL_DEBUGS("LLMediaDataClient") << "not queueing dead request " << *request << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "not queuing dead request " << *request << LL_ENDL; return; } + PredicateMatchRequest upred(request); + // If there's already a matching request in the queue, remove it. - request_queue_t::iterator iter = find_matching_request(mQueue, request, LLMediaDataClient::Request::ANY); + request_queue_t::iterator iter = std::find_if(mQueue.begin(), mQueue.end(), upred); if(iter != mQueue.end()) { LL_DEBUGS("LLMediaDataClient") << "removing matching queued request " << (**iter) << LL_ENDL; @@ -960,7 +997,7 @@ void LLObjectMediaNavigateClient::enqueue(Request *request) } else { - request_set_t::iterator set_iter = find_matching_request(mUnQueuedRequests, request, LLMediaDataClient::Request::ANY); + request_set_t::iterator set_iter = std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred); if(set_iter != mUnQueuedRequests.end()) { LL_DEBUGS("LLMediaDataClient") << "removing matching unqueued request " << (**set_iter) << LL_ENDL; @@ -979,7 +1016,7 @@ void LLObjectMediaNavigateClient::enqueue(Request *request) else #endif { - LL_DEBUGS("LLMediaDataClient") << "queueing new request " << (*request) << LL_ENDL; + LL_DEBUGS("LLMediaDataClient") << "queuing new request " << (*request) << LL_ENDL; mQueue.push_back(request); // Start the timer if not already running @@ -993,7 +1030,7 @@ void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 t // LL_INFOS("LLMediaDataClient") << "navigate() initiated: " << ll_print_sd(sd_payload) << LL_ENDL; // Create a get request and put it in the queue. - enqueue(new RequestNavigate(object, this, texture_index, url)); + enqueue(Request::ptr_t(new RequestNavigate(object, this, texture_index, url))); } LLObjectMediaNavigateClient::RequestNavigate::RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url): @@ -1012,75 +1049,67 @@ LLSD LLObjectMediaNavigateClient::RequestNavigate::getPayload() const return result; } -LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::createResponder() +LLHttpSDHandler *LLObjectMediaNavigateClient::RequestNavigate::createHandler() { - return new LLObjectMediaNavigateClient::Responder(this); + return new LLObjectMediaNavigateClient::Handler(shared_from_this()); } -/*virtual*/ -void LLObjectMediaNavigateClient::Responder::httpFailure() +void LLObjectMediaNavigateClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { - getRequest()->stopTracking(); + LLMediaDataClient::Handler::onSuccess(response, content); - if(getRequest()->isDead()) - { - LL_WARNS("LLMediaDataClient") << "dead request " << *(getRequest()) << LL_ENDL; - return; - } + if (getRequest()->isDead()) + { // already warned. + return; + } + + LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned" << LL_ENDL; + + if (content.has("error")) + { + const LLSD &error = content["error"]; + int error_code = error["code"]; + + if (ERROR_PERMISSION_DENIED_CODE == error_code) + { + mediaNavigateBounceBack(); + } + else + { + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << + error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; + } + + // XXX Warn user? + } + else + { + // No action required. + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << LL_ENDL; + } - // Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base - // class - if (getStatus() == HTTP_SERVICE_UNAVAILABLE) - { - LLMediaDataClient::Responder::httpFailure(); - } - else - { - // bounce the face back - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: " << dumpResponse() << LL_ENDL; - const LLSD &payload = getRequest()->getPayload(); - // bounce the face back - getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); - } } -/*virtual*/ -void LLObjectMediaNavigateClient::Responder::httpSuccess() +void LLObjectMediaNavigateClient::Handler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) { - getRequest()->stopTracking(); + LLMediaDataClient::Handler::onFailure(response, status); - if(getRequest()->isDead()) - { - LL_WARNS("LLMediaDataClient") << "dead request " << *(getRequest()) << LL_ENDL; - return; - } + if (getRequest()->isDead()) + { // already warned. + return; + } - LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << dumpResponse() << LL_ENDL; - - const LLSD& content = getContent(); - if (content.has("error")) - { - const LLSD &error = content["error"]; - int error_code = error["code"]; - - if (ERROR_PERMISSION_DENIED_CODE == error_code) - { - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL; - const LLSD &payload = getRequest()->getPayload(); - // bounce the face back - getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); - } - else - { - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << - error["code"].asString() << ": " << error["message"].asString() << LL_ENDL; - } + if (status != LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE)) + { + mediaNavigateBounceBack(); + } +} - // XXX Warn user? - } - else - { - // No action required. - LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL; - } +void LLObjectMediaNavigateClient::Handler::mediaNavigateBounceBack() +{ + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating or denied." << LL_ENDL; + const LLSD &payload = getRequest()->getPayload(); + + // bounce the face back + getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); } |