aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llxmlrpctransaction.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/newview/llxmlrpctransaction.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/newview/llxmlrpctransaction.cpp')
-rw-r--r--linden/indra/newview/llxmlrpctransaction.cpp152
1 files changed, 63 insertions, 89 deletions
diff --git a/linden/indra/newview/llxmlrpctransaction.cpp b/linden/indra/newview/llxmlrpctransaction.cpp
index 96f3326..bc10c1b 100644
--- a/linden/indra/newview/llxmlrpctransaction.cpp
+++ b/linden/indra/newview/llxmlrpctransaction.cpp
@@ -33,10 +33,10 @@
33 33
34#include "llxmlrpctransaction.h" 34#include "llxmlrpctransaction.h"
35 35
36#include "llcurl.h"
36#include "llviewercontrol.h" 37#include "llviewercontrol.h"
37 38
38// Have to include these last to avoid queue redefinition! 39// Have to include these last to avoid queue redefinition!
39#include <curl/curl.h>
40#include <xmlrpc-epi/xmlrpc.h> 40#include <xmlrpc-epi/xmlrpc.h>
41 41
42#include "llappviewer.h" 42#include "llappviewer.h"
@@ -150,51 +150,48 @@ class LLXMLRPCTransaction::Impl
150{ 150{
151public: 151public:
152 typedef LLXMLRPCTransaction::Status Status; 152 typedef LLXMLRPCTransaction::Status Status;
153 153
154 CURL* mCurl; 154 LLCurlEasyRequest* mCurlRequest;
155 CURLM* mCurlMulti;
156 155
157 Status mStatus; 156 Status mStatus;
158 CURLcode mCurlCode; 157 CURLcode mCurlCode;
159 std::string mStatusMessage; 158 std::string mStatusMessage;
160 std::string mStatusURI; 159 std::string mStatusURI;
160 LLCurl::TransferInfo mTransferInfo;
161 161
162 char mCurlErrorBuffer[CURL_ERROR_SIZE]; /* Flawfinder: ignore */
163
164 std::string mURI; 162 std::string mURI;
165 char* mRequestText; 163 char* mRequestText;
166 int mRequestTextSize; 164 int mRequestTextSize;
167 165
168 std::string mProxyAddress; 166 std::string mProxyAddress;
169 struct curl_slist* mHeaders;
170 167
171 std::string mResponseText; 168 std::string mResponseText;
172 XMLRPC_REQUEST mResponse; 169 XMLRPC_REQUEST mResponse;
173 170
174 Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip); 171 Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip);
175 Impl(const std::string& uri, 172 Impl(const std::string& uri,
176 const std::string& method, LLXMLRPCValue params, bool useGzip); 173 const std::string& method, LLXMLRPCValue params, bool useGzip);
177 ~Impl(); 174 ~Impl();
178 175
179 bool process(); 176 bool process();
180 177
181 void setStatus(Status code, 178 void setStatus(Status code,
182 const std::string& message = "", const std::string& uri = ""); 179 const std::string& message = "", const std::string& uri = "");
183 void setCurlStatus(CURLcode); 180 void setCurlStatus(CURLcode);
184 181
185private: 182private:
186 void init(XMLRPC_REQUEST request, bool useGzip); 183 void init(XMLRPC_REQUEST request, bool useGzip);
187 184
188 static size_t curlDownloadCallback( 185 static size_t curlDownloadCallback(
189 void* data, size_t size, size_t nmemb, void* user_data); 186 char* data, size_t size, size_t nmemb, void* user_data);
190}; 187};
191 188
192LLXMLRPCTransaction::Impl::Impl(const std::string& uri, 189LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
193 XMLRPC_REQUEST request, bool useGzip) 190 XMLRPC_REQUEST request, bool useGzip)
194 : mCurl(0), mCurlMulti(0), 191 : mCurlRequest(0),
195 mStatus(LLXMLRPCTransaction::StatusNotStarted), 192 mStatus(LLXMLRPCTransaction::StatusNotStarted),
196 mURI(uri), 193 mURI(uri),
197 mRequestText(0), mHeaders(0), 194 mRequestText(0),
198 mResponse(0) 195 mResponse(0)
199{ 196{
200 init(request, useGzip); 197 init(request, useGzip);
@@ -203,10 +200,10 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
203 200
204LLXMLRPCTransaction::Impl::Impl(const std::string& uri, 201LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
205 const std::string& method, LLXMLRPCValue params, bool useGzip) 202 const std::string& method, LLXMLRPCValue params, bool useGzip)
206 : mCurl(0), mCurlMulti(0), 203 : mCurlRequest(0),
207 mStatus(LLXMLRPCTransaction::StatusNotStarted), 204 mStatus(LLXMLRPCTransaction::StatusNotStarted),
208 mURI(uri), 205 mURI(uri),
209 mRequestText(0), mHeaders(0), 206 mRequestText(0),
210 mResponse(0) 207 mResponse(0)
211{ 208{
212 XMLRPC_REQUEST request = XMLRPC_RequestNew(); 209 XMLRPC_REQUEST request = XMLRPC_RequestNew();
@@ -222,55 +219,53 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
222 219
223void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) 220void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
224{ 221{
225 mCurl = curl_easy_init(); 222 if (!mCurlRequest)
226 223 {
224 mCurlRequest = new LLCurlEasyRequest();
225 }
226
227 if (gSavedSettings.getBOOL("BrowserProxyEnabled")) 227 if (gSavedSettings.getBOOL("BrowserProxyEnabled"))
228 { 228 {
229 mProxyAddress = gSavedSettings.getString("BrowserProxyAddress"); 229 mProxyAddress = gSavedSettings.getString("BrowserProxyAddress");
230 S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" ); 230 S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" );
231 231
232 // tell curl about the settings 232 // tell curl about the settings
233 curl_easy_setopt(mCurl, CURLOPT_PROXY, mProxyAddress.c_str()); 233 mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress);
234 curl_easy_setopt(mCurl, CURLOPT_PROXYPORT, (long) port); 234 mCurlRequest->setopt(CURLOPT_PROXYPORT, port);
235 curl_easy_setopt(mCurl, CURLOPT_PROXYTYPE, (long) CURLPROXY_HTTP); 235 mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
236 }; 236 }
237 237
238// curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1L); // usefull for debugging 238// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
239 curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, 1L); 239 mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
240 curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &curlDownloadCallback); 240 mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
241 curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this); 241 mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, gVerifySSLCert);
242 curl_easy_setopt(mCurl, CURLOPT_ERRORBUFFER, &mCurlErrorBuffer); 242 mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, gVerifySSLCert? 2 : 0);
243 curl_easy_setopt(mCurl, CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str());
244 curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, (long) gVerifySSLCert);
245 curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, gVerifySSLCert? 2L : 0L);
246 // Be a little impatient about establishing connections. 243 // Be a little impatient about establishing connections.
247 curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 40L); 244 mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
248 245
249 /* Setting the DNS cache timeout to -1 disables it completely. 246 /* Setting the DNS cache timeout to -1 disables it completely.
250 This might help with bug #503 */ 247 This might help with bug #503 */
251 curl_easy_setopt(mCurl, CURLOPT_DNS_CACHE_TIMEOUT, -1L); 248 mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
249
250 mCurlRequest->slist_append("Content-Type: text/xml");
252 251
253 mHeaders = curl_slist_append(mHeaders, "Content-Type: text/xml");
254 curl_easy_setopt(mCurl, CURLOPT_URL, mURI.c_str());
255 curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaders);
256 if (useGzip) 252 if (useGzip)
257 { 253 {
258 curl_easy_setopt(mCurl, CURLOPT_ENCODING, ""); 254 mCurlRequest->setoptString(CURLOPT_ENCODING, "");
259 } 255 }
260 256
261 mRequestText = XMLRPC_REQUEST_ToXML(request, &mRequestTextSize); 257 mRequestText = XMLRPC_REQUEST_ToXML(request, &mRequestTextSize);
262 if (mRequestText) 258 if (mRequestText)
263 { 259 {
264 curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, mRequestText); 260 mCurlRequest->setoptString(CURLOPT_POSTFIELDS, mRequestText);
265 curl_easy_setopt(mCurl, CURLOPT_POSTFIELDSIZE, (long) mRequestTextSize); 261 mCurlRequest->setopt(CURLOPT_POSTFIELDSIZE, mRequestTextSize);
266 } 262 }
267 else 263 else
268 { 264 {
269 setStatus(StatusOtherError); 265 setStatus(StatusOtherError);
270 } 266 }
271 267
272 mCurlMulti = curl_multi_init(); 268 mCurlRequest->sendRequest(mURI);
273 curl_multi_add_handle(mCurlMulti, mCurl);
274} 269}
275 270
276 271
@@ -281,30 +276,12 @@ LLXMLRPCTransaction::Impl::~Impl()
281 XMLRPC_RequestFree(mResponse, 1); 276 XMLRPC_RequestFree(mResponse, 1);
282 } 277 }
283 278
284 if (mHeaders)
285 {
286 curl_slist_free_all(mHeaders);
287 }
288
289 if (mRequestText) 279 if (mRequestText)
290 { 280 {
291 XMLRPC_Free(mRequestText); 281 XMLRPC_Free(mRequestText);
292 } 282 }
293 283
294 if (mCurl) 284 delete mCurlRequest;
295 {
296 if (mCurlMulti)
297 {
298 curl_multi_remove_handle(mCurlMulti, mCurl);
299 }
300 curl_easy_cleanup(mCurl);
301 }
302
303 if (mCurlMulti)
304 {
305 curl_multi_cleanup(mCurlMulti);
306 }
307
308} 285}
309 286
310bool LLXMLRPCTransaction::Impl::process() 287bool LLXMLRPCTransaction::Impl::process()
@@ -333,27 +310,28 @@ bool LLXMLRPCTransaction::Impl::process()
333 310
334 const F32 MAX_PROCESSING_TIME = 0.05f; 311 const F32 MAX_PROCESSING_TIME = 0.05f;
335 LLTimer timer; 312 LLTimer timer;
336 int count; 313
337 314 while (mCurlRequest->perform() > 0)
338 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(mCurlMulti, &count))
339 { 315 {
340 if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME) 316 if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME)
341 { 317 {
342 return false; 318 return false;
343 } 319 }
344 } 320 }
345 321
346 while(CURLMsg* curl_msg = curl_multi_info_read(mCurlMulti, &count)) 322 while(1)
347 { 323 {
348 if (CURLMSG_DONE == curl_msg->msg) 324 CURLcode result;
325 bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo);
326 if (newmsg)
349 { 327 {
350 if (curl_msg->data.result != CURLE_OK) 328 if (result != CURLE_OK)
351 { 329 {
352 setCurlStatus(curl_msg->data.result); 330 setCurlStatus(result);
353 llwarns << "LLXMLRPCTransaction CURL error " 331 llwarns << "LLXMLRPCTransaction CURL error "
354 << mCurlCode << ": " << mCurlErrorBuffer << llendl; 332 << mCurlCode << ": " << mCurlRequest->getErrorString() << llendl;
355 llwarns << "LLXMLRPCTransaction request URI: " 333 llwarns << "LLXMLRPCTransaction request URI: "
356 << mURI << llendl; 334 << mURI << llendl;
357 335
358 return true; 336 return true;
359 } 337 }
@@ -361,7 +339,7 @@ bool LLXMLRPCTransaction::Impl::process()
361 setStatus(LLXMLRPCTransaction::StatusComplete); 339 setStatus(LLXMLRPCTransaction::StatusComplete);
362 340
363 mResponse = XMLRPC_REQUEST_FromXML( 341 mResponse = XMLRPC_REQUEST_FromXML(
364 mResponseText.data(), mResponseText.size(), NULL); 342 mResponseText.data(), mResponseText.size(), NULL);
365 343
366 bool hasError = false; 344 bool hasError = false;
367 bool hasFault = false; 345 bool hasFault = false;
@@ -387,15 +365,19 @@ bool LLXMLRPCTransaction::Impl::process()
387 setStatus(LLXMLRPCTransaction::StatusXMLRPCError); 365 setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
388 366
389 llwarns << "LLXMLRPCTransaction XMLRPC " 367 llwarns << "LLXMLRPCTransaction XMLRPC "
390 << (hasError ? "error " : "fault ") 368 << (hasError ? "error " : "fault ")
391 << faultCode << ": " 369 << faultCode << ": "
392 << faultString << llendl; 370 << faultString << llendl;
393 llwarns << "LLXMLRPCTransaction request URI: " 371 llwarns << "LLXMLRPCTransaction request URI: "
394 << mURI << llendl; 372 << mURI << llendl;
395 } 373 }
396 374
397 return true; 375 return true;
398 } 376 }
377 else
378 {
379 break; // done
380 }
399 } 381 }
400 382
401 return false; 383 return false;
@@ -504,13 +486,13 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code)
504} 486}
505 487
506size_t LLXMLRPCTransaction::Impl::curlDownloadCallback( 488size_t LLXMLRPCTransaction::Impl::curlDownloadCallback(
507 void* data, size_t size, size_t nmemb, void* user_data) 489 char* data, size_t size, size_t nmemb, void* user_data)
508{ 490{
509 Impl& impl(*(Impl*)user_data); 491 Impl& impl(*(Impl*)user_data);
510 492
511 size_t n = size * nmemb; 493 size_t n = size * nmemb;
512 494
513 impl.mResponseText.append((const char*)data, n); 495 impl.mResponseText.append(data, n);
514 496
515 if (impl.mStatus == LLXMLRPCTransaction::StatusStarted) 497 if (impl.mStatus == LLXMLRPCTransaction::StatusStarted)
516 { 498 {
@@ -579,25 +561,17 @@ LLXMLRPCValue LLXMLRPCTransaction::responseValue()
579 561
580F64 LLXMLRPCTransaction::transferRate() 562F64 LLXMLRPCTransaction::transferRate()
581{ 563{
582 if (!impl.mCurl || impl.mStatus != StatusComplete) 564 if (impl.mStatus != StatusComplete)
583 { 565 {
584 return 0.0L; 566 return 0.0L;
585 } 567 }
586 568
587 double size_bytes = 0.0; 569 double rate_bits_per_sec = impl.mTransferInfo.mSpeedDownload * 8.0;
588 double time_seconds = 0.0;
589 double rate_bytes_per_sec = 0.0;
590
591 curl_easy_getinfo(impl.mCurl, CURLINFO_SIZE_DOWNLOAD, &size_bytes);
592 curl_easy_getinfo(impl.mCurl, CURLINFO_TOTAL_TIME, &time_seconds);
593 curl_easy_getinfo(impl.mCurl, CURLINFO_SPEED_DOWNLOAD, &rate_bytes_per_sec);
594
595 double rate_bits_per_sec = rate_bytes_per_sec * 8.0;
596 570
597 llinfos << "Buffer size: " << impl.mResponseText.size() << " B" << llendl; 571 llinfos << "Buffer size: " << impl.mResponseText.size() << " B" << llendl;
598 llinfos << "Transfer size: " << size_bytes << " B" << llendl; 572 llinfos << "Transfer size: " << impl.mTransferInfo.mSizeDownload << " B" << llendl;
599 llinfos << "Transfer time: " << time_seconds << " s" << llendl; 573 llinfos << "Transfer time: " << impl.mTransferInfo.mTotalTime << " s" << llendl;
600 llinfos << "Transfer rate: " << rate_bits_per_sec/1000.0 << " Kb/s" << llendl; 574 llinfos << "Transfer rate: " << rate_bits_per_sec / 1000.0 << " Kb/s" << llendl;
601 575
602 return rate_bits_per_sec; 576 return rate_bits_per_sec;
603} 577}