Adding new HTTP handling for material manager.

meow-7.2.2
Rider Linden 2015-03-19 17:01:21 -07:00
parent 6f4d36634e
commit 6b8c814df3
14 changed files with 317 additions and 154 deletions

View File

@ -131,6 +131,7 @@ protected:
container_t mBlocks;
size_t mLen;
}; // end class BufferArray

View File

@ -105,7 +105,7 @@ void HttpHeaders::appendNormal(const char * header, size_t size)
// Find from end to simulate a tradition of using single-valued
// std::map for this in the past.
const std::string * HttpHeaders::find(const char * name) const
const std::string * HttpHeaders::find(const std::string &name) const
{
const_reverse_iterator iend(rend());
for (const_reverse_iterator iter(rbegin()); iend != iter; ++iter)

View File

@ -146,8 +146,12 @@ public:
// a pointer to a std::string in the container.
// Pointer is valid only for the lifetime of
// the container or until container is modifed.
//
const std::string * find(const char * name) const;
const std::string * find(const std::string &name) const;
const std::string * find(const char * name) const
{
return find(std::string(name));
}
// Count of headers currently in the list.
size_type size() const

View File

@ -89,5 +89,9 @@ void HttpResponse::setHeaders(HttpHeaders * headers)
mHeaders = headers;
}
size_t HttpResponse::getBodySize() const
{
return (mBufferArray) ? mBufferArray->size() : 0;
}
} // end namespace LLCore

View File

@ -104,6 +104,10 @@ public:
return mBufferArray;
}
/// Safely get the size of the body buffer. If the body buffer is missing
/// return 0 as the size.
size_t getBodySize() const;
/// Set the response data in the instance. Will drop the reference
/// count to any existing data and increment the count of that passed
/// in. It is legal to set the data to NULL.

View File

@ -49,6 +49,7 @@ set(llmessage_SOURCE_FILES
llhttpclientadapter.cpp
llhttpconstants.cpp
llhttpnode.cpp
llhttpsdhandler.cpp
llhttpsender.cpp
llinstantmessage.cpp
lliobuffer.cpp
@ -144,6 +145,7 @@ set(llmessage_HEADER_FILES
llhttpconstants.h
llhttpnode.h
llhttpnodeadapter.h
llhttpsdhandler.h
llhttpsender.h
llinstantmessage.h
llinvite.h

View File

@ -88,6 +88,32 @@ HttpHandle requestPostWithLLSD(HttpRequest * request,
return handle;
}
HttpHandle requestPutWithLLSD(HttpRequest * request,
HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
HttpOptions * options,
HttpHeaders * headers,
HttpHandler * handler)
{
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
BufferArray * ba = new BufferArray();
BufferArrayStream bas(ba);
LLSDSerialize::toXML(body, bas);
handle = request->requestPut(policy_id,
priority,
url,
ba,
options,
headers,
handler);
ba->release();
return handle;
}
std::string responseToString(LLCore::HttpResponse * response)
{

View File

@ -109,6 +109,31 @@ LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpHeaders * headers,
LLCore::HttpHandler * handler);
/// Issue a standard HttpRequest::requestPut() call but using
/// and LLSD object as the request body. Conventions are the
/// same as with that method. Caller is expected to provide
/// an HttpHeaders object with a correct 'Content-Type:' header.
/// One will not be provided by this call.
///
/// @return If request is successfully issued, the
/// HttpHandle representing the request.
/// On error, LLCORE_HTTP_HANDLE_INVALID
/// is returned and caller can fetch detailed
/// status with the getStatus() method on the
/// request object. In case of error, no
/// request is queued and caller may need to
/// perform additional cleanup such as freeing
/// a now-useless HttpHandler object.
///
LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpRequest::policy_t policy_id,
LLCore::HttpRequest::priority_t priority,
const std::string & url,
const LLSD & body,
LLCore::HttpOptions * options,
LLCore::HttpHeaders * headers,
LLCore::HttpHandler * handler);
} // end namespace LLCoreHttpUtil

View File

