aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llurlrequest.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/llmessage/llurlrequest.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to 'linden/indra/llmessage/llurlrequest.cpp')
-rw-r--r--linden/indra/llmessage/llurlrequest.cpp209
1 files changed, 47 insertions, 162 deletions
diff --git a/linden/indra/llmessage/llurlrequest.cpp b/linden/indra/llmessage/llurlrequest.cpp
index 6c826cd..eabd951 100644
--- a/linden/indra/llmessage/llurlrequest.cpp
+++ b/linden/indra/llmessage/llurlrequest.cpp
@@ -37,6 +37,7 @@
37#include <curl/curl.h> 37#include <curl/curl.h>
38#include <algorithm> 38#include <algorithm>
39 39
40#include "llcurl.h"
40#include "llioutil.h" 41#include "llioutil.h"
41#include "llmemtype.h" 42#include "llmemtype.h"
42#include "llpumpio.h" 43#include "llpumpio.h"
@@ -52,8 +53,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
52const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri"); 53const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
53 54
54 55
55static 56static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
56size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
57 57
58/** 58/**
59 * class LLURLRequestDetail 59 * class LLURLRequestDetail
@@ -63,12 +63,8 @@ class LLURLRequestDetail
63public: 63public:
64 LLURLRequestDetail(); 64 LLURLRequestDetail();
65 ~LLURLRequestDetail(); 65 ~LLURLRequestDetail();
66 CURLM* mCurlMulti; 66 std::string mURL;
67 CURL* mCurl; 67 LLCurlEasyRequest* mCurlRequest;
68 struct curl_slist* mHeaders;
69 char* mURL;
70 char mCurlErrorBuf[CURL_ERROR_SIZE + 1]; /* Flawfinder: ignore */
71 bool mNeedToRemoveEasyHandle;
72 LLBufferArray* mResponseBuffer; 68 LLBufferArray* mResponseBuffer;
73 LLChannelDescriptors mChannels; 69 LLChannelDescriptors mChannels;
74 U8* mLastRead; 70 U8* mLastRead;
@@ -77,11 +73,7 @@ public:
77}; 73};
78 74
79LLURLRequestDetail::LLURLRequestDetail() : 75LLURLRequestDetail::LLURLRequestDetail() :
80 mCurlMulti(NULL), 76 mCurlRequest(NULL),
81 mCurl(NULL),
82 mHeaders(NULL),
83 mURL(NULL),
84 mNeedToRemoveEasyHandle(false),
85 mResponseBuffer(NULL), 77 mResponseBuffer(NULL),
86 mLastRead(NULL), 78 mLastRead(NULL),
87 mBodyLimit(0), 79 mBodyLimit(0),
@@ -89,34 +81,13 @@ LLURLRequestDetail::LLURLRequestDetail() :
89 81
90{ 82{
91 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); 83 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
92 mCurlErrorBuf[0] = '\0'; 84 mCurlRequest = new LLCurlEasyRequest();
93} 85}
94 86
95LLURLRequestDetail::~LLURLRequestDetail() 87LLURLRequestDetail::~LLURLRequestDetail()
96{ 88{
97 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); 89 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
98 if(mCurl) 90 delete mCurlRequest;
99 {
100 if(mNeedToRemoveEasyHandle && mCurlMulti)
101 {
102 curl_multi_remove_handle(mCurlMulti, mCurl);
103 mNeedToRemoveEasyHandle = false;
104 }
105 curl_easy_cleanup(mCurl);
106 mCurl = NULL;
107 }
108 if(mCurlMulti)
109 {
110 curl_multi_cleanup(mCurlMulti);
111 mCurlMulti = NULL;
112 }
113 if(mHeaders)
114 {
115 curl_slist_free_all(mHeaders);
116 mHeaders = NULL;
117 }
118 delete[] mURL;
119 mURL = NULL;
120 mResponseBuffer = NULL; 91 mResponseBuffer = NULL;
121 mLastRead = NULL; 92 mLastRead = NULL;
122} 93}
@@ -126,9 +97,6 @@ LLURLRequestDetail::~LLURLRequestDetail()
126 * class LLURLRequest 97 * class LLURLRequest
127 */ 98 */
128 99
129static std::string sCAFile("");
130static std::string sCAPath("");
131
132LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) : 100LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
133 mAction(action) 101 mAction(action)
134{ 102{
@@ -155,31 +123,13 @@ LLURLRequest::~LLURLRequest()
155void LLURLRequest::setURL(const std::string& url) 123void LLURLRequest::setURL(const std::string& url)
156{ 124{
157 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); 125 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
158 if(mDetail->mURL) 126 mDetail->mURL = url;
159 {
160 // *NOTE: if any calls to set the url have been made to curl,
161 // this will probably lead to a crash.
162 delete[] mDetail->mURL;
163 mDetail->mURL = NULL;
164 }
165 if(!url.empty())
166 {
167 mDetail->mURL = new char[url.size() + 1];
168 url.copy(mDetail->mURL, url.size());
169 mDetail->mURL[url.size()] = '\0';
170 }
171} 127}
172 128
173void LLURLRequest::addHeader(const char* header) 129void LLURLRequest::addHeader(const char* header)
174{ 130{
175 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); 131 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
176 mDetail->mHeaders = curl_slist_append(mDetail->mHeaders, header); 132 mDetail->mCurlRequest->slist_append(header);
177}
178
179void LLURLRequest::requestEncoding(const char* encoding)
180{
181 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
182 curl_easy_setopt(mDetail->mCurl, CURLOPT_ENCODING, encoding);
183} 133}
184 134
185void LLURLRequest::setBodyLimit(U32 size) 135void LLURLRequest::setBodyLimit(U32 size)
@@ -188,22 +138,17 @@ void LLURLRequest::setBodyLimit(U32 size)
188 mDetail->mIsBodyLimitSet = true; 138 mDetail->mIsBodyLimitSet = true;
189} 139}
190 140
191void LLURLRequest::checkRootCertificate(bool check, const char* caBundle) 141void LLURLRequest::checkRootCertificate(bool check)
192{ 142{
193 curl_easy_setopt(mDetail->mCurl, CURLOPT_SSL_VERIFYPEER, (check? TRUE : FALSE)); 143 mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, (check? TRUE : FALSE));
194 if (caBundle) 144 mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
195 {
196 curl_easy_setopt(mDetail->mCurl, CURLOPT_CAINFO, caBundle);
197 }
198} 145}
199 146
200void LLURLRequest::setCallback(LLURLRequestComplete* callback) 147void LLURLRequest::setCallback(LLURLRequestComplete* callback)
201{ 148{
202 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); 149 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
203 mCompletionCallback = callback; 150 mCompletionCallback = callback;
204 151 mDetail->mCurlRequest->setHeaderCallback(&headerCallback, (void*)callback);
205 curl_easy_setopt(mDetail->mCurl, CURLOPT_HEADERFUNCTION, &headerCallback);
206 curl_easy_setopt(mDetail->mCurl, CURLOPT_WRITEHEADER, callback);
207} 152}
208 153
209// Added to mitigate the effect of libcurl looking 154// Added to mitigate the effect of libcurl looking
@@ -235,15 +180,15 @@ void LLURLRequest::useProxy(bool use_proxy)
235 } 180 }
236 181
237 182
238 lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << env_proxy << llendl; 183 lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl;
239 184
240 if (env_proxy && use_proxy) 185 if (env_proxy && use_proxy)
241 { 186 {
242 curl_easy_setopt(mDetail->mCurl, CURLOPT_PROXY, env_proxy); 187 mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy);
243 } 188 }
244 else 189 else
245 { 190 {
246 curl_easy_setopt(mDetail->mCurl, CURLOPT_PROXY, ""); 191 mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, "");
247 } 192 }
248} 193}
249 194
@@ -309,27 +254,20 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
309 case STATE_PROCESSING_RESPONSE: 254 case STATE_PROCESSING_RESPONSE:
310 { 255 {
311 PUMP_DEBUG; 256 PUMP_DEBUG;
312 const S32 MAX_CALLS = 5;
313 S32 count = MAX_CALLS;
314 CURLMcode code;
315 LLIOPipe::EStatus status = STATUS_BREAK; 257 LLIOPipe::EStatus status = STATUS_BREAK;
316 S32 queue; 258 mDetail->mCurlRequest->perform();
317 do 259 while(1)
318 {
319 LLFastTimer t2(LLFastTimer::FTM_CURL);
320 code = curl_multi_perform(mDetail->mCurlMulti, &queue);
321 }while((CURLM_CALL_MULTI_PERFORM == code) && (queue > 0) && count--);
322 CURLMsg* curl_msg;
323 do
324 { 260 {
325 curl_msg = curl_multi_info_read(mDetail->mCurlMulti, &queue); 261 CURLcode result;
326 if(curl_msg && (curl_msg->msg == CURLMSG_DONE)) 262 bool newmsg = mDetail->mCurlRequest->getResult(&result);
263 if (!newmsg)
327 { 264 {
328 mState = STATE_HAVE_RESPONSE; 265 break;
266 }
329 267
330 CURLcode result = curl_msg->data.result; 268 mState = STATE_HAVE_RESPONSE;
331 switch(result) 269 switch(result)
332 { 270 {
333 case CURLE_OK: 271 case CURLE_OK:
334 case CURLE_WRITE_ERROR: 272 case CURLE_WRITE_ERROR:
335 // NB: The error indication means that we stopped the 273 // NB: The error indication means that we stopped the
@@ -352,31 +290,21 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
352 mCompletionCallback = NULL; 290 mCompletionCallback = NULL;
353 } 291 }
354 break; 292 break;
293 case CURLE_FAILED_INIT:
355 case CURLE_COULDNT_CONNECT: 294 case CURLE_COULDNT_CONNECT:
356 status = STATUS_NO_CONNECTION; 295 status = STATUS_NO_CONNECTION;
357 break; 296 break;
358 default: 297 default:
359 llwarns << "URLRequest Error: " << curl_msg->data.result 298 llwarns << "URLRequest Error: " << result
360 << ", " 299 << ", "
361#if LL_DARWIN 300 << LLCurl::strerror(result)
362 // curl_easy_strerror was added in libcurl 7.12.0. Unfortunately, the version in the Mac OS X 10.3.9 SDK is 7.10.2...
363 // There's a problem with the custom curl headers in our build that keeps me from #ifdefing this on the libcurl version number
364 // (the correct check would be #if LIBCURL_VERSION_NUM >= 0x070c00). We'll fix the header problem soon, but for now
365 // just punt and print the numeric error code on the Mac.
366 << curl_msg->data.result
367#else // LL_DARWIN
368 << curl_easy_strerror(curl_msg->data.result)
369#endif // LL_DARWIN
370 << ", " 301 << ", "
371 << (mDetail->mURL ? mDetail->mURL : "<EMPTY URL>") 302 << (mDetail->mURL.empty() ? "<EMPTY URL>" : mDetail->mURL)
372 << llendl; 303 << llendl;
373 status = STATUS_ERROR; 304 status = STATUS_ERROR;
374 break; 305 break;
375 }
376 curl_multi_remove_handle(mDetail->mCurlMulti, mDetail->mCurl);
377 mDetail->mNeedToRemoveEasyHandle = false;
378 } 306 }
379 }while(curl_msg && (queue > 0)); 307 }
380 return status; 308 return status;
381 } 309 }
382 case STATE_HAVE_RESPONSE: 310 case STATE_HAVE_RESPONSE:
@@ -397,26 +325,9 @@ void LLURLRequest::initialize()
397 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); 325 LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
398 mState = STATE_INITIALIZED; 326 mState = STATE_INITIALIZED;
399 mDetail = new LLURLRequestDetail; 327 mDetail = new LLURLRequestDetail;
400 mDetail->mCurl = curl_easy_init(); 328 mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
401 mDetail->mCurlMulti = curl_multi_init(); 329 mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
402 curl_easy_setopt(mDetail->mCurl, CURLOPT_NOSIGNAL, 1); 330 mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
403 curl_easy_setopt(mDetail->mCurl, CURLOPT_WRITEFUNCTION, &downCallback);
404 curl_easy_setopt(mDetail->mCurl, CURLOPT_WRITEDATA, this);
405 curl_easy_setopt(mDetail->mCurl, CURLOPT_READFUNCTION, &upCallback);
406 curl_easy_setopt(mDetail->mCurl, CURLOPT_READDATA, this);
407 curl_easy_setopt(
408 mDetail->mCurl,
409 CURLOPT_ERRORBUFFER,
410 mDetail->mCurlErrorBuf);
411
412 if(sCAPath != std::string(""))
413 {
414 curl_easy_setopt(mDetail->mCurl, CURLOPT_CAPATH, sCAPath.c_str());
415 }
416 if(sCAFile != std::string(""))
417 {
418 curl_easy_setopt(mDetail->mCurl, CURLOPT_CAINFO, sCAFile.c_str());
419 }
420} 331}
421 332
422bool LLURLRequest::configure() 333bool LLURLRequest::configure()
@@ -429,15 +340,14 @@ bool LLURLRequest::configure()
429 switch(mAction) 340 switch(mAction)
430 { 341 {
431 case HTTP_HEAD: 342 case HTTP_HEAD:
432 curl_easy_setopt(mDetail->mCurl, CURLOPT_HEADER, 1); 343 mDetail->mCurlRequest->setopt(CURLOPT_HEADER, 1);
433 curl_easy_setopt(mDetail->mCurl, CURLOPT_NOBODY, 1); 344 mDetail->mCurlRequest->setopt(CURLOPT_NOBODY, 1);
434 curl_easy_setopt(mDetail->mCurl, CURLOPT_FOLLOWLOCATION, 1); 345 mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
435 rv = true; 346 rv = true;
436 break; 347 break;
437
438 case HTTP_GET: 348 case HTTP_GET:
439 curl_easy_setopt(mDetail->mCurl, CURLOPT_HTTPGET, 1); 349 mDetail->mCurlRequest->setopt(CURLOPT_HTTPGET, 1);
440 curl_easy_setopt(mDetail->mCurl, CURLOPT_FOLLOWLOCATION, 1); 350 mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
441 rv = true; 351 rv = true;
442 break; 352 break;
443 353
@@ -446,8 +356,8 @@ bool LLURLRequest::configure()
446 // to turning this on, and I am not too sure what it means. 356 // to turning this on, and I am not too sure what it means.
447 addHeader("Expect:"); 357 addHeader("Expect:");
448 358
449 curl_easy_setopt(mDetail->mCurl, CURLOPT_UPLOAD, 1); 359 mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
450 curl_easy_setopt(mDetail->mCurl, CURLOPT_INFILESIZE, bytes); 360 mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
451 rv = true; 361 rv = true;
452 break; 362 break;
453 363
@@ -461,15 +371,13 @@ bool LLURLRequest::configure()
461 addHeader("Content-Type:"); 371 addHeader("Content-Type:");
462 372
463 // Set the handle for an http post 373 // Set the handle for an http post
464 curl_easy_setopt(mDetail->mCurl, CURLOPT_POST, 1); 374 mDetail->mCurlRequest->setPost(NULL, bytes);
465 curl_easy_setopt(mDetail->mCurl, CURLOPT_POSTFIELDS, NULL);
466 curl_easy_setopt(mDetail->mCurl, CURLOPT_POSTFIELDSIZE, bytes);
467 rv = true; 375 rv = true;
468 break; 376 break;
469 377
470 case HTTP_DELETE: 378 case HTTP_DELETE:
471 // Set the handle for an http post 379 // Set the handle for an http post
472 curl_easy_setopt(mDetail->mCurl, CURLOPT_CUSTOMREQUEST, "DELETE"); 380 mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
473 rv = true; 381 rv = true;
474 break; 382 break;
475 383
@@ -479,24 +387,14 @@ bool LLURLRequest::configure()
479 } 387 }
480 if(rv) 388 if(rv)
481 { 389 {
482 if(mDetail->mHeaders) 390 mDetail->mCurlRequest->sendRequest(mDetail->mURL);
483 {
484 curl_easy_setopt(
485 mDetail->mCurl,
486 CURLOPT_HTTPHEADER,
487 mDetail->mHeaders);
488 }
489 curl_easy_setopt(mDetail->mCurl, CURLOPT_URL, mDetail->mURL);
490 lldebugs << "URL: " << mDetail->mURL << llendl;
491 curl_multi_add_handle(mDetail->mCurlMulti, mDetail->mCurl);
492 mDetail->mNeedToRemoveEasyHandle = true;
493 } 391 }
494 return rv; 392 return rv;
495} 393}
496 394
497// static 395// static
498size_t LLURLRequest::downCallback( 396size_t LLURLRequest::downCallback(
499 void* data, 397 char* data,
500 size_t size, 398 size_t size,
501 size_t nmemb, 399 size_t nmemb,
502 void* user) 400 void* user)
@@ -530,7 +428,7 @@ size_t LLURLRequest::downCallback(
530 428
531// static 429// static
532size_t LLURLRequest::upCallback( 430size_t LLURLRequest::upCallback(
533 void* data, 431 char* data,
534 size_t size, 432 size_t size,
535 size_t nmemb, 433 size_t nmemb,
536 void* user) 434 void* user)
@@ -550,8 +448,7 @@ size_t LLURLRequest::upCallback(
550 return bytes; 448 return bytes;
551} 449}
552 450
553static 451static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
554size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
555{ 452{
556 const char* headerLine = (const char*)data; 453 const char* headerLine = (const char*)data;
557 size_t headerLen = size * nmemb; 454 size_t headerLen = size * nmemb;
@@ -607,18 +504,6 @@ size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
607 return headerLen; 504 return headerLen;
608} 505}
609 506
610//static
611void LLURLRequest::setCertificateAuthorityFile(const std::string& file_name)
612{
613 sCAFile = file_name;
614}
615
616//static
617void LLURLRequest::setCertificateAuthorityPath(const std::string& path)
618{
619 sCAPath = path;
620}
621
622/** 507/**
623 * LLContextURLExtractor 508 * LLContextURLExtractor
624 */ 509 */