12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541 |
- /**
- * @file llcorehttputil.cpp
- * @date 2014-08-25
- * @brief Implementation of adapter and utility classes expanding the llcorehttp interfaces.
- *
- * $LicenseInfo:firstyear=2014&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2014, 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 <algorithm>
- #include <iterator>
- #include <sstream>
- #include "llcorehttputil.h"
- #include "llfilesystem.h"
- #include "llhttpconstants.h"
- #include "llsdjson.h"
- #include "llsdserialize.h"
- #include "llmessage.h" // For getting the port
- using namespace LLCore;
- namespace LLCoreHttpUtil
- {
- void logMessageSuccess(const std::string& log_auth, const std::string& url,
- const std::string& message)
- {
- llinfos << log_auth << ": Success '" << message << "' for: " << url
- << llendl;
- }
- void logMessageFail(const std::string& log_auth, const std::string& url,
- const std::string& message)
- {
- llwarns << log_auth << ": Failure '" << message << "' for: " << url
- << llendl;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HttpRequestPumper class
- ///////////////////////////////////////////////////////////////////////////////
- // The HttpRequestPumper is a utility class. When constructed it will poll the
- // supplied HttpRequest once per frame until it is destroyed.
- class HttpRequestPumper
- {
- public:
- HttpRequestPumper(const LLCore::HttpRequest::ptr_t& request);
- ~HttpRequestPumper();
- private:
- bool pollRequest();
- private:
- LLBoundListener mBoundListener;
- LLCore::HttpRequest::ptr_t mHttpRequest;
- };
- HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t& request)
- : mHttpRequest(request)
- {
- LLEventPump& pump = gEventPumps.obtain("mainloop");
- mBoundListener = pump.listen(LLEventPump::ANONYMOUS,
- boost::bind(&HttpRequestPumper::pollRequest,
- this));
- }
- HttpRequestPumper::~HttpRequestPumper()
- {
- if (mBoundListener.connected())
- {
- mBoundListener.disconnect();
- }
- }
- bool HttpRequestPumper::pollRequest()
- {
- if (mHttpRequest && !mHttpRequest->isCancelled() &&
- mHttpRequest->getStatus() != gStatusCancelled)
- {
- mHttpRequest->update(0L);
- }
- // No point to keep pumping once the request is cancelled or destroyed...
- else if (mBoundListener.connected())
- {
- mBoundListener.disconnect();
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // *TODO: Currently converts only from XML content. A mode to convert using
- // fromBinary() might be useful as well. Mesh headers could use it.
- bool responseToLLSD(HttpResponse* response, bool log, LLSD& out_llsd)
- {
- // Convert response to LLSD
- BufferArray* body = response ? response->getBody() : NULL;
- if (!body || !body->size())
- {
- return false;
- }
- LLCore::BufferArrayStream bas(body);
- LLSD body_llsd;
- S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log));
- if (LLSDParser::PARSE_FAILURE == parse_status)
- {
- return false;
- }
- out_llsd = body_llsd;
- return true;
- }
- HttpHandle requestPostWithLLSD(HttpRequest* request,
- HttpRequest::policy_t policy_id,
- const std::string& url, const LLSD& body,
- const HttpOptions::ptr_t& options,
- const HttpHeaders::ptr_t& headers,
- const HttpHandler::ptr_t& handler)
- {
- HttpHandle handle = LLCORE_HTTP_HANDLE_INVALID;
- if (!request) return handle;
- BufferArray* ba = new BufferArray();
- BufferArrayStream bas(ba);
- LLSDSerialize::toXML(body, bas);
- handle = request->requestPost(policy_id, url, ba, options, headers,
- handler);
- ba->release();
- return handle;
- }
- HttpHandle requestPutWithLLSD(HttpRequest* request,
- HttpRequest::policy_t policy_id,
- const std::string& url, const LLSD& body,
- const HttpOptions::ptr_t& options,
- const HttpHeaders::ptr_t& headers,
- const HttpHandler::ptr_t& handler)
- {
- HttpHandle handle = LLCORE_HTTP_HANDLE_INVALID;
- if (!request) return handle;
- BufferArray* ba = new BufferArray();
- BufferArrayStream bas(ba);
- LLSDSerialize::toXML(body, bas);
- handle = request->requestPut(policy_id, url, ba, options, headers,
- handler);
- ba->release();
- return handle;
- }
- HttpHandle requestPatchWithLLSD(HttpRequest* request,
- HttpRequest::policy_t policy_id,
- const std::string& url, const LLSD& body,
- const HttpOptions::ptr_t& options,
- const HttpHeaders::ptr_t& headers,
- const HttpHandler::ptr_t& handler)
- {
- HttpHandle handle = LLCORE_HTTP_HANDLE_INVALID;
- if (!request) return handle;
- BufferArray* ba = new BufferArray();
- BufferArrayStream bas(ba);
- LLSDSerialize::toXML(body, bas);
- handle = request->requestPatch(policy_id, url, ba, options, headers,
- handler);
- ba->release();
- return handle;
- }
- std::string responseToString(LLCore::HttpResponse* response)
- {
- static const std::string empty = "[Empty]";
- if (!response)
- {
- return empty;
- }
- BufferArray* body = response->getBody();
- if (!body || !body->size())
- {
- return empty;
- }
- // Attempt to parse as LLSD regardless of content-type
- LLSD body_llsd;
- if (responseToLLSD(response, false, body_llsd))
- {
- std::ostringstream tmp;
- LLSDSerialize::toPrettyNotation(body_llsd, tmp);
- size_t temp_len = tmp.tellp();
- if (temp_len)
- {
- return tmp.str().substr(0, llmin(temp_len, (size_t)1024));
- }
- }
- else
- {
- // *TODO: More elaborate forms based on Content-Type as needed.
- char content[1024];
- size_t len = body->read(0, content, sizeof(content));
- if (len)
- {
- return std::string(content, 0, len);
- }
- }
- // Default
- return empty;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroHandler class
- ///////////////////////////////////////////////////////////////////////////////
- HttpCoroHandler::HttpCoroHandler(LLEventStream& reply)
- : mReplyPump(reply)
- {
- }
- void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle,
- LLCore::HttpResponse* response)
- {
- if (!response)
- {
- llwarns << "NULL response pointer passed !" << llendl;
- return;
- }
- static const LLCore::HttpStatus bad_handle(LLCore::HttpStatus::LLCORE,
- LLCore::HE_HANDLE_NOT_FOUND);
- LLCore::HttpStatus status = response->getStatus();
- if (status == bad_handle)
- {
- // A response came in for a cancelled request and we have not processed
- // the cancel yet. Patience !
- return;
- }
- LLSD result;
- if (!status)
- {
- bool parse_success = false;
- result = LLSD::emptyMap();
- LLCore::HttpStatus::type_enum_t error = status.getType();
- LL_DEBUGS("CoreHttp") << "Error " << status.toTerseString()
- << " - Cannot access url: "
- << response->getRequestURL()
- << " - Reason: " << status.toString() << LL_ENDL;
- if (error >= 400 && error < 500)
- {
- LLSD body = parseBody(response, parse_success);
- if (!body.isUndefined())
- {
- if (!body.isMap())
- {
- result[HttpCoroutineAdapter::HTTP_RESULTS_CONTENT] = body;
- }
- else
- {
- result = body;
- }
- }
- }
- }
- else
- {
- result = handleSuccess(response, status);
- }
- buildStatusEntry(response, status, result);
- if (!status)
- {
- LLSD& status_llsd = result[HttpCoroutineAdapter::HTTP_RESULTS];
- bool parse_success = false;
- LLSD error_body = parseBody(response, parse_success);
- if (parse_success)
- {
- status_llsd["error_body"] = error_body;
- LL_DEBUGS("CoreHttp") << "Returned body:\n";
- std::stringstream str;
- LLSDSerialize::toPrettyXML(error_body, str);
- LL_CONT << str.str() << LL_ENDL;
- }
- else
- {
- LLCore::BufferArray* body = response->getBody();
- LLCore::BufferArrayStream bas(body);
- LLSD::String bodydata;
- bodydata.reserve(response->getBodySize());
- bas >> std::noskipws;
- bodydata.assign(std::istream_iterator<U8>(bas),
- std::istream_iterator<U8>());
- status_llsd["error_body"] = LLSD(bodydata);
- LL_DEBUGS("CoreHttp") << "Returned body:" << std::endl
- << status_llsd["error_body"].asString()
- << LL_ENDL;
- }
- }
- mReplyPump.post(result);
- }
- void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse* response,
- LLCore::HttpStatus status, LLSD& result)
- {
- if (!response)
- {
- llwarns << "NULL response pointer passed !" << llendl;
- return;
- }
- LLSD httpresults = LLSD::emptyMap();
- writeStatusCodes(status, response->getRequestURL(), httpresults);
- LLSD httpheaders = LLSD::emptyMap();
- LLCore::HttpHeaders::ptr_t hdrs = response->getHeaders();
- if (hdrs)
- {
- for (LLCore::HttpHeaders::iterator it = hdrs->begin(),
- end = hdrs->end();
- it != end; ++it)
- {
- if (!it->second.empty())
- {
- httpheaders[it->first] = it->second;
- }
- else
- {
- httpheaders[it->first] = LLSD::Boolean(true);
- }
- }
- }
- httpresults[HttpCoroutineAdapter::HTTP_RESULTS_HEADERS] = httpheaders;
- result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults;
- }
- void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status,
- const std::string& url, LLSD& result)
- {
- result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = LLSD::Boolean(status);
- result[HttpCoroutineAdapter::HTTP_RESULTS_TYPE] = LLSD::Integer(status.getType());
- result[HttpCoroutineAdapter::HTTP_RESULTS_STATUS] = LLSD::Integer(status.getStatus());
- result[HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE] = LLSD::String(status.getMessage());
- result[HttpCoroutineAdapter::HTTP_RESULTS_URL] = LLSD::String(url);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroLLSDHandler class
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroLLSDHandler is a specialization of the LLCore::HttpHandler for
- // interacting with coroutines. When the request is completed the response will
- // be posted onto the supplied Event Pump.
- //
- // If the LLSD retrieved from through the HTTP connection is not in the form of
- // a LLSD::map it will be returned as in an llsd["content"] element.
- //
- // The LLSD posted back to the coroutine will have the following additions:
- // llsd["http_result"] -+- ["message"] An error message returned from the HTTP
- // status.
- // +- ["status"] The status code associated with the
- // HTTP call.
- // +- ["success"] Success of failure of the HTTP call and
- // LLSD parsing.
- // +- ["type"] The LLCore::HttpStatus type associted
- // with the HTTP call.
- // +- ["url"] The URL used to make the call.
- // +- ["headers"] A map of name name value pairs with the
- // HTTP headers.
- class HttpCoroLLSDHandler final : public HttpCoroHandler
- {
- public:
- HttpCoroLLSDHandler(LLEventStream& reply)
- : HttpCoroHandler(reply)
- {
- }
- protected:
- LLSD handleSuccess(LLCore::HttpResponse* response,
- LLCore::HttpStatus& status) override;
- LLSD parseBody(LLCore::HttpResponse* response, bool& success) override;
- };
- LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse* response,
- LLCore::HttpStatus& status)
- {
- LLSD result;
- if (!response)
- {
- llwarns << "NULL response pointer passed !" << llendl;
- return result;
- }
- bool success = false;
- result = parseBody(response, success);
- if (!success)
- {
- // 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* content_type =
- headers ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
- if (content_type && *content_type == HTTP_CONTENT_LLSD_XML)
- {
- std::string thebody = LLCoreHttpUtil::responseToString(response);
- llwarns << "Failed to deserialize: " << response->getRequestURL()
- << " - Status: " << response->getStatus().toString()
- << " - Body: " << thebody << llendl;
- // Replace the status with a new one indicating the failure.
- status = LLCore::HttpStatus(499, "Failed to deserialize LLSD.");
- }
- // If we have gotten to this point and the result LLSD is still
- // undefined either there was an issue deserializing the body or the
- // response was blank. Create an empty map to hold the result either
- // way.
- result = LLSD::emptyMap();
- }
- else if (!result.isMap() && result.isDefined())
- {
- // The results are not themselves a map. Move them down so that this
- // method can return a map to the caller.
- // *TODO: Should it always do this ?
- // HB: probably not... It causes issues with callbacks expecting either
- // a map or an empty LLSD (e.g. path finding routines). This is why I
- // added a result.isDefined() condition...
- LLSD new_result = LLSD::emptyMap();
- new_result[HttpCoroutineAdapter::HTTP_RESULTS_CONTENT] = result;
- result = new_result;
- }
- return result;
- }
- LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse* response,
- bool& success)
- {
- LLSD result;
- if (!response)
- {
- llwarns << "NULL response pointer passed !" << llendl;
- success = false;
- return result;
- }
- if (response->getBodySize() == 0 ||
- LLCoreHttpUtil::responseToLLSD(response, false, result))
- {
- success = true;
- return result;
- }
- success = false;
- return LLSD();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroRawHandler class
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroRawHandler is a specialization of the LLCore::HttpHandler for
- // interacting with coroutines.
- //
- // In addition to the normal "http_results" the returned LLSD will contain an
- // entry keyed with "raw" containing the unprocessed results of the HTTP call.
- class HttpCoroRawHandler final : public HttpCoroHandler
- {
- public:
- HttpCoroRawHandler(LLEventStream& reply)
- : HttpCoroHandler(reply)
- {
- }
- LLSD handleSuccess(LLCore::HttpResponse* response,
- LLCore::HttpStatus& status) override;
- LLSD parseBody(LLCore::HttpResponse* response, bool& success) override;
- };
- LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse* response,
- LLCore::HttpStatus& status)
- {
- LLSD result = LLSD::emptyMap();
- BufferArray* body = response ? response->getBody() : NULL;
- if (!body || !body->size())
- {
- return result;
- }
- size_t size = body->size();
- LLCore::BufferArrayStream bas(body);
- LLSD::Binary data;
- data.reserve(size);
- bas >> std::noskipws;
- data.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
- result[HttpCoroutineAdapter::HTTP_RESULTS_RAW] = data;
- return result;
- }
- LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse* response,
- bool& success)
- {
- success = true;
- return LLSD();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroJSONHandler class
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroJSONHandler is a specialization of the LLCore::HttpHandler for
- // interacting with coroutines.
- //
- // In addition to the normal "http_results" the returned LLSD will contain JSON
- // entries will be converted into an LLSD map. All results are considered
- // strings
- class HttpCoroJSONHandler final : public HttpCoroHandler
- {
- public:
- HttpCoroJSONHandler(LLEventStream& reply)
- : HttpCoroHandler(reply)
- {
- }
- LLSD handleSuccess(LLCore::HttpResponse* response,
- LLCore::HttpStatus& status) override;
- LLSD parseBody(LLCore::HttpResponse* response, bool& success) override;
- };
- LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse* response,
- LLCore::HttpStatus& status)
- {
- LLSD result = LLSD::emptyMap();
- BufferArray* body = response ? response->getBody() : NULL;
- if (!body || !body->size())
- {
- return result;
- }
- LLCore::BufferArrayStream bas(body);
- lljson jsonroot;
- try
- {
- bas >> jsonroot;
- }
- catch (std::runtime_error& e)
- {
- // Deserialization failed. Record the reason and pass back an empty map
- // for markup.
- status = LLCore::HttpStatus(499, std::string(e.what()));
- return result;
- }
- // Convert the JSON structure to LLSD
- result = llsd_from_json(jsonroot);
- return result;
- }
- LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse* response,
- bool& success)
- {
- success = true;
- BufferArray* body = response ? response->getBody() : NULL;
- if (!body || !body->size())
- {
- return LLSD();
- }
- LLCore::BufferArrayStream bas(body);
- lljson jsonroot;
- try
- {
- bas >> jsonroot;
- }
- catch (std::runtime_error& e)
- {
- success = false;
- return LLSD();
- }
- // Convert the JSON structure to LLSD
- return llsd_from_json(jsonroot);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // HttpCoroutineAdapter class
- ///////////////////////////////////////////////////////////////////////////////
- const std::string HttpCoroutineAdapter::HTTP_RESULTS("http_result");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS("success");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_TYPE("type");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_STATUS("status");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE("message");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_URL("url");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_HEADERS("headers");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content");
- const std::string HttpCoroutineAdapter::HTTP_RESULTS_RAW("raw");
- //static
- HttpCoroutineAdapter::instances_list_t HttpCoroutineAdapter::sInstances;
- HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string& name,
- LLCore::HttpRequest::ptr_t& request,
- LLCore::HttpRequest::policy_t polid)
- : mAdapterName(name),
- mPolicyId(polid),
- mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID),
- mRequest(request)
- {
- sInstances.insert(this);
- }
- HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string& name,
- LLCore::HttpRequest::policy_t polid)
- : mAdapterName(name),
- mPolicyId(polid),
- mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID),
- mRequest(DEFAULT_HTTP_REQUEST)
- {
- sInstances.insert(this);
- }
- HttpCoroutineAdapter::~HttpCoroutineAdapter()
- {
- sInstances.erase(this);
- cancelSuspendedOperation();
- }
- //static
- void HttpCoroutineAdapter::cleanup()
- {
- if (sInstances.empty())
- {
- return;
- }
- llinfos << "Cancelling suspended operations on remaining adapters..."
- << llendl;
- // Note: just in case calling cancelSuspendedOperation() on one adapter
- // instance would destroy another instance, we consider that sInstances
- // could get modified during the loop, and thus copy it beforehand and
- // check each time that the adapter still exists in sInstances before
- // attempting to cancel its operation...
- instances_list_t copy = sInstances;
- for (instances_list_t::const_iterator it = copy.begin(), end = copy.end();
- it != end; ++it)
- {
- HttpCoroutineAdapter* adapter = *it;
- if (sInstances.count(adapter))
- {
- adapter->cancelSuspendedOperation();
- }
- }
- }
- LLSD HttpCoroutineAdapter::postAndSuspend(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName, true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- return postAndSuspend_(url, body, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::postAndSuspend_(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = requestPostWithLLSD(mRequest, mPolicyId,
- url, body, options,
- headers, handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::postAndSuspend(const std::string& url,
- LLCore::BufferArray::ptr_t rawbody,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName, true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- return postAndSuspend_(url, rawbody, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::postRawAndSuspend(const std::string& url,
- LLCore::BufferArray::ptr_t rawbody,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName, true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroRawHandler>(reply_pump);
- return postAndSuspend_(url, rawbody, options, headers, http_handler);
- }
- // *TODO: This functionality could be moved into the LLCore::Http library
- // itself by having the CURL layer read the file directly.
- LLSD HttpCoroutineAdapter::postFileAndSuspend(const std::string& url,
- std::string filename,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLCore::BufferArray::ptr_t filedata(new LLCore::BufferArray);
- // Scoping for our streams so that they go away when we no longer need them
- {
- LLCore::BufferArrayStream outs(filedata.get());
- llifstream ins(filename.c_str(),
- std::iostream::binary | std::iostream::out);
- if (ins.is_open())
- {
- ins.seekg(0, std::ios::beg);
- ins >> std::noskipws;
- std::copy(std::istream_iterator<U8>(ins),
- std::istream_iterator<U8>(),
- std::ostream_iterator<U8>(outs));
- ins.close();
- }
- }
- return postAndSuspend(url, filedata, options, headers);
- }
- // *TODO: This functionality could be moved into the LLCore::Http library
- // itself by having the CURL layer read the file directly.
- LLSD HttpCoroutineAdapter::postFileAndSuspend(const std::string& url,
- const LLUUID& assetid,
- LLAssetType::EType assetType,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLCore::BufferArray::ptr_t filedata(new LLCore::BufferArray);
- // Scoping for our streams so that they go away when we no longer need them
- {
- LLCore::BufferArrayStream outs(filedata.get());
- LLFileSystem vfile(assetid);
- S32 file_size = vfile.getSize();
- U8* file_buffer = new U8[file_size];
- vfile.read(file_buffer, file_size);
- outs.write((char*)file_buffer, file_size);
- delete[] file_buffer;
- }
- return postAndSuspend(url, filedata, options, headers);
- }
- LLSD HttpCoroutineAdapter::postJsonAndSuspend(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName, true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroJSONHandler>(reply_pump);
- LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
- {
- LLCore::BufferArrayStream outs(rawbody.get());
- lljson root = llsd_to_json(body);
- LL_DEBUGS("CoreHttp") << "JSON Generates: " << root << LL_ENDL;
- outs << root;
- }
- return postAndSuspend_(url, rawbody, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::postAndSuspend_(const std::string& url,
- LLCore::BufferArray::ptr_t& rawbody,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = mRequest->requestPost(mPolicyId, url,
- rawbody.get(), options,
- headers, handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::putAndSuspend(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- return putAndSuspend_(url, body, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::putJsonAndSuspend(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName, true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroJSONHandler>(reply_pump);
- LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
- {
- LLCore::BufferArrayStream outs(rawbody.get());
- lljson root = llsd_to_json(body);
- LL_DEBUGS("CoreHttp") << "JSON Generates: " << root << LL_ENDL;
- outs << root;
- }
- return putAndSuspend_(url, rawbody, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::putAndSuspend_(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = requestPutWithLLSD(mRequest, mPolicyId, url,
- body, options, headers,
- handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::putAndSuspend_(const std::string& url,
- const LLCore::BufferArray::ptr_t& rawbody,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = mRequest->requestPut(mPolicyId, url,
- rawbody.get(), options,
- headers, handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::getAndSuspend(const std::string& url,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- return getAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::getRawAndSuspend(const std::string& url,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroRawHandler>(reply_pump);
- return getAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::getJsonAndSuspend(const std::string& url,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroJSONHandler>(reply_pump);
- return getAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::getAndSuspend_(const std::string& url,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = mRequest->requestGet(mPolicyId, url, options,
- headers, handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::deleteAndSuspend(const std::string& url,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- return deleteAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::deleteJsonAndSuspend(const std::string& url,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroJSONHandler>(reply_pump);
- return deleteAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::deleteAndSuspend_(const std::string& url,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = mRequest->requestDelete(mPolicyId, url,
- options, headers,
- handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::patchAndSuspend(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- return patchAndSuspend_(url, body, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::patchAndSuspend_(const std::string& url,
- const LLSD& body,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = requestPatchWithLLSD(mRequest, mPolicyId, url,
- body, options, headers,
- handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::copyAndSuspend(const std::string& url,
- const std::string dest,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- if (!headers)
- {
- headers.reset(new LLCore::HttpHeaders);
- }
- headers->append(HTTP_OUT_HEADER_DESTINATION, dest);
- return copyAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::copyAndSuspend_(const std::string& url,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = mRequest->requestCopy(mPolicyId, url, options,
- headers, handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- LLSD HttpCoroutineAdapter::moveAndSuspend(const std::string& url,
- const std::string dest,
- LLCore::HttpOptions::ptr_t options,
- LLCore::HttpHeaders::ptr_t headers)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLEventStream reply_pump(mAdapterName + "Reply", true);
- HttpCoroHandler::ptr_t http_handler =
- std::make_shared<HttpCoroLLSDHandler>(reply_pump);
- if (!headers)
- {
- headers.reset(new LLCore::HttpHeaders);
- }
- headers->append(HTTP_OUT_HEADER_DESTINATION, dest);
- return moveAndSuspend_(url, options, headers, http_handler);
- }
- LLSD HttpCoroutineAdapter::moveAndSuspend_(const std::string& url,
- LLCore::HttpOptions::ptr_t& options,
- LLCore::HttpHeaders::ptr_t& headers,
- HttpCoroHandler::ptr_t& handler)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- checkDefaultHeaders(headers);
- // The HTTPCoroHandler does not self delete, so retrieval of a the
- // contained pointer from the smart pointer is safe in this case.
- LLCore::HttpHandle hhandle = mRequest->requestMove(mPolicyId, url, options,
- headers, handler);
- if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
- {
- return buildImmediateErrorResult(url);
- }
- saveState(url, hhandle, handler);
- HttpRequestPumper pumper(mRequest);
- LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
- cleanState();
- return results;
- }
- void HttpCoroutineAdapter::checkDefaultHeaders(LLCore::HttpHeaders::ptr_t& headers)
- {
- if (!headers)
- {
- headers.reset(new LLCore::HttpHeaders);
- }
- if (!headers->find(HTTP_OUT_HEADER_ACCEPT))
- {
- headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
- }
- if (!headers->find(HTTP_OUT_HEADER_CONTENT_TYPE))
- {
- headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
- }
- if (gMessageSystemp && !headers->find("X-SecondLife-UDP-Listen-Port"))
- {
- headers->append("X-SecondLife-UDP-Listen-Port",
- llformat("%d", gMessageSystemp->mPort));
- }
- }
- void HttpCoroutineAdapter::cancelSuspendedOperation()
- {
- LLCore::HttpRequest::ptr_t request = mWeakRequest.lock();
- HttpCoroHandler::ptr_t handler = mWeakHandler.lock();
- if (request && handler && mYieldingHandle != LLCORE_HTTP_HANDLE_INVALID)
- {
- llinfos << "Cancelling yielding request for " << mAdapterName
- << llendl;
- request->requestCancel(mYieldingHandle, handler);
- cleanState();
- // We now need to wake up the coroutine, else it might keep sitting
- // there for a while, which would be a problem on viewer exit. HB
- // First, create a fake result LLSD with cancelled operation as the
- // error status.
- LLSD status = LLSD::emptyMap();
- HttpCoroHandler::writeStatusCodes(gStatusCancelled, mURL, status);
- LLSD result = LLSD::emptyMap();
- result["http_result"] = status;
- // Then, post to the associated pump, passing the fake result LLSD.
- // IMPORTANT: since this call shall result in the exit of the coroutine
- // and likely the destruction of our adapter instance, it *must* be
- // immediately followed by a return.
- handler->getReplyPump().post(result);
- return;
- }
- LL_DEBUGS("CoreHttp") << "Operation for " << mAdapterName;
- if (!handler)
- {
- LL_CONT << " already finished";
- }
- else if (!request)
- {
- LL_CONT << " got a NULL request pointer";
- }
- else
- {
- LL_CONT << " not yielding";
- }
- LL_CONT << LL_ENDL;
- }
- void HttpCoroutineAdapter::saveState(const std::string& url,
- LLCore::HttpHandle yielding_handle,
- HttpCoroHandler::ptr_t& handler)
- {
- mURL = url;
- mWeakRequest = mRequest;
- mWeakHandler = handler;
- mYieldingHandle = yielding_handle;
- }
- void HttpCoroutineAdapter::cleanState()
- {
- mURL.clear();
- mWeakRequest.reset();
- mWeakHandler.reset();
- mYieldingHandle = LLCORE_HTTP_HANDLE_INVALID;
- }
- LLSD HttpCoroutineAdapter::buildImmediateErrorResult(const std::string& url)
- {
- if (!mRequest)
- {
- llwarns << "Invalid request !" << llendl;
- return LLSD();
- }
- LLCore::HttpStatus status = mRequest->getStatus();
- llwarns << "Error posting to: " << url << " - Status: "
- << status.getStatus() << " - Message: " << status.getMessage()
- << llendl;
- // Mimic the status results returned from an http error that we had to wait
- // on
- LLSD httpresults = LLSD::emptyMap();
- HttpCoroHandler::writeStatusCodes(status, url, httpresults);
- LLSD errors = LLSD::emptyMap();
- errors["http_result"] = httpresults;
- return errors;
- }
- //static
- LLCore::HttpStatus HttpCoroutineAdapter::getStatusFromLLSD(const LLSD& results)
- {
- const LLSD* resp;
- if (results.has(HttpCoroutineAdapter::HTTP_RESULTS))
- {
- resp = &results[HttpCoroutineAdapter::HTTP_RESULTS];
- }
- else
- {
- resp = &results;
- }
- S32 type = (*resp)[HttpCoroutineAdapter::HTTP_RESULTS_TYPE].asInteger();
- S32 code = (*resp)[HttpCoroutineAdapter::HTTP_RESULTS_STATUS].asInteger();
- return LLCore::HttpStatus((LLCore::HttpStatus::type_enum_t)type,
- (short)code);
- }
- //static
- void HttpCoroutineAdapter::callbackHttpGet(const std::string& url,
- LLCore::HttpRequest::policy_t policy_id,
- completionCallback_t success,
- completionCallback_t failure)
- {
- gCoros.launch("HttpCoroutineAdapter::genericGetCoro",
- boost::bind(&HttpCoroutineAdapter::trivialGetCoro, url,
- policy_id, success, failure));
- }
- //static
- void HttpCoroutineAdapter::messageHttpGet(const std::string& url,
- const std::string& success,
- const std::string& failure)
- {
- completionCallback_t cb_succ = NULL;
- if (!success.empty())
- {
- cb_succ = (completionCallback_t)boost::bind(&logMessageSuccess,
- "HttpCoroutineAdapter",
- url, success);
- }
- completionCallback_t cb_fail = NULL;
- if (!failure.empty())
- {
- cb_fail = (completionCallback_t)boost::bind(&logMessageFail,
- "HttpCoroutineAdapter",
- url, failure);
- }
- callbackHttpGet(url, cb_succ, cb_fail);
- }
- //static
- void HttpCoroutineAdapter::trivialGetCoro(std::string url,
- LLCore::HttpRequest::policy_t policy_id,
- completionCallback_t success,
- completionCallback_t failure)
- {
- LL_DEBUGS("CoreHttp") << "Generic GET for: " << url << LL_ENDL;
- LLCore::HttpOptions::ptr_t options(DEFAULT_HTTP_OPTIONS);
- options->setWantHeaders(true);
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("genericGetCoro", policy_id);
- LLSD result = adapter.getAndSuspend(url, options);
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (status)
- {
- if (success)
- {
- success(result);
- }
- }
- else if (failure)
- {
- const LLSD& http_results =
- result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- failure(http_results);
- }
- }
- //static
- void HttpCoroutineAdapter::callbackHttpPost(const std::string& url,
- LLCore::HttpRequest::policy_t policy_id,
- const LLSD& postdata,
- completionCallback_t success,
- completionCallback_t failure)
- {
- gCoros.launch("HttpCoroutineAdapter::genericPostCoro",
- boost::bind(&HttpCoroutineAdapter::trivialPostCoro, url,
- policy_id, postdata, success, failure));
- }
- //static
- void HttpCoroutineAdapter::messageHttpPost(const std::string& url,
- const LLSD& postdata,
- const std::string& success,
- const std::string& failure)
- {
- completionCallback_t cb_succ = NULL;
- if (!success.empty())
- {
- cb_succ = (completionCallback_t)boost::bind(&logMessageSuccess,
- "HttpCoroutineAdapter",
- url, success);
- }
- completionCallback_t cb_fail = NULL;
- if (!failure.empty())
- {
- cb_fail = (completionCallback_t)boost::bind(&logMessageFail,
- "HttpCoroutineAdapter",
- url, failure);
- }
- callbackHttpPost(url, postdata, cb_succ, cb_fail);
- }
- //static
- void HttpCoroutineAdapter::trivialPostCoro(std::string url,
- LLCore::HttpRequest::policy_t policy_id,
- LLSD postdata,
- completionCallback_t success,
- completionCallback_t failure)
- {
- LL_DEBUGS("CoreHttp") << "Generic POST for: " << url << LL_ENDL;
- LLCore::HttpOptions::ptr_t options(DEFAULT_HTTP_OPTIONS);
- options->setWantHeaders(true);
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("genericPostCoro", policy_id);
- LLSD result = adapter.postAndSuspend(url, postdata, options);
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (status)
- {
- // If a success routine is provided call it.
- if (success)
- {
- success(result);
- }
- }
- else if (failure)
- {
- // If a failure routine is provided call it.
- const LLSD& http_results =
- result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- failure(http_results);
- }
- }
- } // End namespace LLCoreHttpUtil
|