@ -309,7 +309,6 @@ private:
static void deleteAllFreeHandles();
};
#if 1
class LLCurl::Multi
{
LOG_CLASS(Multi);
@ -380,7 +379,6 @@ private:
LLFrameTimer mIdleTimer ;
F32 mIdleTimeOut;
};
#endif
class LLCurlThread : public LLQueuedThread
{
@ -419,103 +417,6 @@ private:
void cleanupMulti(LLCurl::Multi* multi) ;
} ;
#if 0
class LLCurlRequest
{
public:
typedef std::vector<std::string> headers_t;
LLCurlRequest();
~LLCurlRequest();
void get(const std::string& url, LLCurl::ResponderPtr responder);
bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
S32 process();
S32 getQueued();
private:
void addMulti();
LLCurl::Easy* allocEasy();
bool addEasy(LLCurl::Easy* easy);
private:
typedef std::set<LLCurl::Multi*> curlmulti_set_t;
curlmulti_set_t mMultiSet;
LLCurl::Multi* mActiveMulti;
S32 mActiveRequestCount;
BOOL mProcessing;
};
#endif
#if 0
//for texture fetch only
class LLCurlTextureRequest : public LLCurlRequest
{
public:
LLCurlTextureRequest(S32 concurrency);
~LLCurlTextureRequest();
U32 getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder, F32 delay_time = -1.f);
void nextRequests();
void completeRequest(S32 received_bytes);
void updatePriority(U32 handle, U32 pri);
void removeRequest(U32 handle);
U32 getTotalReceivedBits();
U32 getTotalIssuedRequests();
S32 getNumRequests();
bool isWaiting(U32 handle);
private:
LLMutex mMutex;
S32 mConcurrency;
S32 mInQueue; //request currently in queue.
U32 mHandleCounter;
U32 mTotalIssuedRequests;
U32 mTotalReceivedBits;
typedef struct _request_t
{
_request_t(U32 handle, const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder) :
mHandle(handle), mUrl(url), mHeaders(headers), mOffset(offset), mLength(length), mPriority(pri), mResponder(responder), mStartTime(0.f)
{}
U32 mHandle;
std::string mUrl;
LLCurlRequest::headers_t mHeaders;
S32 mOffset;
S32 mLength;
LLCurl::ResponderPtr mResponder;
U32 mPriority;
F32 mStartTime; //start time to issue this request
} request_t;
struct request_compare
{
bool operator()(const request_t* lhs, const request_t* rhs) const
{
if(lhs->mPriority != rhs->mPriority)
{
return lhs->mPriority > rhs->mPriority; // higher priority in front of queue (set)
}
else
{
return (U32)lhs < (U32)rhs;
}
}
};
typedef std::set<request_t*, request_compare> req_queue_t;
req_queue_t mCachedRequests;
std::map<S32, request_t*> mRequestMap;
LLFrameTimer mGlobalTimer;
};
#endif
class LLCurlEasyRequest
{

View File

@ -0,0 +1,82 @@
/**
* @file llhttpsdhandler.h
* @brief Public-facing declarations for the HttpHandler class
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llhttpconstants.h"
#include "llhttpsdhandler.h"
#include "httpresponse.h"
#include "httpheaders.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "bufferstream.h"
#include "llcorehttputil.h"
//========================================================================
LLHttpSDHandler::LLHttpSDHandler(const LLURI &uri):
mUri(uri)
{
}
void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
{
LLCore::HttpStatus status = response->getStatus();
if (!status)
{
this->onFailure(response, status);
}
else
{
LLSD resplsd;
const bool emit_parse_errors = false;
bool parsed = !((response->getBodySize() == 0) ||
!LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, resplsd));
if (!parsed)
{
// Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
{
std::string thebody = LLCoreHttpUtil::responseToString(response);
LL_WARNS() << "Failed to deserialize . " << getUri() << " [status:" << response->getStatus().toString() << "] "
<< " body: " << thebody << LL_ENDL;
}
}
this->onSuccess(response, resplsd);
}
// The handler must destroy itself when it is done.
delete this;
}

View File

@ -0,0 +1,56 @@
/**
* @file llhttpsdhandler.h
* @brief Public-facing declarations for the HttpHandler class
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef _LLHTTPSDHANDLER_H_
#define _LLHTTPSDHANDLER_H_
#include "httpcommon.h"
#include "httphandler.h"
#include "lluri.h"
///
///
class LLHttpSDHandler : public LLCore::HttpHandler
{
public:
LLHttpSDHandler(const LLURI &uri);
virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
inline const LLURI &getUri() const
{
return mUri;
}
protected:
virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content) = 0;
virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0;
private:
LLURI mUri;
};
#endif

View File

@ -36,6 +36,10 @@
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llworld.h"
#include "llhttpsdhandler.h"
#include "httpcommon.h"
#include "httpheaders.h"
#include "llcorehttputil.h"
/**
* Materials cap parameters
@ -59,56 +63,51 @@
#define MATERIALS_PUT_THROTTLE_SECS 1.f
#define MATERIALS_PUT_MAX_ENTRIES 50
/**
* LLMaterialsResponder helper class
*/
class LLMaterialsResponder : public LLHTTPClient::Responder
class LLMaterialHttpHandler : public LLHttpSDHandler
{
public:
typedef boost::function<void (bool, const LLSD&)> CallbackFunction;
public:
typedef boost::function<void(bool, const LLSD&)> CallbackFunction;
typedef boost::shared_ptr<LLMaterialHttpHandler> ptr_t;
LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
virtual ~LLMaterialsResponder();
LLMaterialHttpHandler(const std::string& method, const std::string& capabilityURL, CallbackFunction cback);
virtual void httpSuccess();
virtual void httpFailure();
virtual ~LLMaterialHttpHandler();
protected:
virtual void onSuccess(LLCore::HttpResponse * response, LLSD &content);
virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
private:
std::string mMethod;
std::string mCapabilityURL;
CallbackFunction mCallback;
};
LLMaterialsResponder::LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback)
: LLHTTPClient::Responder()
, mMethod(pMethod)
, mCapabilityURL(pCapabilityURL)
, mCallback(pCallback)
LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, const std::string& capabilityURL, CallbackFunction cback):
LLHttpSDHandler(capabilityURL),
mMethod(method),
mCallback(cback)
{
}
LLMaterialHttpHandler::~LLMaterialHttpHandler()
{
}
LLMaterialsResponder::~LLMaterialsResponder()
void LLMaterialHttpHandler::onSuccess(LLCore::HttpResponse * response, LLSD &content)
{
}
void LLMaterialsResponder::httpSuccess()
{
const LLSD& pContent = getContent();
LL_DEBUGS("Materials") << LL_ENDL;
mCallback(true, pContent);
mCallback(true, content);
}
void LLMaterialsResponder::httpFailure()
void LLMaterialHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
{
U32 pStatus = (U32) getStatus();
const std::string& pReason = getReason();
LL_WARNS("Materials")
<< "\n--------------------------------------------------------------------------\n"
<< mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
<< "'\n with url '" << mCapabilityURL << "' because " << pReason
<< mMethod << " Error[" << status.toULong() << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
<< "'\n with url '" << getUri() << "' because " << status.toString()
<< "\n--------------------------------------------------------------------------"
<< LL_ENDL;
@ -116,12 +115,16 @@ void LLMaterialsResponder::httpFailure()
mCallback(false, emptyResult);
}
/**
* LLMaterialMgr class
*/
LLMaterialMgr::LLMaterialMgr()
{
mRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(LLMaterialID::null, LLMaterialPtr(NULL)));
gIdleCallbacks.addFunction(&LLMaterialMgr::onIdle, NULL);
LLWorld::instance().setRegionRemovedCallback(boost::bind(&LLMaterialMgr::onRegionRemoved, this, _1));
@ -554,6 +557,8 @@ void LLMaterialMgr::onIdle(void*)
{
instancep->processPutQueue();
}
instancep->mRequest->update(0L);
}
void LLMaterialMgr::processGetQueue()
@ -629,10 +634,28 @@ void LLMaterialMgr::processGetQueue()
LLSD postData = LLSD::emptyMap();
postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("POST", capURL, boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id));
LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials."
LLMaterialHttpHandler * handler =
new LLMaterialHttpHandler("POST", capURL,
boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)
);
LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials."
<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
LLHTTPClient::post(capURL, postData, materialsResponder);
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD(mRequest.get(),
LLCore::HttpRequest::DEFAULT_POLICY_ID, 0, capURL,
postData, NULL, headers.get(), handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
delete handler;
LLCore::HttpStatus status = mRequest->getStatus();
LL_ERRS("Meterials") << "Failed to execute material POST. Status = " <<
status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
}
regionp->resetMaterialsCapThrottle();
}
}
@ -667,8 +690,24 @@ void LLMaterialMgr::processGetAllQueue()
}
LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL;
LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("GET", capURL, boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion));
LLHTTPClient::get(capURL, materialsResponder);
LLMaterialHttpHandler *handler =
new LLMaterialHttpHandler("GET", capURL,
boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)
);
LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
LLCore::HttpHandle handle = mRequest->requestGet(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
capURL, NULL, headers.get(), handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
delete handler;
LLCore::HttpStatus status = mRequest->getStatus();
LL_ERRS("Meterials") << "Failed to execute material GET. Status = " <<
status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
}
regionp->resetMaterialsCapThrottle();
mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds()));
mGetAllQueue.erase(itRegion); // Invalidates region_id
@ -755,8 +794,25 @@ void LLMaterialMgr::processPutQueue()
putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL;
LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2));
LLHTTPClient::put(capURL, putData, materialsResponder);
LLMaterialHttpHandler * handler =
new LLMaterialHttpHandler("PUT", capURL,
boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)
);
LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD(mRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
capURL, putData, NULL, headers.get(), handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
delete handler;
LLCore::HttpStatus status = mRequest->getStatus();
LL_ERRS("Meterials") << "Failed to execute material PUT. Status = " <<
status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
}
regionp->resetMaterialsCapThrottle();
}
else

