summaryrefslogtreecommitdiff
path: root/indra/newview/llxmlrpclistener.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llxmlrpclistener.cpp')
-rw-r--r--indra/newview/llxmlrpclistener.cpp284
1 files changed, 45 insertions, 239 deletions
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
index 1148e81fd5..92e6c88752 100644
--- a/indra/newview/llxmlrpclistener.cpp
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -34,16 +34,6 @@
// STL headers
#include <map>
#include <set>
-// std headers
-// external library headers
-#include <boost/scoped_ptr.hpp>
-#include <boost/range.hpp> // boost::begin(), boost::end()
-
-#ifdef LL_USESYSTEMLIBS
-#include <xmlrpc.h>
-#else
-#include <xmlrpc-epi/xmlrpc.h>
-#endif
#include "curl/curl.h"
@@ -178,13 +168,6 @@ public:
static const CURLcodeMapper sCURLcodeMapper;
-LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname):
- mBoundListener(LLEventPumps::instance().
- obtain(pumpname).
- listen("LLXMLRPCListener", boost::bind(&LLXMLRPCListener::process, this, _1)))
-{
-}
-
/**
* Capture an outstanding LLXMLRPCTransaction and poll it periodically until
* done.
@@ -213,38 +196,20 @@ public:
mMethod(command["method"]),
mReplyPump(command["reply"])
{
- // LL_ERRS if any of these are missing
- const char* required[] = { "uri", "method", "reply" };
- // optional: "options" (array of string)
- // Validate the request
- std::set<std::string> missing;
- for (const char** ri = boost::begin(required); ri != boost::end(required); ++ri)
+ // LL_ERRS if any of these keys are missing or empty
+ if (mUri.empty() || mMethod.empty() || mReplyPump.empty())
{
- // If the command does not contain this required entry, add it to 'missing'.
- if (! command.has(*ri))
- {
- missing.insert(*ri);
- }
- }
- if (! missing.empty())
- {
- LL_ERRS("LLXMLRPCListener") << mMethod << " request missing params: ";
- const char* separator = "";
- for (std::set<std::string>::const_iterator mi(missing.begin()), mend(missing.end());
- mi != mend; ++mi)
- {
- LL_CONT << separator << *mi;
- separator = ", ";
- }
- LL_CONT << LL_ENDL;
+ LL_ERRS("LLXMLRPCListener")
+ << "Some params are missing: "
+ << "reply: '" << mReplyPump << "', "
+ << "method: '" << mMethod << "', "
+ << "uri: '" << mUri << "'"
+ << LL_ENDL;
}
- // Build the XMLRPC request.
- XMLRPC_REQUEST request = XMLRPC_RequestNew();
- XMLRPC_RequestSetMethodName(request, mMethod.c_str());
- XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
- XMLRPC_VALUE xparams = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
- LLSD params(command["params"]);
+ LLSD request_params = LLSD::emptyMap();
+
+ LLSD params = command.get("params");
if (params.isMap())
{
for (LLSD::map_const_iterator pi(params.beginMap()), pend(params.endMap());
@@ -252,44 +217,33 @@ public:
{
std::string name(pi->first);
LLSD param(pi->second);
- if (param.isString())
+ switch (param.type())
{
- XMLRPC_VectorAppendString(xparams, name.c_str(), param.asString().c_str(), 0);
- }
- else if (param.isInteger() || param.isBoolean())
- {
- XMLRPC_VectorAppendInt(xparams, name.c_str(), param.asInteger());
- }
- else if (param.isReal())
- {
- XMLRPC_VectorAppendDouble(xparams, name.c_str(), param.asReal());
- }
- else
- {
- LL_ERRS("LLXMLRPCListener") << mMethod << " request param "
- << name << " has unknown type: " << param << LL_ENDL;
+ case LLSD::TypeString:
+ case LLSD::TypeInteger:
+ case LLSD::TypeReal:
+ request_params.insert(name, param);
+ break;
+ case LLSD::TypeBoolean:
+ request_params.insert(name, param.asInteger());
+ break;
+ default:
+ LL_ERRS("LLXMLRPCListener") << mMethod
+ << " request param '" << name << "' has unknown type: " << param << LL_ENDL;
}
}
}
- LLSD options(command["options"]);
+
+ LLSD options = command.get("options");
if (options.isArray())
{
- XMLRPC_VALUE xoptions = XMLRPC_CreateVector("options", xmlrpc_vector_array);
- for (LLSD::array_const_iterator oi(options.beginArray()), oend(options.endArray());
- oi != oend; ++oi)
- {
- XMLRPC_VectorAppendString(xoptions, NULL, oi->asString().c_str(), 0);
- }
- XMLRPC_AddValueToVector(xparams, xoptions);
+ request_params.insert("options", options);
}
- XMLRPC_RequestSetData(request, xparams);
- mTransaction.reset(new LLXMLRPCTransaction(mUri, request, true, command.has("http_params")? LLSD(command["http_params"]) : LLSD()));
+ LLSD http_params = command.get("http_params");
+ mTransaction.reset(new LLXMLRPCTransaction(mUri, mMethod, request_params, http_params));
mPreviousStatus = mTransaction->status(NULL);
- // Free the XMLRPC_REQUEST object and the attached data values.
- XMLRPC_RequestFree(request, 1);
-
// Now ensure that we get regular callbacks to poll for completion.
mBoundListener =
LLEventPumps::instance().
@@ -323,7 +277,7 @@ public:
data["error"] = "";
data["transfer_rate"] = 0.0;
LLEventPump& replyPump(LLEventPumps::instance().obtain(mReplyPump));
- if (! done)
+ if (!done)
{
// Not done yet, carry on.
if (status == LLXMLRPCTransaction::StatusDownloading
@@ -367,10 +321,8 @@ public:
// Given 'message', need we care?
if (status == LLXMLRPCTransaction::StatusComplete)
{
- // Success! Parse data.
- std::string status_string(data["status"]);
- data["responses"] = parseResponse(status_string);
- data["status"] = status_string;
+ // Success! Retrieve response data.
+ data["responses"] = mTransaction->response();
}
// whether successful or not, send reply on requested LLEventPump
@@ -378,7 +330,7 @@ public:
// need to wake up the loginCoro now
llcoro::suspend();
- // Because mTransaction is a boost::scoped_ptr, deleting this object
+ // Because mTransaction is a std::unique_ptr, deleting this object
// frees our LLXMLRPCTransaction object.
// Because mBoundListener is an LLTempBoundListener, deleting this
// object disconnects it from "mainloop".
@@ -388,159 +340,6 @@ public:
}
private:
- /// Derived from LLUserAuth::parseResponse() and parseOptionInto()
- LLSD parseResponse(std::string& status_string)
- {
- // Extract every member into data["responses"] (a map of string
- // values).
- XMLRPC_REQUEST response = mTransaction->response();
- if (! response)
- {
- LL_DEBUGS("LLXMLRPCListener") << "No response" << LL_ENDL;
- return LLSD();
- }
-
- XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
- if (! param)
- {
- LL_DEBUGS("LLXMLRPCListener") << "Response contains no data" << LL_ENDL;
- return LLSD();
- }
-
- // Now, parse everything
- return parseValues(status_string, "", param);
- }
-
- LLSD parseValue(std::string& status_string, const std::string& key, const std::string& key_pfx, XMLRPC_VALUE param)
- {
- LLSD response;
-
- XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(param);
- switch (type)
- {
- case xmlrpc_type_empty:
- LL_INFOS("LLXMLRPCListener") << "Empty result for key " << key_pfx << key << LL_ENDL;
- break;
- case xmlrpc_type_base64:
- {
- S32 len = XMLRPC_GetValueStringLen(param);
- const char* buf = XMLRPC_GetValueBase64(param);
- if ((len > 0) && buf)
- {
- // During implementation this code was not tested
- // If you encounter this, please make sure this is correct,
- // then remove llassert
- llassert(0);
-
- LLSD::Binary data;
- data.resize(len);
- memcpy((void*)&data[0], (void*)buf, len);
- response = data;
- }
- else
- {
- LL_WARNS("LLXMLRPCListener") << "Potentially malformed xmlrpc_type_base64 for key "
- << key_pfx << key << LL_ENDL;
- }
- break;
- }
- case xmlrpc_type_boolean:
- {
- response = LLSD::Boolean(XMLRPC_GetValueBoolean(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_datetime:
- {
- std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << iso8601_date << LL_ENDL;
- response = LLSD::Date(iso8601_date);
- break;
- }
- case xmlrpc_type_double:
- {
- response = LLSD::Real(XMLRPC_GetValueDouble(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_int:
- {
- response = LLSD::Integer(XMLRPC_GetValueInt(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_string:
- {
- response = LLSD::String(XMLRPC_GetValueString(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_mixed:
- case xmlrpc_type_array:
- {
- // We expect this to be an array of submaps. Walk the array,
- // recursively parsing each submap and collecting them.
- LLSD array;
- int i = 0; // for descriptive purposes
- for (XMLRPC_VALUE row = XMLRPC_VectorRewind(param); row;
- row = XMLRPC_VectorNext(param), ++i)
- {
- // Recursive call. For the lower-level key_pfx, if 'key'
- // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
- // nested call, a subkey "bar" will then be logged as
- // "foo[0]:bar", and so forth.
- // Parse the scalar subkey/value pairs from this array
- // entry into a temp submap. Collect such submaps in 'array'.
-
- array.append(parseValue(status_string, "",
- STRINGIZE(key_pfx << key << '[' << i << "]:"),
- row));
- }
- // Having collected an 'array' of 'submap's, insert that whole
- // 'array' as the value of this 'key'.
- response = array;
- break;
- }
- case xmlrpc_type_struct:
- {
- response = parseValues(status_string,
- STRINGIZE(key_pfx << key << ':'),
- param);
- break;
- }
- case xmlrpc_type_none: // Not expected
- default:
- // whoops - unrecognized type
- LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key "
- << key_pfx << key << LL_ENDL;
- response = STRINGIZE("<bad XMLRPC type " << type << '>');
- status_string = "BadType";
- }
- return response;
- }
-
- /**
- * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map.
- * @param key_pfx Used to describe a given key in log messages. At top
- * level, pass "". When parsing an options array, pass the top-level key
- * name of the array plus the index of the array entry; to this we'll
- * append the subkey of interest.
- * @param param XMLRPC_VALUE iterator. At top level, pass
- * XMLRPC_RequestGetData(XMLRPC_REQUEST).
- */
- LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param)
- {
- LLSD responses;
- for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current;
- current = XMLRPC_VectorNext(param))
- {
- std::string key(XMLRPC_GetValueID(current));
- LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL;
- responses.insert(key, parseValue(status_string, key, key_pfx, current));
- }
- return responses;
- }
-
const LLReqID mReqID;
const std::string mUri;
const std::string mMethod;
@@ -550,11 +349,18 @@ private:
LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes.
};
-bool LLXMLRPCListener::process(const LLSD& command)
+LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname)
+: mBoundListener(LLEventPumps::instance().obtain(pumpname).listen
+(
+ "LLXMLRPCListener",
+ [&](const LLSD& command) -> bool
+ {
+ // Allocate a new heap Poller, but do not save a pointer to it. Poller
+ // will check its own status and free itself on completion of the request.
+ (new Poller(command));
+ // Conventional event listener return
+ return false;
+ }
+))
{
- // Allocate a new heap Poller, but do not save a pointer to it. Poller
- // will check its own status and free itself on completion of the request.
- (new Poller(command));
- // conventional event listener return
- return false;
}