diff options
author | Jacek Antonelli | 2008-08-15 23:45:34 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:34 -0500 |
commit | cd17687f01420952712a500107e0f93e7ab8d5f8 (patch) | |
tree | ce48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/newview/llxmlrpctransaction.cpp | |
parent | Second Life viewer sources 1.19.0.5 (diff) | |
download | meta-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.cpp | 152 |
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 | { |
151 | public: | 151 | public: |
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 | ||
185 | private: | 182 | private: |
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 | ||
192 | LLXMLRPCTransaction::Impl::Impl(const std::string& uri, | 189 | LLXMLRPCTransaction::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 | ||
204 | LLXMLRPCTransaction::Impl::Impl(const std::string& uri, | 201 | LLXMLRPCTransaction::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 | ||
223 | void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) | 220 | void 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 | ||
310 | bool LLXMLRPCTransaction::Impl::process() | 287 | bool 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 | ||
506 | size_t LLXMLRPCTransaction::Impl::curlDownloadCallback( | 488 | size_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 | ||
580 | F64 LLXMLRPCTransaction::transferRate() | 562 | F64 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 | } |