View File

@ -30,6 +30,7 @@
#include "llmaterial.h"
#include "llmaterialid.h"
#include "llsingleton.h"
#include "httprequest.h"
class LLViewerRegion;
@ -56,7 +57,7 @@ public:
void put(const LLUUID& object_id, const U8 te, const LLMaterial& material);
void remove(const LLUUID& object_id, const U8 te);
protected:
private:
void clearGetQueues(const LLUUID& region_id);
bool isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const;
bool isGetAllPending(const LLUUID& region_id) const;
@ -72,14 +73,15 @@ protected:
void onPutResponse(bool success, const LLSD& content);
void onRegionRemoved(LLViewerRegion* regionp);
protected:
private:
typedef std::set<LLMaterialID> material_queue_t;
typedef std::map<LLUUID, material_queue_t> get_queue_t;
get_queue_t mGetQueue;
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
typedef std::map<const pending_material_t, F64> get_pending_map_t;
get_pending_map_t mGetPending;
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
get_queue_t mGetQueue;
get_pending_map_t mGetPending;
get_callback_map_t mGetCallbacks;
// struct for TE-specific material ID query
@ -109,22 +111,22 @@ protected:
};
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
get_callback_te_map_t mGetTECallbacks;
typedef std::set<LLUUID> getall_queue_t;
getall_queue_t mGetAllQueue;
getall_queue_t mGetAllRequested;
typedef std::map<LLUUID, F64> getall_pending_map_t;
getall_pending_map_t mGetAllPending;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
getall_callback_map_t mGetAllCallbacks;
typedef std::map<U8, LLMaterial> facematerial_map_t;
typedef std::map<LLUUID, facematerial_map_t> put_queue_t;
put_queue_t mPutQueue;
get_callback_te_map_t mGetTECallbacks;
getall_queue_t mGetAllQueue;
getall_queue_t mGetAllRequested;
getall_pending_map_t mGetAllPending;
getall_callback_map_t mGetAllCallbacks;
put_queue_t mPutQueue;
material_map_t mMaterials;
LLCore::HttpRequest::ptr_t mRequest;
U32 getMaxEntries(const LLViewerRegion* regionp);
};

View File

@ -312,7 +312,6 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
: mHttpRequest(0),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
// mRequestText(0),
mResponse(0)
{
init(request, useGzip);
@ -324,7 +323,6 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
: mHttpRequest(0),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
// mRequestText(0),
mResponse(0)
{
XMLRPC_REQUEST request = XMLRPC_RequestNew();
@ -485,12 +483,14 @@ void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status)
CURLcode code = static_cast<CURLcode>(status.toULong());
std::string message;
std::string uri = "http://secondlife.com/community/support.php";
LLURI failuri(mURI);
switch (code)
{
case CURLE_COULDNT_RESOLVE_HOST:
message =
"DNS could not resolve the host name.\n"
std::string("DNS could not resolve the host name(") + failuri.hostName() + ").\n"
"Please verify that you can connect to the www.secondlife.com\n"
"web site. If you can, but continue to receive this error,\n"
"please go to the support section and report this problem.";