summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
authorAaron Brashears <aaronb@lindenlab.com>2009-05-18 23:38:35 +0000
committerAaron Brashears <aaronb@lindenlab.com>2009-05-18 23:38:35 +0000
commit6df2755ba6b24d0cefd52ce175b0212dd46c9b10 (patch)
tree833bc29e7bd5438eb89f34119ae157efe6258b2c /indra/llmessage
parent0257214763203708e8e29d09346e777b95cdfce6 (diff)
Result of svn merge -r119432:120464 svn+ssh://svn/svn/linden/branches/http_database/merge-03 into trunk. QAR-1462
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/llhttpclient.cpp140
-rw-r--r--indra/llmessage/llhttpclient.h8
-rw-r--r--indra/llmessage/llmessageconfig.cpp7
-rw-r--r--indra/llmessage/llurlrequest.cpp20
-rw-r--r--indra/llmessage/llurlrequest.h5
-rw-r--r--indra/llmessage/message.h16
6 files changed, 159 insertions, 37 deletions
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 307d9b92fa..8b90a4c5ca 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -224,6 +224,10 @@ static void request(
LLURLRequest* req = new LLURLRequest(method, url);
req->checkRootCertificate(true);
+
+ lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "
+ << headers << llendl;
+
// Insert custom headers is the caller sent any
if (headers.isMap())
{
@@ -375,72 +379,140 @@ private:
std::string mBuffer;
};
-// *TODO: Deprecate (only used by dataserver)
-// This call is blocking! This is probably usually bad. :(
-LLSD LLHTTPClient::blockingGet(const std::string& url)
+// These calls are blocking! This is usually bad, unless you're a dataserver. Then it's awesome.
+
+/**
+ @brief does a blocking request on the url, returning the data or bad status.
+
+ @param url URI to verb on.
+ @param method the verb to hit the URI with.
+ @param body the body of the call (if needed - for instance not used for GET and DELETE, but is for POST and PUT)
+ @param headers HTTP headers to use for the request.
+ @param timeout Curl timeout to use. Defaults to 5. Rationale:
+ Without this timeout, blockingGet() calls have been observed to take
+ up to 90 seconds to complete. Users of blockingGet() already must
+ check the HTTP return code for validity, so this will not introduce
+ new errors. A 5 second timeout will succeed > 95% of the time (and
+ probably > 99% of the time) based on my statistics. JC
+
+ @returns an LLSD map: {status: integer, body: map}
+ */
+static LLSD blocking_request(
+ const std::string& url,
+ LLURLRequest::ERequestAction method,
+ const LLSD& body,
+ const LLSD& headers = LLSD(),
+ const F32 timeout = 5
+)
{
- llinfos << "blockingGet of " << url << llendl;
-
- // Returns an LLSD map: {status: integer, body: map}
- char curl_error_buffer[CURL_ERROR_SIZE];
+ lldebugs << "blockingRequest of " << url << llendl;
+ char curl_error_buffer[CURL_ERROR_SIZE] = "\0";
CURL* curlp = curl_easy_init();
-
LLHTTPBuffer http_buffer;
-
- // Without this timeout, blockingGet() calls have been observed to take
- // up to 90 seconds to complete. Users of blockingGet() already must
- // check the HTTP return code for validity, so this will not introduce
- // new errors. A 5 second timeout will succeed > 95% of the time (and
- // probably > 99% of the time) based on my statistics. JC
+ std::string body_str;
+
+ // other request method checks root cert first, we skip?
+ //req->checkRootCertificate(true);
+
+ // * Set curl handle options
curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts
- curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5); // seconds
-
+ curl_easy_setopt(curlp, CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function.
curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write);
curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer);
curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());
curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer);
- curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1);
-
- struct curl_slist *header_list = NULL;
- header_list = curl_slist_append(header_list, "Accept: application/llsd+xml");
- CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, header_list);
+
+ // * Setup headers (don't forget to free them after the call!)
+ curl_slist* headers_list = NULL;
+ if (headers.isMap())
+ {
+ LLSD::map_const_iterator iter = headers.beginMap();
+ LLSD::map_const_iterator end = headers.endMap();
+ for (; iter != end; ++iter)
+ {
+ std::ostringstream header;
+ header << iter->first << ": " << iter->second.asString() ;
+ lldebugs << "header = " << header.str() << llendl;
+ headers_list = curl_slist_append(headers_list, header.str().c_str());
+ }
+ }
+
+ // * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
+ if (method == LLURLRequest::HTTP_GET)
+ {
+ curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
+ }
+ else if (method == LLURLRequest::HTTP_POST)
+ {
+ curl_easy_setopt(curlp, CURLOPT_POST, 1);
+ //serialize to ostr then copy to str - need to because ostr ptr is unstable :(
+ std::ostringstream ostr;
+ LLSDSerialize::toXML(body, ostr);
+ body_str = ostr.str();
+ curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
+ //copied from PHP libs, correct?
+ headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
+
+ // copied from llurlrequest.cpp
+ // it appears that apache2.2.3 or django in etch is busted. If
+ // we do not clear the expect header, we get a 500. May be
+ // limited to django/mod_wsgi.
+ headers_list = curl_slist_append(headers_list, "Expect:");
+ }
+
+ // * Do the action using curl, handle results
+ lldebugs << "HTTP body: " << body_str << llendl;
+ headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
+ CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
if ( curl_result != CURLE_OK )
{
- llinfos << "Curl is hosed - can't add Accept header for llsd+xml" << llendl;
+ llinfos << "Curl is hosed - can't add headers" << llendl;
}
LLSD response = LLSD::emptyMap();
-
S32 curl_success = curl_easy_perform(curlp);
-
S32 http_status = 499;
- curl_easy_getinfo(curlp,CURLINFO_RESPONSE_CODE, &http_status);
-
+ curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
response["status"] = http_status;
-
- if (curl_success != 0
- && http_status != 404) // We expect 404s, don't spam for them.
+ // if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
+ if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
{
+ // We expect 404s, don't spam for them.
+ llwarns << "CURL REQ URL: " << url << llendl;
+ llwarns << "CURL REQ METHOD TYPE: " << method << llendl;
+ llwarns << "CURL REQ HEADERS: " << headers.asString() << llendl;
+ llwarns << "CURL REQ BODY: " << body_str << llendl;
+ llwarns << "CURL HTTP_STATUS: " << http_status << llendl;
llwarns << "CURL ERROR: " << curl_error_buffer << llendl;
-
+ llwarns << "CURL ERROR BODY: " << http_buffer.asString() << llendl;
response["body"] = http_buffer.asString();
}
else
{
response["body"] = http_buffer.asLLSD();
+ lldebugs << "CURL response: " << http_buffer.asString() << llendl;
}
- if(header_list)
+ if(headers_list)
{ // free the header list
- curl_slist_free_all(header_list);
- header_list = NULL;
+ curl_slist_free_all(headers_list);
}
+ // * Cleanup
curl_easy_cleanup(curlp);
-
return response;
}
+LLSD LLHTTPClient::blockingGet(const std::string& url)
+{
+ return blocking_request(url, LLURLRequest::HTTP_GET, LLSD());
+}
+
+LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
+{
+ return blocking_request(url, LLURLRequest::HTTP_POST, body);
+}
+
void LLHTTPClient::put(
const std::string& url,
const LLSD& body,
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index a0c9fac77f..3d0646e5fe 100644
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -142,6 +142,14 @@ public:
*/
static LLSD blockingGet(const std::string& url);
+ /**
+ * @brief Blocking HTTP POST that returns an LLSD map of status and body.
+ *
+ * @param url the complete serialized (and escaped) url to get
+ * @param body the LLSD post body
+ * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) }
+ */
+ static LLSD blockingPost(const std::string& url, const LLSD& body);
static void setPump(LLPumpIO& pump);
diff --git a/indra/llmessage/llmessageconfig.cpp b/indra/llmessage/llmessageconfig.cpp
index d4279354b6..dff0a3844c 100644
--- a/indra/llmessage/llmessageconfig.cpp
+++ b/indra/llmessage/llmessageconfig.cpp
@@ -66,7 +66,7 @@ public:
static LLMessageConfigFile& instance();
// return the singleton configuration file
- /* virtual */ void loadFile();
+ /* virtual */ bool loadFile();
void loadServerDefaults(const LLSD& data);
void loadMaxQueuedEvents(const LLSD& data);
void loadMessages(const LLSD& data);
@@ -98,7 +98,7 @@ LLMessageConfigFile& LLMessageConfigFile::instance()
}
// virtual
-void LLMessageConfigFile::loadFile()
+bool LLMessageConfigFile::loadFile()
{
LLSD data;
{
@@ -115,7 +115,7 @@ void LLMessageConfigFile::loadFile()
LL_INFOS("AppInit") << "LLMessageConfigFile::loadFile: file missing,"
" ill-formed, or simply undefined; not changing the"
" file" << LL_ENDL;
- return;
+ return false;
}
}
loadServerDefaults(data);
@@ -123,6 +123,7 @@ void LLMessageConfigFile::loadFile()
loadMessages(data);
loadCapBans(data);
loadMessageBans(data);
+ return true;
}
void LLMessageConfigFile::loadServerDefaults(const LLSD& data)
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 46e976fe35..3ab8057abb 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -98,6 +98,26 @@ LLURLRequestDetail::~LLURLRequestDetail()
* class LLURLRequest
*/
+// static
+std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
+{
+ static const std::string VERBS[] =
+ {
+ "(invalid)",
+ "HEAD",
+ "GET",
+ "PUT",
+ "POST",
+ "DELETE",
+ "MOVE"
+ };
+ if(((S32)action <=0) || ((S32)action >= REQUEST_ACTION_COUNT))
+ {
+ return VERBS[0];
+ }
+ return VERBS[action];
+}
+
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
mAction(action)
{
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index d1facbff0f..86ef71f085 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -81,6 +81,11 @@ public:
REQUEST_ACTION_COUNT
};
+ /**
+ * @brief Turn the requst action into an http verb.
+ */
+ static std::string actionAsVerb(ERequestAction action);
+
/**
* @brief Constructor.
*
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index b25b27eb0f..0f3576732d 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -509,6 +509,22 @@ private:
public:
// BOOL decodeData(const U8 *buffer, const LLHost &host);
+ /**
+ gets binary data from the current message.
+
+ @param blockname the name of the block in the message (from the message template)
+
+ @param varname
+
+ @param datap
+
+ @param size expected size - set to zero to get any amount of data up to max_size.
+ Make sure max_size is set in that case!
+
+ @param blocknum
+
+ @param max_size the max number of bytes to read
+ */
void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
void getBOOLFast( const char *block, const char *var, BOOL &data, S32 blocknum = 0);