Add improved timeout handling for HTTP transactions.

Introduces AIHTTPTimeoutPolicy objects which do not just
specify a single "timeout" in seconds, but a plethora of
timings related to the life cycle of the average HTTP
transaction.

This knowledge is that moved to the Responder being
used instead of floating constants hardcoded in the
callers of http requests. This assumes that the same
timeout policy is wanted for each transaction that
uses the same Responder, which can be enforced is needed.

I added a AIHTTPTimeoutPolicy for EVERY responder,
only to make it easier later to tune timeout values
and/or to get feedback about which responder runs
into HTTP errors in debug output (especially time outs),
so that they can be tuned later. If we already understood
exactly what we were doing then most responders could
have been left alone and just return the default timeout
policy: by far most timeout policies are just a copy
of the default policy, currently.

This commit is not finished... It's a work in progress
(viewer runs fine with it though).
This commit is contained in:
Aleric Inglewood
2012-10-05 15:53:29 +02:00
parent 2766f17cb9
commit 3f1fb9a66e
67 changed files with 1654 additions and 198 deletions

View File

@@ -56,8 +56,22 @@
#include "llproxy.h" #include "llproxy.h"
#include "llhttpstatuscodes.h" #include "llhttpstatuscodes.h"
#include "aihttpheaders.h" #include "aihttpheaders.h"
#include "aihttptimeoutpolicy.h"
#include "aicurleasyrequeststatemachine.h"
#ifdef CWDEBUG #ifdef CWDEBUG
#include <libcwd/buf2str.h> #include <libcwd/buf2str.h>
#include <sstream>
#define DoutCurlEasy(x) do { \
using namespace libcwd; \
std::ostringstream marker; \
marker << (void*)this->get_lockobj(); \
libcw_do.push_marker(); \
libcw_do.marker().assign(marker.str().data(), marker.str().size()); \
Dout(dc::curl, x); \
libcw_do.pop_marker(); \
} while(0)
#else
#define DoutCurlEasy(x) Dout(dc::curl, x << " [" << (void*)this->get_lockobj() << ']')
#endif #endif
//================================================================================== //==================================================================================
@@ -446,6 +460,11 @@ void Responder::setURL(std::string const& url)
mURL = url; mURL = url;
} }
AIHTTPTimeoutPolicy const& Responder::getHTTPTimeoutPolicy(void) const
{
return AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout();
}
// Called with HTML header. // Called with HTML header.
// virtual // virtual
void Responder::completedHeaders(U32, std::string const&, AIHTTPHeaders const&) void Responder::completedHeaders(U32, std::string const&, AIHTTPHeaders const&)
@@ -778,9 +797,9 @@ DEFINE_FUNCTION_SETOPT1(curl_debug_callback, CURLOPT_DEBUGFUNCTION)
DEFINE_FUNCTION_SETOPT4(curl_write_callback, CURLOPT_HEADERFUNCTION, CURLOPT_WRITEFUNCTION, CURLOPT_INTERLEAVEFUNCTION, CURLOPT_READFUNCTION) DEFINE_FUNCTION_SETOPT4(curl_write_callback, CURLOPT_HEADERFUNCTION, CURLOPT_WRITEFUNCTION, CURLOPT_INTERLEAVEFUNCTION, CURLOPT_READFUNCTION)
//DEFINE_FUNCTION_SETOPT1(curl_read_callback, CURLOPT_READFUNCTION) //DEFINE_FUNCTION_SETOPT1(curl_read_callback, CURLOPT_READFUNCTION)
DEFINE_FUNCTION_SETOPT1(curl_ssl_ctx_callback, CURLOPT_SSL_CTX_FUNCTION) DEFINE_FUNCTION_SETOPT1(curl_ssl_ctx_callback, CURLOPT_SSL_CTX_FUNCTION)
DEFINE_FUNCTION_SETOPT1(curl_progress_callback, CURLOPT_PROGRESSFUNCTION)
DEFINE_FUNCTION_SETOPT3(curl_conv_callback, CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPT_CONV_FROM_UTF8_FUNCTION) DEFINE_FUNCTION_SETOPT3(curl_conv_callback, CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPT_CONV_FROM_UTF8_FUNCTION)
#if 0 // Not used by the viewer. #if 0 // Not used by the viewer.
DEFINE_FUNCTION_SETOPT1(curl_progress_callback, CURLOPT_PROGRESSFUNCTION)
DEFINE_FUNCTION_SETOPT1(curl_seek_callback, CURLOPT_SEEKFUNCTION) DEFINE_FUNCTION_SETOPT1(curl_seek_callback, CURLOPT_SEEKFUNCTION)
DEFINE_FUNCTION_SETOPT1(curl_ioctl_callback, CURLOPT_IOCTLFUNCTION) DEFINE_FUNCTION_SETOPT1(curl_ioctl_callback, CURLOPT_IOCTLFUNCTION)
DEFINE_FUNCTION_SETOPT1(curl_sockopt_callback, CURLOPT_SOCKOPTFUNCTION) DEFINE_FUNCTION_SETOPT1(curl_sockopt_callback, CURLOPT_SOCKOPTFUNCTION)
@@ -805,7 +824,7 @@ void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size)
{ {
llassert_always(postdata->data()); llassert_always(postdata->data());
Dout(dc::curl, "POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\"."); DoutCurlEasy("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\".");
setPostField(postdata); // Make sure the data stays around until we don't need it anymore. setPostField(postdata); // Make sure the data stays around until we don't need it anymore.
setPost_raw(size, postdata->data()); setPost_raw(size, postdata->data());
@@ -816,7 +835,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data)
if (!data) if (!data)
{ {
// data == NULL when we're going to read the data using CURLOPT_READFUNCTION. // data == NULL when we're going to read the data using CURLOPT_READFUNCTION.
Dout(dc::curl, "POST size is " << size << " bytes."); DoutCurlEasy("POST size is " << size << " bytes.");
} }
// Accept everything (send an Accept-Encoding header containing all encodings we support (zlib and gzip)). // Accept everything (send an Accept-Encoding header containing all encodings we support (zlib and gzip)).
@@ -906,6 +925,24 @@ void CurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* us
setopt(CURLOPT_SSL_CTX_DATA, this); setopt(CURLOPT_SSL_CTX_DATA, this);
} }
//static
int CurlEasyRequest::progressCallback(void* userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
CurlEasyRequest* self = static_cast<CurlEasyRequest*>(userdata);
ThreadSafeCurlEasyRequest* lockobj = self->get_lockobj();
AICurlEasyRequest_wat lock_self(*lockobj);
return self->mProgressCallback(self->mProgressCallbackUserData, dltotal, dlnow, ultotal, ulnow);
}
void CurlEasyRequest::setProgressCallback(curl_progress_callback callback, void* userdata)
{
mProgressCallback = callback;
mProgressCallbackUserData = userdata;
setopt(CURLOPT_PROGRESSFUNCTION, callback ? &CurlEasyRequest::progressCallback : NULL);
setopt(CURLOPT_PROGRESSDATA, userdata ? this : NULL);
setopt(CURLOPT_NOPROGRESS, callback ? 0L: 1L);
}
#define llmaybewarns lllog(LLApp::isExiting() ? LLError::LEVEL_INFO : LLError::LEVEL_WARN, NULL, NULL, false, true) #define llmaybewarns lllog(LLApp::isExiting() ? LLError::LEVEL_INFO : LLError::LEVEL_WARN, NULL, NULL, false, true)
static size_t noHeaderCallback(char* ptr, size_t size, size_t nmemb, void* userdata) static size_t noHeaderCallback(char* ptr, size_t size, size_t nmemb, void* userdata)
@@ -932,12 +969,19 @@ static CURLcode noSSLCtxCallback(CURL* curl, void* sslctx, void* parm)
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
} }
static int noProgressCallback(void* userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
llmaybewarns << "Calling noProgressCallback(); curl session aborted." << llendl;
return CURLE_ABORTED_BY_CALLBACK;
}
void CurlEasyRequest::revokeCallbacks(void) void CurlEasyRequest::revokeCallbacks(void)
{ {
if (mHeaderCallback == &noHeaderCallback && if (mHeaderCallback == &noHeaderCallback &&
mWriteCallback == &noWriteCallback && mWriteCallback == &noWriteCallback &&
mReadCallback == &noReadCallback && mReadCallback == &noReadCallback &&
mSSLCtxCallback == &noSSLCtxCallback) mSSLCtxCallback == &noSSLCtxCallback &&
mProgressCallback == &noProgressCallback)
{ {
// Already revoked. // Already revoked.
return; return;
@@ -946,6 +990,7 @@ void CurlEasyRequest::revokeCallbacks(void)
mWriteCallback = &noWriteCallback; mWriteCallback = &noWriteCallback;
mReadCallback = &noReadCallback; mReadCallback = &noReadCallback;
mSSLCtxCallback = &noSSLCtxCallback; mSSLCtxCallback = &noSSLCtxCallback;
mProgressCallback = &noProgressCallback;
if (active() && !no_warning()) if (active() && !no_warning())
{ {
llwarns << "Revoking callbacks on a still active CurlEasyRequest object!" << llendl; llwarns << "Revoking callbacks on a still active CurlEasyRequest object!" << llendl;
@@ -954,6 +999,7 @@ void CurlEasyRequest::revokeCallbacks(void)
curl_easy_setopt(getEasyHandle(), CURLOPT_WRITEHEADER, &noWriteCallback); curl_easy_setopt(getEasyHandle(), CURLOPT_WRITEHEADER, &noWriteCallback);
curl_easy_setopt(getEasyHandle(), CURLOPT_READFUNCTION, &noReadCallback); curl_easy_setopt(getEasyHandle(), CURLOPT_READFUNCTION, &noReadCallback);
curl_easy_setopt(getEasyHandle(), CURLOPT_SSL_CTX_FUNCTION, &noSSLCtxCallback); curl_easy_setopt(getEasyHandle(), CURLOPT_SSL_CTX_FUNCTION, &noSSLCtxCallback);
curl_easy_setopt(getEasyHandle(), CURLOPT_PROGRESSFUNCTION, &noProgressCallback);
} }
CurlEasyRequest::~CurlEasyRequest() CurlEasyRequest::~CurlEasyRequest()
@@ -1167,8 +1213,8 @@ void CurlEasyRequest::applyDefaultOptions(void)
setoptString(CURLOPT_CAINFO, CertificateAuthority_r->file); setoptString(CURLOPT_CAINFO, CertificateAuthority_r->file);
setSSLCtxCallback(&curlCtxCallback, NULL); setSSLCtxCallback(&curlCtxCallback, NULL);
setopt(CURLOPT_NOSIGNAL, 1); setopt(CURLOPT_NOSIGNAL, 1);
// The old code did this for the 'buffered' version, but I think it's nonsense. // Cache DNS look ups an hour. If we set it smaller we risk frequent connect timeouts in cases where DNS look ups are slow.
//setopt(CURLOPT_DNS_CACHE_TIMEOUT, 0); setopt(CURLOPT_DNS_CACHE_TIMEOUT, 3600);
// Disable SSL/TLS session caching; some servers (aka id.secondlife.com) refuse connections when session ids are enabled. // Disable SSL/TLS session caching; some servers (aka id.secondlife.com) refuse connections when session ids are enabled.
setopt(CURLOPT_SSL_SESSIONID_CACHE, 0); setopt(CURLOPT_SSL_SESSIONID_CACHE, 0);
// Set the CURL options for either SOCKS or HTTP proxy. // Set the CURL options for either SOCKS or HTTP proxy.
@@ -1184,7 +1230,7 @@ void CurlEasyRequest::applyDefaultOptions(void)
); );
} }
void CurlEasyRequest::finalizeRequest(std::string const& url) void CurlEasyRequest::finalizeRequest(std::string const& url, AIHTTPTimeoutPolicy const& policy, AICurlEasyRequestStateMachine* state_machine)
{ {
llassert(!mRequestFinalized); llassert(!mRequestFinalized);
mResult = CURLE_FAILED_INIT; // General error code; the final result code is stored here by MultiHandle::check_run_count when msg is CURLMSG_DONE. mResult = CURLE_FAILED_INIT; // General error code; the final result code is stored here by MultiHandle::check_run_count when msg is CURLMSG_DONE.
@@ -1207,6 +1253,8 @@ void CurlEasyRequest::finalizeRequest(std::string const& url)
mRequestFinalized = true; mRequestFinalized = true;
setopt(CURLOPT_HTTPHEADER, mHeaders); setopt(CURLOPT_HTTPHEADER, mHeaders);
setoptString(CURLOPT_URL, url); setoptString(CURLOPT_URL, url);
mTimeoutPolicy = &policy;
state_machine->setTotalDelayTimeout(policy.getTotalDelay());
// The following line is a bit tricky: we store a pointer to the object without increasing its reference count. // The following line is a bit tricky: we store a pointer to the object without increasing its reference count.
// Of course we could increment the reference count, but that doesn't help much: if then this pointer would // Of course we could increment the reference count, but that doesn't help much: if then this pointer would
// get "lost" we'd have a memory leak. Either way we must make sure that it is impossible that this pointer // get "lost" we'd have a memory leak. Either way we must make sure that it is impossible that this pointer
@@ -1224,6 +1272,208 @@ void CurlEasyRequest::finalizeRequest(std::string const& url)
setopt(CURLOPT_PRIVATE, get_lockobj()); setopt(CURLOPT_PRIVATE, get_lockobj());
} }
//.............................................................................
// HTTP Timeout stuff
// url must be of the form
// (see http://www.ietf.org/rfc/rfc3986.txt Appendix A for definitions not given here):
//
// url = sheme ":" hier-part [ "?" query ] [ "#" fragment ]
// hier-part = "//" authority path-abempty
// authority = [ userinfo "@" ] host [ ":" port ]
// path-abempty = *( "/" segment )
//
// That is, a hier-part of the form '/ path-absolute', '/ path-rootless' or
// '/ path-empty' is NOT allowed here. This should be safe because we only
// call this function for curl access, any file access would use APR.
//
// However, as a special exception, this function allows:
//
// url = authority path-abempty
//
// without the 'sheme ":" "//"' parts.
//
// As follows from the ABNF (see RFC, Appendix A):
// - authority is either terminated by a '/' or by the end of the string because
// neither userinfo, host nor port may contain a '/'.
// - userinfo does not contain a '@', and if it exists, is always terminated by a '@'.
// - port does not contain a ':', and if it exists is always prepended by a ':'.
//
// Only called by CurlEasyRequest::timeout_add_easy_request.
static std::string extract_canonical_hostname(std::string url)
{
std::string::size_type pos;
std::string::size_type authority = 0; // Default if there is no sheme.
if ((pos = url.find("://")) != url.npos && pos < url.find('/')) authority = pos + 3; // Skip the "sheme://" if any, the second find is to avoid finding a "://" as part of path-abempty.
std::string::size_type host = authority; // Default if there is no userinfo.
if ((pos = url.find('@', authority)) != url.npos) host = pos + 1; // Skip the "userinfo@" if any.
authority = url.length() - 1; // Default last character of host if there is no path-abempty.
if ((pos = url.find('/', host)) != url.npos) authority = pos - 1; // Point to last character of host.
std::string::size_type len = url.find_last_not_of(":0123456789", authority) - host + 1; // Skip trailing ":port", if any.
std::string hostname(url, host, len);
#if APR_CHARSET_EBCDIC
#error Not implemented
#else
// Convert hostname to lowercase in a way that we compare two hostnames equal iff libcurl does.
for (std::string::iterator iter = hostname.begin(); iter != hostname.end(); ++iter)
{
int c = *iter;
if (c >= 'A' && c <= 'Z')
*iter = c + ('a' - 'A');
}
#endif
return hostname;
}
// CURL-THREAD
// This is called when the easy handle is actually being added to the multi handle (thus after being queued).
void CurlEasyRequest::timeout_add_easy_request(void)
{
char* eff_url;
getinfo(CURLINFO_EFFECTIVE_URL, &eff_url); // According to a discussion on IRC with a curl developer, we can rely on this returning the set CURLOPT_URL at this point.
setopt(CURLOPT_CONNECTTIMEOUT, mTimeoutPolicy->getConnectTimeout(extract_canonical_hostname(eff_url)));
setopt(CURLOPT_TIMEOUT, mTimeoutPolicy->getCurlTransaction());
// We do NOT use CURLOPT_LOW_SPEED_TIME and CURLOPT_LOW_SPEED_LIMIT,
// instead use a progress meter callback.
setProgressCallback(&AICurlPrivate::CurlEasyRequest::timeout_progress, this);
// This boolean is valid (only) if we get a time out event from libcurl.
mTimeoutConnected = false;
}
// CURL-THREAD
// This is called when the connection succeeded (thus after DNS lookup and connect).
void CurlEasyRequest::timeout_connected(void)
{
DoutCurlEasy("Calling CurlEasyRequest::timeout_connected(): mTimeoutWaitingForReply = false");
mTimeoutConnected = true;
#ifdef CWDEBUG
mTimeout_connect_time = get_clock_count();
#endif
// Now that mTimeoutConnected is set we'll be calling timeout_progress(); initialize the variables used there.
mTimeout_dlnow = 0;
mTimeout_ulnow = 0;
mTimeout_progress_time = 0;
mTimeoutWaitingForReply = false;
mTimeoutNothingReceivedYet = true;
}
// CURL-THREAD
// This is called when data was sent to the server socket.
void CurlEasyRequest::timeout_data_sent(size_t n)
{
if (!mTimeoutConnected)
{
// If we can send data (for the first time) then that's our way to know we connected.
timeout_connected();
}
}
// CURL-THREAD
// This is called when data was received from the server.
void CurlEasyRequest::timeout_data_received(size_t n)
{
if (n > 0)
{
#ifdef CWDEBUG
if (mTimeoutNothingReceivedYet)
DoutCurlEasy("CurlEasyRequest::timeout_data_received(): Received data from server: set mTimeoutWaitingForReply = false");
#endif
// We received something, now switch to getLowSpeedLimit()/getLowSpeedTime().
mTimeoutWaitingForReply = false;
mTimeoutNothingReceivedYet = false;
}
}
// CURL_THREAD
//static
int CurlEasyRequest::timeout_progress(void* userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
CurlEasyRequest* self = static_cast<CurlEasyRequest*>(userdata);
//AIFIXME: There has to be a better way to determine this (because it feels fuzzy, I only allow it to SET the boolean):
#ifdef CWDEBUG
if (!self->mTimeoutWaitingForReply && (self->mTimeoutNothingReceivedYet && ultotal > 0 && ulnow == ultotal))
Dout(dc::curl, "CurlEasyRequest::timeout_progress(): uploading data finished: set mTimeoutWaitingForReply = true [" << (void*)self->get_lockobj() << ']');
#endif
llassert(ulnow == 0 || ultotal > 0); // Do we always know the total upload size?
self->mTimeoutWaitingForReply = self->mTimeoutWaitingForReply || (self->mTimeoutNothingReceivedYet && ultotal > 0 && ulnow == ultotal);
return self->mTimeoutConnected ? self->timeout_progress(dlnow, ulnow) : 0;
}
// CURL_THREAD
// dlnow is the number of bytes of the BODY of the message, received from the server.
// ulnow is the number of bytes of the BODY of the message, sent to the server so far.
//
// Note that the algorithm used here is basically the same as libcurl uses
// for CURLOPT_LOW_SPEED_LIMIT / CURLOPT_LOW_SPEED_TIME, but we can't use that
// because we need to change the variables involved during transfer, which isn't
// officially supported by libcurl.
// Libcurl does the progress callback at the exact same point as checking for
// low speed, and the same data is passed (except the time, unfortunately), so
// the functionality is the same.
int CurlEasyRequest::timeout_progress(double dlnow, double ulnow)
{
static double const clock_frequency = calc_clock_frequency();
U64 last_time = mTimeout_progress_time;
mTimeout_progress_time = get_clock_count();
double transfer = (dlnow - mTimeout_dlnow) + (ulnow - mTimeout_ulnow); // Just combine up and download :p.
mTimeout_dlnow = dlnow;
mTimeout_ulnow = ulnow;
if (!last_time || mTimeout_progress_time == last_time) // Is this the first time this function is called (or are we called infinitely fast)?
{
DoutCurlEasy("timeout_progress(" << dlnow << ", " << ulnow << ") called at " <<
((mTimeout_progress_time - mTimeout_connect_time) / clock_frequency) << " seconds after connect" <<
(last_time ? "" : " (first time)"));
// Start the timer: we need to have a too low transfer rate, for at least
// mTimeoutPolicy->getLowSpeedTime() seconds, counting from this moment.
mTransferOK = mTimeout_progress_time;
return 0;
}
transfer *= clock_frequency / (mTimeout_progress_time - last_time); // Bytes per second.
U64 timer = mTimeout_progress_time - mTransferOK; // Low speed timer in clock ticks.
U16 lowspeedtime = mTimeoutWaitingForReply ? mTimeoutPolicy->getReplyDelay() : mTimeoutPolicy->getLowSpeedTime();
U32 lowspeedlimit = mTimeoutWaitingForReply ? (U32)1 : mTimeoutPolicy->getLowSpeedLimit();
DoutCurlEasy("timeout_progress(" << dlnow << ", " << ulnow << ") called at " << ((mTimeout_progress_time - mTimeout_connect_time) / clock_frequency) <<
" seconds after connect (timer = " << (timer / clock_frequency) << " s ; transfer = " << transfer << " bytes/s; lowspeedtime = " << lowspeedtime <<
"; lowspeedlimit = " << lowspeedlimit << " (mTimeoutWaitingForReply == " << (mTimeoutWaitingForReply ? "true" : "false") << "))");
if (transfer >= lowspeedlimit)
{
// Yay! Transfer rate is OK; restart timeout timer.
mTransferOK = mTimeout_progress_time;
}
else if (timer > clock_frequency * lowspeedtime)
{
// We haven't seen a high enough transfer rate for too long. Abort the transfer.
llwarns <<
#ifdef CWDEBUG
(void*)get_lockobj() << ": "
#endif
"aborting slow connection (transfer rate below " << lowspeedlimit <<
" for more than " << lowspeedtime << " second" << ((lowspeedtime == 1) ? "" : "s") << ")." << llendl;
return 1;
}
return 0;
}
// CURL-THREAD
// This is called immediately before done() after curl finished, with code.
void CurlEasyRequest::timeout_done(CURLcode code)
{
if (code == CURLE_OPERATION_TIMEDOUT && !mTimeoutConnected)
{
char* eff_url;
getinfo(CURLINFO_EFFECTIVE_URL, &eff_url); //AIFIXME: cache hostname, cause this might have changed.
AIHTTPTimeoutPolicy::connect_timed_out(extract_canonical_hostname(eff_url));
// AIFIXME: use return value to change priority
}
// Abuse this boolean to tell any subsequent call to timeout_progress that this certainly can't timeout anymore.
mTimeoutConnected = false;
}
// End of HTTP Timeout stuff.
//.............................................................................
void CurlEasyRequest::getTransferInfo(AICurlInterface::TransferInfo* info) void CurlEasyRequest::getTransferInfo(AICurlInterface::TransferInfo* info)
{ {
// Curl explicitly demands a double for these info's. // Curl explicitly demands a double for these info's.
@@ -1268,8 +1518,6 @@ void CurlEasyRequest::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy
// CurlResponderBuffer // CurlResponderBuffer
static int const HTTP_REDIRECTS_DEFAULT = 10; static int const HTTP_REDIRECTS_DEFAULT = 10;
static S32 const CURL_REQUEST_TIMEOUT = 30; // The minimum value of the CURLOPT_TIMEOUT option (which is the maximum
// time in seconds that we allow a libcurl transfer operation to take).
LLChannelDescriptors const CurlResponderBuffer::sChannels; LLChannelDescriptors const CurlResponderBuffer::sChannels;
@@ -1334,7 +1582,7 @@ ThreadSafeBufferedCurlEasyRequest* CurlResponderBuffer::get_lockobj(void)
return static_cast<ThreadSafeBufferedCurlEasyRequest*>(AIThreadSafeSimple<CurlResponderBuffer>::wrapper_cast(this)); return static_cast<ThreadSafeBufferedCurlEasyRequest*>(AIThreadSafeSimple<CurlResponderBuffer>::wrapper_cast(this));
} }
void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w, AIHTTPHeaders const& headers, AICurlInterface::ResponderPtr responder, S32 time_out) void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w, AIHTTPHeaders const& headers, AICurlInterface::ResponderPtr responder)
{ {
mInput.reset(new LLBufferArray); mInput.reset(new LLBufferArray);
mInput->setThreaded(true); mInput->setThreaded(true);
@@ -1359,8 +1607,6 @@ void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w
// Don't verify host name so urls with scrubbed host names will work (improves DNS performance). // Don't verify host name so urls with scrubbed host names will work (improves DNS performance).
curl_easy_request_w->setopt(CURLOPT_SSL_VERIFYHOST, 0); curl_easy_request_w->setopt(CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_request_w->setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
// Keep responder alive. // Keep responder alive.
mResponder = responder; mResponder = responder;
// Send header events to responder if needed. // Send header events to responder if needed.
@@ -1387,7 +1633,8 @@ size_t CurlResponderBuffer::curlWriteCallback(char* data, size_t size, size_t nm
// CurlResponderBuffer::setBodyLimit is never called, so buffer_w->mBodyLimit is infinite. // CurlResponderBuffer::setBodyLimit is never called, so buffer_w->mBodyLimit is infinite.
//S32 bytes = llmin(size * nmemb, buffer_w->mBodyLimit); buffer_w->mBodyLimit -= bytes; //S32 bytes = llmin(size * nmemb, buffer_w->mBodyLimit); buffer_w->mBodyLimit -= bytes;
buffer_w->getOutput()->append(sChannels.in(), (U8 const*)data, bytes); buffer_w->getOutput()->append(sChannels.in(), (U8 const*)data, bytes);
buffer_w->mResponseTransferedBytes += bytes; // Accumulate data received from the server. buffer_w->mResponseTransferedBytes += bytes; // Accumulate data received from the server.
buffered_easy_request_w->timeout_data_received(bytes); // Timeout administration.
return bytes; return bytes;
} }
@@ -1403,7 +1650,8 @@ size_t CurlResponderBuffer::curlReadCallback(char* data, size_t size, size_t nme
S32 bytes = size * nmemb; // The maximum amount to read. S32 bytes = size * nmemb; // The maximum amount to read.
AICurlResponderBuffer_wat buffer_w(*lockobj); AICurlResponderBuffer_wat buffer_w(*lockobj);
buffer_w->mLastRead = buffer_w->getInput()->readAfter(sChannels.out(), buffer_w->mLastRead, (U8*)data, bytes); buffer_w->mLastRead = buffer_w->getInput()->readAfter(sChannels.out(), buffer_w->mLastRead, (U8*)data, bytes);
buffer_w->mRequestTransferedBytes += bytes; // Accumulate data sent to the server. buffer_w->mRequestTransferedBytes += bytes; // Accumulate data sent to the server.
buffered_easy_request_w->timeout_data_sent(bytes); // Timeout administration.
return bytes; // Return the amount actually read (might be lowered by readAfter()). return bytes; // Return the amount actually read (might be lowered by readAfter()).
} }
@@ -1420,6 +1668,7 @@ size_t CurlResponderBuffer::curlHeaderCallback(char* data, size_t size, size_t n
char const* const header_line = static_cast<char const*>(data); char const* const header_line = static_cast<char const*>(data);
size_t const header_len = size * nmemb; size_t const header_len = size * nmemb;
buffered_easy_request_w->timeout_data_received(header_len); // Timeout administration.
if (!header_len) if (!header_len)
{ {
@@ -1504,7 +1753,7 @@ void CurlResponderBuffer::finished(AICurlEasyRequest_wat& curl_easy_request_w)
void CurlResponderBuffer::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) void CurlResponderBuffer::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w)
{ {
Dout(dc::curl, "Calling CurlResponderBuffer::removed_from_multi_handle(@" << (void*)&*curl_easy_request_w << ") for this = " << (void*)this); DoutCurlEasy("Calling CurlResponderBuffer::removed_from_multi_handle(@" << (void*)&*curl_easy_request_w << ") for this = " << (void*)this);
// Lock self. // Lock self.
ThreadSafeBufferedCurlEasyRequest* lockobj = get_lockobj(); ThreadSafeBufferedCurlEasyRequest* lockobj = get_lockobj();

View File

@@ -57,6 +57,7 @@
class LLSD; class LLSD;
class LLBufferArray; class LLBufferArray;
class LLChannelDescriptors; class LLChannelDescriptors;
class AIHTTPTimeoutPolicy;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Exceptions. // Exceptions.
@@ -210,6 +211,9 @@ class Responder : public AICurlResponderBufferEvents {
// Derived classes that implement completedHeaders() should return true here. // Derived classes that implement completedHeaders() should return true here.
virtual bool needsHeaders(void) const { return false; } virtual bool needsHeaders(void) const { return false; }
// Timeout policy to use.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
// Derived classes can override this to get the raw data of the body of the HTML message that was received. // Derived classes can override this to get the raw data of the body of the HTML message that was received.
// The default is to interpret the content as LLSD and call completed(). // The default is to interpret the content as LLSD and call completed().
virtual void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); virtual void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer);

View File

@@ -30,6 +30,7 @@
#include "linden_common.h" #include "linden_common.h"
#include "aicurleasyrequeststatemachine.h" #include "aicurleasyrequeststatemachine.h"
#include "aihttptimeoutpolicy.h"
#include "llcontrol.h" #include "llcontrol.h"
enum curleasyrequeststatemachine_state_type { enum curleasyrequeststatemachine_state_type {
@@ -61,7 +62,7 @@ void AICurlEasyRequestStateMachine::initialize_impl(void)
{ {
{ {
AICurlEasyRequest_wat curlEasyRequest_w(*mCurlEasyRequest); AICurlEasyRequest_wat curlEasyRequest_w(*mCurlEasyRequest);
llassert(curlEasyRequest_w->is_finalized()); // Call finalizeRequest(url) before calling run(). llassert(curlEasyRequest_w->is_finalized()); // Call finalizeRequest() before calling run().
curlEasyRequest_w->send_events_to(this); curlEasyRequest_w->send_events_to(this);
} }
mAdded = false; mAdded = false;
@@ -116,13 +117,13 @@ void AICurlEasyRequestStateMachine::multiplex_impl(void)
// 3) AICurlEasyRequestStateMachine_finished (running) // 3) AICurlEasyRequestStateMachine_finished (running)
// 4) AICurlEasyRequestStateMachine_removed_after_finished (running) // 4) AICurlEasyRequestStateMachine_removed_after_finished (running)
if (mRequestTimeOut > 0.f) if (mTotalDelayTimeout > 0.f)
{ {
// Set an inactivity timer. // Set an inactivity timer.
// This shouldn't really be necessary, except in the case of a bug // This shouldn't really be necessary, except in the case of a bug
// in libcurl; but lets be sure and set a timer for inactivity. // in libcurl; but lets be sure and set a timer for inactivity.
mTimer = new AIPersistentTimer; // Do not delete timer upon expiration. mTimer = new AIPersistentTimer; // Do not delete timer upon expiration.
mTimer->setInterval(mRequestTimeOut); mTimer->setInterval(mTotalDelayTimeout);
mTimer->run(this, AICurlEasyRequestStateMachine_timedOut, false, false); mTimer->run(this, AICurlEasyRequestStateMachine_timedOut, false, false);
} }
break; break;
@@ -246,7 +247,7 @@ void AICurlEasyRequestStateMachine::finish_impl(void)
} }
AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(bool buffered) : AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(bool buffered) :
mBuffered(buffered), mCurlEasyRequest(buffered), mTimer(NULL), mRequestTimeOut(sCurlRequestTimeOut) mBuffered(buffered), mCurlEasyRequest(buffered), mTimer(NULL), mTotalDelayTimeout(AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout().getTotalDelay())
{ {
Dout(dc::statemachine, "Calling AICurlEasyRequestStateMachine(" << (buffered ? "true" : "false") << ") [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]"); Dout(dc::statemachine, "Calling AICurlEasyRequestStateMachine(" << (buffered ? "true" : "false") << ") [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
if (!mBuffered) if (!mBuffered)
@@ -255,18 +256,9 @@ AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(bool buffered) :
} }
} }
//static void AICurlEasyRequestStateMachine::setTotalDelayTimeout(F32 totalDelayTimeout)
F32 AICurlEasyRequestStateMachine::sCurlRequestTimeOut = 40.f;
//static
void AICurlEasyRequestStateMachine::setDefaultRequestTimeOut(F32 defaultRequestTimeOut)
{ {
sCurlRequestTimeOut = defaultRequestTimeOut; mTotalDelayTimeout = totalDelayTimeout;
}
void AICurlEasyRequestStateMachine::setRequestTimeOut(F32 curlRequestTimeOut)
{
mRequestTimeOut = curlRequestTimeOut;
} }
AICurlEasyRequestStateMachine::~AICurlEasyRequestStateMachine() AICurlEasyRequestStateMachine::~AICurlEasyRequestStateMachine()

View File

@@ -64,16 +64,11 @@ class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHa
bool mFinished; // Set by the curl thread to signal it finished. bool mFinished; // Set by the curl thread to signal it finished.
bool mHandled; // Set when we processed the received data. bool mHandled; // Set when we processed the received data.
AITimer* mTimer; // Expiration timer. AITimer* mTimer; // Expiration timer.
F32 mRequestTimeOut; // The time out value for mTimer. F32 mTotalDelayTimeout; // The time out value for mTimer.
static F32 sCurlRequestTimeOut; // The default time out value for mTimer (CurlRequestTimeOut debug setting).
public: public:
// Called once to set a different timeout then the default of 40 seconds.
static void setDefaultRequestTimeOut(F32 defaultRequestTimeOut);
// Called to set a specific time out, instead of the default one. // Called to set a specific time out, instead of the default one.
void setRequestTimeOut(F32 requestTimeOut); void setTotalDelayTimeout(F32 totalDelayTimeout);
protected: protected:
// AICurlEasyRequest Events. // AICurlEasyRequest Events.

View File

@@ -35,6 +35,8 @@
#include "llatomic.h" #include "llatomic.h"
class AIHTTPHeaders; class AIHTTPHeaders;
class AIHTTPTimeoutPolicy;
class AICurlEasyRequestStateMachine;
namespace AICurlPrivate { namespace AICurlPrivate {
namespace curlthread { class MultiHandle; } namespace curlthread { class MultiHandle; }
@@ -87,9 +89,9 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
DECLARE_SETOPT(curl_write_callback); DECLARE_SETOPT(curl_write_callback);
//DECLARE_SETOPT(curl_read_callback); Same type as curl_write_callback //DECLARE_SETOPT(curl_read_callback); Same type as curl_write_callback
DECLARE_SETOPT(curl_ssl_ctx_callback); DECLARE_SETOPT(curl_ssl_ctx_callback);
DECLARE_SETOPT(curl_progress_callback);
DECLARE_SETOPT(curl_conv_callback); DECLARE_SETOPT(curl_conv_callback);
#if 0 // Not used by the viewer. #if 0 // Not used by the viewer.
DECLARE_SETOPT(curl_progress_callback);
DECLARE_SETOPT(curl_seek_callback); DECLARE_SETOPT(curl_seek_callback);
DECLARE_SETOPT(curl_ioctl_callback); DECLARE_SETOPT(curl_ioctl_callback);
DECLARE_SETOPT(curl_sockopt_callback); DECLARE_SETOPT(curl_sockopt_callback);
@@ -225,6 +227,7 @@ class CurlEasyRequest : public CurlEasyHandle {
static size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* userdata); static size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* userdata);
static size_t readCallback(char* ptr, size_t size, size_t nmemb, void* userdata); static size_t readCallback(char* ptr, size_t size, size_t nmemb, void* userdata);
static CURLcode SSLCtxCallback(CURL* curl, void* sslctx, void* userdata); static CURLcode SSLCtxCallback(CURL* curl, void* sslctx, void* userdata);
static int progressCallback(void* clientp, double dltotal, double dlnow, double ultotal, double ulnow);
curl_write_callback mHeaderCallback; curl_write_callback mHeaderCallback;
void* mHeaderCallbackUserData; void* mHeaderCallbackUserData;
@@ -234,12 +237,15 @@ class CurlEasyRequest : public CurlEasyHandle {
void* mReadCallbackUserData; void* mReadCallbackUserData;
curl_ssl_ctx_callback mSSLCtxCallback; curl_ssl_ctx_callback mSSLCtxCallback;
void* mSSLCtxCallbackUserData; void* mSSLCtxCallbackUserData;
curl_progress_callback mProgressCallback;
void* mProgressCallbackUserData;
public: public:
void setHeaderCallback(curl_write_callback callback, void* userdata); void setHeaderCallback(curl_write_callback callback, void* userdata);
void setWriteCallback(curl_write_callback callback, void* userdata); void setWriteCallback(curl_write_callback callback, void* userdata);
void setReadCallback(curl_read_callback callback, void* userdata); void setReadCallback(curl_read_callback callback, void* userdata);
void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata); void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
void setProgressCallback(curl_progress_callback callback, void* userdata);
// Call this if the set callbacks are about to be invalidated. // Call this if the set callbacks are about to be invalidated.
void revokeCallbacks(void); void revokeCallbacks(void);
@@ -260,7 +266,26 @@ class CurlEasyRequest : public CurlEasyHandle {
// Prepare the request for adding it to a multi session, or calling perform. // Prepare the request for adding it to a multi session, or calling perform.
// This actually adds the headers that were collected with addHeader. // This actually adds the headers that were collected with addHeader.
void finalizeRequest(std::string const& url); void finalizeRequest(std::string const& url, AIHTTPTimeoutPolicy const& policy, AICurlEasyRequestStateMachine* state_machine);
// Called by MultiHandle::add_easy_request when the easy handle is actually being added to the multi handle.
void timeout_add_easy_request(void);
// Called when data was written the first time, meaning that the connection succeeded.
void timeout_connected(void);
// Called when data is sent.
void timeout_data_sent(size_t n);
// Called when data is received.
void timeout_data_received(size_t n);
// Called immediately before done() after curl finished, with code.
void timeout_done(CURLcode code);
// Progress meter callback.
static int timeout_progress(void* userdata, double dltotal, double dlnow, double ultotal, double ulnow);
int timeout_progress(double dlnow, double ulnow);
// Called by MultiHandle::check_run_count() to store result code that is returned by getResult. // Called by MultiHandle::check_run_count() to store result code that is returned by getResult.
void store_result(CURLcode result) { mResult = result; } void store_result(CURLcode result) { mResult = result; }
@@ -280,12 +305,25 @@ class CurlEasyRequest : public CurlEasyHandle {
AICurlEasyHandleEvents* mEventsTarget; AICurlEasyHandleEvents* mEventsTarget;
CURLcode mResult; CURLcode mResult;
// AIFIXME: put all timeout stuff in it's own class.
AIHTTPTimeoutPolicy const* mTimeoutPolicy;
bool mTimeoutConnected; // Set if we succeeded to connect and are transfering data.
#ifdef CWDEBUG
U64 mTimeout_connect_time; // Time at which mTimeoutConnected was set to true (for debugging purposes only).
#endif
bool mTimeoutWaitingForReply; // Set after we finished sending data to the server and are waiting for the reply.
bool mTimeoutNothingReceivedYet; // Set when connected, reset when the HTML reply header from the server is received.
U64 mTimeout_progress_time; // The (last) time timeout_progress() was called, in microseconds.
U64 mTransferOK; // The last time the transfer rate was OK.
double mTimeout_dlnow; // Number of downloaded bytes so far, as per last call to timeout_progress.
double mTimeout_ulnow; // Number of uploaded bytes so far, as per last call to timeout_progress.
private: private:
// This class may only be created by constructing a ThreadSafeCurlEasyRequest. // This class may only be created by constructing a ThreadSafeCurlEasyRequest.
friend class ThreadSafeCurlEasyRequest; friend class ThreadSafeCurlEasyRequest;
// Throws AICurlNoEasyHandle. // Throws AICurlNoEasyHandle.
CurlEasyRequest(void) : CurlEasyRequest(void) :
mHeaders(NULL), mRequestFinalized(false), mEventsTarget(NULL), mResult(CURLE_FAILED_INIT) mHeaders(NULL), mRequestFinalized(false), mEventsTarget(NULL), mResult(CURLE_FAILED_INIT), mTimeoutPolicy(NULL)
{ applyDefaultOptions(); } { applyDefaultOptions(); }
public: public:
~CurlEasyRequest(); ~CurlEasyRequest();
@@ -327,7 +365,7 @@ class CurlResponderBuffer : protected AICurlResponderBufferEvents, protected AIC
typedef AICurlInterface::Responder::buffer_ptr_t buffer_ptr_t; typedef AICurlInterface::Responder::buffer_ptr_t buffer_ptr_t;
void resetState(AICurlEasyRequest_wat& curl_easy_request_w); void resetState(AICurlEasyRequest_wat& curl_easy_request_w);
void prepRequest(AICurlEasyRequest_wat& buffered_curl_easy_request_w, AIHTTPHeaders const& headers, AICurlInterface::ResponderPtr responder, S32 time_out = 0); void prepRequest(AICurlEasyRequest_wat& buffered_curl_easy_request_w, AIHTTPHeaders const& headers, AICurlInterface::ResponderPtr responder);
buffer_ptr_t& getInput(void) { return mInput; } buffer_ptr_t& getInput(void) { return mInput; }
buffer_ptr_t& getOutput(void) { return mOutput; } buffer_ptr_t& getOutput(void) { return mOutput; }

View File

@@ -1382,7 +1382,12 @@ char const* action_str(int action)
//static //static
int MultiHandle::socket_callback(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp) int MultiHandle::socket_callback(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp)
{ {
DoutEntering(dc::curl, "MultiHandle::socket_callback((CURL*)" << (void*)easy << ", " << s << ", " << action_str(action) << ", " << (void*)userp << ", " << (void*)socketp << ")"); #ifdef CWDEBUG
ThreadSafeCurlEasyRequest* lockobj = NULL;
curl_easy_getinfo(easy, CURLINFO_PRIVATE, &lockobj);
DoutEntering(dc::curl, "MultiHandle::socket_callback((CURL*)" << (void*)easy << ", " << s <<
", " << action_str(action) << ", " << (void*)userp << ", " << (void*)socketp << ") [CURLINFO_PRIVATE = " << (void*)lockobj << "]");
#endif
MultiHandle& self = *static_cast<MultiHandle*>(userp); MultiHandle& self = *static_cast<MultiHandle*>(userp);
CurlSocketInfo* sock_info = static_cast<CurlSocketInfo*>(socketp); CurlSocketInfo* sock_info = static_cast<CurlSocketInfo*>(socketp);
if (action == CURL_POLL_REMOVE) if (action == CURL_POLL_REMOVE)
@@ -1449,6 +1454,7 @@ void MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request)
CURLMcode ret; CURLMcode ret;
{ {
AICurlEasyRequest_wat curl_easy_request_w(*easy_request); AICurlEasyRequest_wat curl_easy_request_w(*easy_request);
curl_easy_request_w->timeout_add_easy_request();
ret = curl_easy_request_w->add_handle_to_multi(curl_easy_request_w, mMultiHandle); ret = curl_easy_request_w->add_handle_to_multi(curl_easy_request_w, mMultiHandle);
} }
if (ret == CURLM_OK) if (ret == CURLM_OK)
@@ -1456,7 +1462,7 @@ void MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request)
mHandleAddedOrRemoved = true; mHandleAddedOrRemoved = true;
std::pair<addedEasyRequests_type::iterator, bool> res = mAddedEasyRequests.insert(easy_request); std::pair<addedEasyRequests_type::iterator, bool> res = mAddedEasyRequests.insert(easy_request);
llassert(res.second); // May not have been added before. llassert(res.second); // May not have been added before.
Dout(dc::curl, "MultiHandle::add_easy_request: Added AICurlEasyRequest " << (void*)easy_request.get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); Dout(dc::curl, "MultiHandle::add_easy_request: Added AICurlEasyRequest " << (void*)easy_request.get_ptr().get() << "; now processing " << mAddedEasyRequests.size() << " easy handles.");
return; return;
} }
} }
@@ -1506,7 +1512,7 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request
} }
mAddedEasyRequests.erase(iter); mAddedEasyRequests.erase(iter);
mHandleAddedOrRemoved = true; mHandleAddedOrRemoved = true;
Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)easy_request.get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)easy_request.get_ptr().get() << "; now processing " << mAddedEasyRequests.size() << " easy handles.");
// Attempt to add a queued request, if any. // Attempt to add a queued request, if any.
if (!mQueuedRequests.empty()) if (!mQueuedRequests.empty())
@@ -1541,8 +1547,10 @@ void MultiHandle::check_run_count(void)
#ifdef CWDEBUG #ifdef CWDEBUG
char* eff_url; char* eff_url;
curl_easy_request_w->getinfo(CURLINFO_EFFECTIVE_URL, &eff_url); curl_easy_request_w->getinfo(CURLINFO_EFFECTIVE_URL, &eff_url);
Dout(dc::curl, "Finished: " << eff_url << " (" << msg->data.result << ")"); Dout(dc::curl, "Finished: " << eff_url << " (" << curl_easy_strerror(msg->data.result) << ") [CURLINFO_PRIVATE = " << (void*)ptr << "]");
#endif #endif
// Update timeout administration.
curl_easy_request_w->timeout_done(msg->data.result);
// Signal that this easy handle finished. // Signal that this easy handle finished.
curl_easy_request_w->done(curl_easy_request_w); curl_easy_request_w->done(curl_easy_request_w);
} }

View File

@@ -53,9 +53,14 @@ LLPumpIO* gServicePump;
BOOL gBreak = false; BOOL gBreak = false;
BOOL gSent = false; BOOL gSent = false;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy crashLoggerResponder_timeout;
class LLCrashLoggerResponder : public LLHTTPClient::Responder class LLCrashLoggerResponder : public LLHTTPClient::Responder
{ {
public: public:
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return crashLoggerResponder_timeout; }
LLCrashLoggerResponder() LLCrashLoggerResponder()
{ {
} }
@@ -308,14 +313,14 @@ bool LLCrashLogger::saveCrashBehaviorSetting(S32 crash_behavior)
return true; return true;
} }
bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout) bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg, int retries)
{ {
gBreak = false; gBreak = false;
std::string status_message; std::string status_message;
for(int i = 0; i < retries; ++i) for(int i = 0; i < retries; ++i)
{ {
status_message = llformat("%s, try %d...", msg.c_str(), i+1); status_message = llformat("%s, try %d...", msg.c_str(), i+1);
LLHTTPClient::post4(host, data, new LLCrashLoggerResponder(), timeout); LLHTTPClient::post4(host, data, new LLCrashLoggerResponder);
while(!gBreak) while(!gBreak)
{ {
updateApplication(status_message); updateApplication(status_message);
@@ -350,12 +355,12 @@ bool LLCrashLogger::sendCrashLogs()
// *TODO: Translate // *TODO: Translate
if(mCrashHost != "") if(mCrashHost != "")
{ {
sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5); sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3);
} }
if(!sent) if(!sent)
{ {
sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to alternate server"), 3, 5); sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to alternate server"), 3);
} }
mSentCrashLogs = sent; mSentCrashLogs = sent;

View File

@@ -40,6 +40,8 @@
#include "llsd.h" #include "llsd.h"
#include "llcontrol.h" #include "llcontrol.h"
class AIHTTPTimeoutPolicy;
class LLCrashLogger : public LLApp class LLCrashLogger : public LLApp
{ {
public: public:
@@ -57,7 +59,7 @@ public:
virtual bool cleanup() { return true; } virtual bool cleanup() { return true; }
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; } void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
S32 getCrashBehavior() { return mCrashBehavior; } S32 getCrashBehavior() { return mCrashBehavior; }
bool runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout); bool runCrashLogPost(std::string host, LLSD data, std::string msg, int retries);
protected: protected:
S32 mCrashBehavior; S32 mCrashBehavior;
BOOL mCrashInPreviousExec; BOOL mCrashInPreviousExec;

View File

@@ -21,6 +21,7 @@ include_directories(
set(llmessage_SOURCE_FILES set(llmessage_SOURCE_FILES
aihttpheaders.cpp aihttpheaders.cpp
aihttptimeoutpolicy.cpp
llhttpclient.cpp llhttpclient.cpp
llares.cpp llares.cpp
llareslistener.cpp llareslistener.cpp
@@ -106,6 +107,7 @@ set(llmessage_HEADER_FILES
CMakeLists.txt CMakeLists.txt
aihttpheaders.h aihttpheaders.h
aihttptimeoutpolicy.h
llares.h llares.h
llareslistener.h llareslistener.h
llassetstorage.h llassetstorage.h

View File

@@ -0,0 +1,733 @@
/**
* @file aihttptimeoutpolicy.cpp
* @brief Implementation of AIHTTPTimeoutPolicy
*
* Copyright (c) 2012, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 24/08/2012
* Initial version, written by Aleric Inglewood @ SL
*/
#include "sys.h"
#include "aihttptimeoutpolicy.h"
#include "llerror.h"
#include "lldefs.h"
#include "v3math.h"
#include <vector>
//!
// Timing of a HTML connection.
//
// Request call
// |
// v ... <--low speed time--> ... ... <--low speed time--> ...
// <--request queued--><--DNS lookup--><--connect margin--><--data transfer to server--><--reply delay--><--data transfer from server-->
// <------------------------------------------curl transaction----------------------------------------------------->
// <--------------------------------------------------------------total delay---------------------------------------------------------->
// |
// v
// finished
// For now, low speed limit is the same for up and download: usually download is (much) higher, but we have to take into account that
// there might also be multiple downloads at the same time, more than simultaneous uploads.
// Absolute maxima (min/max range):
// These values are intuitively determined and rather arbitrary.
namespace {
U16 const ABS_min_DNS_lookup = 0; // Rationale: If a FAST roundtrip is demanded, then setting the DNS lookup grace time
// at 0 seconds will not make a connection fail when the lookup takes 1 second, it
// just means that no EXTRA time is added to the connect time.
U16 const ABS_max_DNS_lookup = 300; // Waiting longer than 5 minutes never makes sense.
U16 const ABS_min_connect_time = 1; // Can't demand 0 seconds, and we deal with integer numbers here.
U16 const ABS_max_connect_time = 30; // Making a TCP/IP connection should REALLY succeed within 30 seconds or we rather try again.
U16 const ABS_min_reply_delay = 1; // Can't demand 0 seconds, and we deal with integer numbers here.
U16 const ABS_max_reply_delay = 120; // If the server needs more than 2 minutes to find the reply then something just HAS to be wrong :/.
U16 const ABS_min_low_speed_time = 4; // Intuitively, I think it makes no sense to average a download speed over less than 4 seconds.
U16 const ABS_max_low_speed_time = 120; // Averaging it over a time considerably larger than the normal timeout periods makes no sense either.
U32 const ABS_min_low_speed_limit = 1000; // AIFIXME: this should be 1 byte/s, set at 1000 now for debugging purposes.
U32 const ABS_max_low_speed_limit = 1000000; // This limit almost certainly higher than what the maximum speed you get from the server!
U16 const ABS_min_transaction = 60; // This is an absurd low value for experimentation. In reality, you should control
// termination of really slow connections through the low_speed settings.
U16 const ABS_max_transaction = 1200; // Insane long time. Downloads a texture of 4 MB at 3.5 kB/s. Textures are compressed though ;).
U16 const ABS_min_total_delay = 60; // This is an absurd low value for experimentation. In reality, you should control
// termination of really slow connections through the low_speed settings.
U16 const ABS_max_total_delay = 3000; // Insane long time, for when someone wants to be ABSOLUTELY sure this isn't the bottleneck.
using namespace AIHTTPTimeoutPolicyOperators;
// Default policy values.
U16 const AITP_default_DNS_lookup_grace = 60; // Allow for 60 seconds long DNS look ups.
U16 const AITP_default_maximum_connect_time = 10; // Allow the SSL/TLS connection through a proxy, including handshakes, to take up to 10 seconds.
U16 const AITP_default_maximum_reply_delay = 60; // Allow the server 60 seconds to do whatever it has to do before starting to send data.
U16 const AITP_default_low_speed_time = 30; // If a transfer speed drops below AITP_default_low_speed_limit bytes/s for 30 seconds, terminate the transfer.
U32 const AITP_default_low_speed_limit = 56000; // In bytes per second (use for CURLOPT_LOW_SPEED_LIMIT).
U16 const AITP_default_maximum_curl_transaction = 300; // Allow large files to be transfered over slow connections.
U16 const AITP_default_maximum_total_delay = 600; // Avoid "leaking" by terminating anything that wasn't completed after 10 minutes.
} // namespace
AIHTTPTimeoutPolicy& AIHTTPTimeoutPolicy::operator=(AIHTTPTimeoutPolicy const& rhs)
{
// You're not allowed to assign to a policy that is based on another policy.
llassert(!mBase);
mDNSLookupGrace = rhs.mDNSLookupGrace;
mMaximumConnectTime = rhs.mMaximumConnectTime;
mMaximumReplyDelay = rhs.mMaximumReplyDelay;
mLowSpeedTime = rhs.mLowSpeedTime;
mLowSpeedLimit = rhs.mLowSpeedLimit;
mMaximumCurlTransaction = rhs.mMaximumCurlTransaction;
mMaximumTotalDelay = rhs.mMaximumTotalDelay;
return *this;
}
AIHTTPTimeoutPolicy::AIHTTPTimeoutPolicy(char const* name,
U16 dns_lookup_grace, U16 subsequent_connects, U16 reply_delay,
U16 low_speed_time, U32 low_speed_limit,
U16 curl_transaction, U16 total_delay) :
mName(name),
mBase(NULL),
mDNSLookupGrace(dns_lookup_grace),
mMaximumConnectTime(subsequent_connects),
mMaximumReplyDelay(reply_delay),
mLowSpeedTime(low_speed_time),
mLowSpeedLimit(low_speed_limit),
mMaximumCurlTransaction(curl_transaction),
mMaximumTotalDelay(total_delay)
{
sanity_checks();
}
struct PolicyOp {
PolicyOp* mNext;
PolicyOp(void) : mNext(NULL) { }
PolicyOp(PolicyOp& op) : mNext(&op) { }
virtual void perform(AIHTTPTimeoutPolicy* policy) const { }
void nextOp(AIHTTPTimeoutPolicy* policy) const { if (mNext) mNext->perform(policy); }
};
class AIHTTPTimeoutPolicyBase : public AIHTTPTimeoutPolicy {
private:
std::vector<AIHTTPTimeoutPolicy*> mDerived; // Policies derived from this one.
public:
AIHTTPTimeoutPolicyBase(U16 dns_lookup_grace, U16 subsequent_connects, U16 reply_delay,
U16 low_speed_time, U32 low_speed_limit,
U16 curl_transaction, U16 total_delay) :
AIHTTPTimeoutPolicy(NULL, dns_lookup_grace, subsequent_connects, reply_delay, low_speed_time, low_speed_limit, curl_transaction, total_delay) { }
// Derive base from base.
AIHTTPTimeoutPolicyBase(AIHTTPTimeoutPolicyBase& rhs, PolicyOp const& op = PolicyOp()) : AIHTTPTimeoutPolicy(rhs) { op.perform(this); }
// Called for every derived policy.
void derived(AIHTTPTimeoutPolicy* derived) { mDerived.push_back(derived); }
// Provide public acces to sDebugSettingsCurlTimeout for this compilation unit.
static AIHTTPTimeoutPolicyBase& getDebugSettingsCurlTimeout(void) { return sDebugSettingsCurlTimeout; }
protected:
friend void AIHTTPTimeoutPolicy::setDefaultCurlTimeout(AIHTTPTimeoutPolicy const& timeout);
AIHTTPTimeoutPolicyBase& operator=(AIHTTPTimeoutPolicy const& rhs);
};
AIHTTPTimeoutPolicy::AIHTTPTimeoutPolicy(AIHTTPTimeoutPolicy& base) :
mName(NULL),
mBase(static_cast<AIHTTPTimeoutPolicyBase*>(&base)),
mDNSLookupGrace(base.mDNSLookupGrace),
mMaximumConnectTime(base.mMaximumConnectTime),
mMaximumReplyDelay(base.mMaximumReplyDelay),
mLowSpeedTime(base.mLowSpeedTime),
mLowSpeedLimit(base.mLowSpeedLimit),
mMaximumCurlTransaction(base.mMaximumCurlTransaction),
mMaximumTotalDelay(base.mMaximumTotalDelay)
{
}
AIHTTPTimeoutPolicyBase& AIHTTPTimeoutPolicyBase::operator=(AIHTTPTimeoutPolicy const& rhs)
{
AIHTTPTimeoutPolicy::operator=(rhs);
return *this;
}
AIHTTPTimeoutPolicy::AIHTTPTimeoutPolicy(char const* name, AIHTTPTimeoutPolicyBase& base) :
mName(name),
mBase(&base),
mDNSLookupGrace(mBase->mDNSLookupGrace),
mMaximumConnectTime(mBase->mMaximumConnectTime),
mMaximumReplyDelay(mBase->mMaximumReplyDelay),
mLowSpeedTime(mBase->mLowSpeedTime),
mLowSpeedLimit(mBase->mLowSpeedLimit),
mMaximumCurlTransaction(mBase->mMaximumCurlTransaction),
mMaximumTotalDelay(mBase->mMaximumTotalDelay)
{
// Register for changes to the base policy.
mBase->derived(this);
}
//static
void AIHTTPTimeoutPolicy::setDefaultCurlTimeout(AIHTTPTimeoutPolicy const& timeout)
{
sDebugSettingsCurlTimeout = timeout;
if (sDebugSettingsCurlTimeout.mDNSLookupGrace < AITP_default_DNS_lookup_grace)
{
llwarns << "CurlTimeoutDNSLookup (" << sDebugSettingsCurlTimeout.mDNSLookupGrace << ") is lower than the built-in default value (" << AITP_default_DNS_lookup_grace << ")." << llendl;
}
if (sDebugSettingsCurlTimeout.mMaximumConnectTime < AITP_default_maximum_connect_time)
{
llwarns << "CurlTimeoutConnect (" << sDebugSettingsCurlTimeout.mMaximumConnectTime << ") is lower than the built-in default value (" << AITP_default_maximum_connect_time << ")." << llendl;
}
if (sDebugSettingsCurlTimeout.mMaximumReplyDelay < AITP_default_maximum_reply_delay)
{
llwarns << "CurlTimeoutReplyDelay (" << sDebugSettingsCurlTimeout.mMaximumReplyDelay << ") is lower than the built-in default value (" << AITP_default_maximum_reply_delay << ")." << llendl;
}
if (sDebugSettingsCurlTimeout.mLowSpeedTime < AITP_default_low_speed_time)
{
llwarns << "CurlTimeoutLowSpeedTime (" << sDebugSettingsCurlTimeout.mLowSpeedTime << ") is lower than the built-in default value (" << AITP_default_low_speed_time << ")." << llendl;
}
if (sDebugSettingsCurlTimeout.mLowSpeedLimit > AITP_default_low_speed_limit)
{
llwarns << "CurlTimeoutLowSpeedLimit (" << sDebugSettingsCurlTimeout.mLowSpeedLimit << ") is higher than the built-in default value (" << AITP_default_low_speed_limit << ")." << llendl;
}
if (sDebugSettingsCurlTimeout.mMaximumCurlTransaction < AITP_default_maximum_curl_transaction)
{
llwarns << "CurlTimeoutMaxTransaction (" << sDebugSettingsCurlTimeout.mMaximumCurlTransaction << ") is lower than the built-in default value (" << AITP_default_maximum_curl_transaction<< ")." << llendl;
}
if (sDebugSettingsCurlTimeout.mMaximumTotalDelay < AITP_default_maximum_total_delay)
{
llwarns << "CurlTimeoutMaxTotalDelay (" << sDebugSettingsCurlTimeout.mMaximumTotalDelay << ") is lower than the built-in default value (" << AITP_default_maximum_total_delay << ")." << llendl;
}
}
//static
AIHTTPTimeoutPolicy const& AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout(void)
{
return sDebugSettingsCurlTimeout;
}
#ifdef SHOW_ASSERT
#include "aithreadid.h"
static AIThreadID curlthread(AIThreadID::none); // Initialized by getConnectTimeout.
#endif
static std::set<std::string> gSeenHostnames;
U16 AIHTTPTimeoutPolicy::getConnectTimeout(std::string const& hostname) const
{
#ifdef SHOW_ASSERT
// Only the CURL-THREAD may access gSeenHostnames.
if (curlthread.is_no_thread())
curlthread.reset();
llassert(curlthread.equals_current_thread());
#endif
U16 connect_timeout = mMaximumConnectTime;
// Add the hostname to the list of seen hostnames, if not already there.
if (gSeenHostnames.insert(hostname).second)
connect_timeout += mDNSLookupGrace; // If the host is not in the list, increase the connect timeout with mDNSLookupGrace.
return connect_timeout;
}
//static
bool AIHTTPTimeoutPolicy::connect_timed_out(std::string const& hostname)
{
llassert(curlthread.equals_current_thread());
// This is called when a connect to hostname timed out on connect.
// If the hostname is currently in the list, remove it and return true
// so that subsequent connects will get more time to connect.
// Otherwise return false.
return gSeenHostnames.erase(hostname) > 0;
}
//=======================================================================================================
// Start of policy operation definitions.
namespace AIHTTPTimeoutPolicyOperators {
// Note: Policies are applied in the order First(x, Second(y, Third(z))) etc,
// where the last (Third) has the highest priority.
// For example: Transaction(5, Connect(40)) would first enforce a transaction time of 5 seconds,
// and then a connect time of 40 seconds, even if that would mean increasing the transaction
// time again.
struct DNS : PolicyOp {
int mSeconds;
DNS(int seconds) : mSeconds(seconds) { }
DNS(int seconds, PolicyOp& op) : PolicyOp(op), mSeconds(seconds) { }
static void fix(AIHTTPTimeoutPolicy* policy);
static int min(void) { return ABS_min_DNS_lookup; }
static int max(void) { return ABS_max_DNS_lookup; }
virtual void perform(AIHTTPTimeoutPolicy* policy) const;
};
struct Connect : PolicyOp {
int mSeconds;
Connect(int seconds) : mSeconds(seconds) { }
Connect(int seconds, PolicyOp& op) : PolicyOp(op), mSeconds(seconds) { }
static void fix(AIHTTPTimeoutPolicy* policy);
static int min(void) { return ABS_min_connect_time; }
static int max(void) { return ABS_max_connect_time; }
virtual void perform(AIHTTPTimeoutPolicy* policy) const;
};
struct Reply : PolicyOp {
int mSeconds;
Reply(int seconds) : mSeconds(seconds) { }
Reply(int seconds, PolicyOp& op) : PolicyOp(op), mSeconds(seconds) { }
static void fix(AIHTTPTimeoutPolicy* policy);
static int min(void) { return ABS_min_reply_delay; }
static int max(void) { return ABS_max_reply_delay; }
virtual void perform(AIHTTPTimeoutPolicy* policy) const;
};
struct Speed : PolicyOp {
int mSeconds;
int mRate;
Speed(int seconds, int rate) : mSeconds(seconds), mRate(rate) { }
Speed(int seconds, int rate, PolicyOp& op) : PolicyOp(op), mSeconds(seconds), mRate(rate) { }
static void fix(AIHTTPTimeoutPolicy* policy);
static int min(void) { return ABS_min_low_speed_time; }
static int max(AIHTTPTimeoutPolicy const* policy) { return llmin(ABS_max_low_speed_time, (U16)(policy->mMaximumCurlTransaction / 2)); }
static int lmin(void) { return ABS_min_low_speed_limit; }
static int lmax(void) { return ABS_max_low_speed_limit; }
virtual void perform(AIHTTPTimeoutPolicy* policy) const;
};
struct Transaction : PolicyOp {
int mSeconds;
Transaction(int seconds) : mSeconds(seconds) { }
Transaction(int seconds, PolicyOp& op) : PolicyOp(op), mSeconds(seconds) { }
static void fix(AIHTTPTimeoutPolicy* policy);
static int min(AIHTTPTimeoutPolicy const* policy) { return llmax((int)ABS_min_transaction, policy->mMaximumConnectTime + policy->mMaximumReplyDelay + 4 * policy->mLowSpeedTime); }
static int max(void) { return ABS_max_transaction; }
virtual void perform(AIHTTPTimeoutPolicy* policy) const;
};
struct Total : PolicyOp {
int mSeconds;
Total(int seconds) : mSeconds(seconds) { }
Total(int seconds, PolicyOp& op) : PolicyOp(op), mSeconds(seconds) { }
static void fix(AIHTTPTimeoutPolicy* policy);
static int min(AIHTTPTimeoutPolicy const* policy) { return llmax((int)ABS_min_total_delay, policy->mMaximumCurlTransaction + 1); }
static int max(void) { return ABS_max_total_delay; }
virtual void perform(AIHTTPTimeoutPolicy* policy) const;
};
void DNS::perform(AIHTTPTimeoutPolicy* policy) const
{
policy->mDNSLookupGrace = mSeconds;
fix(policy);
nextOp(policy);
}
void Connect::perform(AIHTTPTimeoutPolicy* policy) const
{
policy->mMaximumConnectTime = mSeconds;
fix(policy);
nextOp(policy);
}
void Reply::perform(AIHTTPTimeoutPolicy* policy) const
{
policy->mMaximumReplyDelay = mSeconds;
fix(policy);
nextOp(policy);
}
void Speed::perform(AIHTTPTimeoutPolicy* policy) const
{
policy->mLowSpeedTime = mSeconds;
policy->mLowSpeedLimit = mRate;
fix(policy);
nextOp(policy);
}
void Transaction::perform(AIHTTPTimeoutPolicy* policy) const
{
policy->mMaximumCurlTransaction = mSeconds;
fix(policy);
nextOp(policy);
}
void Total::perform(AIHTTPTimeoutPolicy* policy) const
{
policy->mMaximumTotalDelay = mSeconds;
fix(policy);
nextOp(policy);
}
void DNS::fix(AIHTTPTimeoutPolicy* policy)
{
if (policy->mDNSLookupGrace > max())
{
policy->mDNSLookupGrace = max();
}
else if (policy->mDNSLookupGrace < min())
{
policy->mDNSLookupGrace = min();
}
}
void Connect::fix(AIHTTPTimeoutPolicy* policy)
{
bool changed = false;
if (policy->mMaximumConnectTime > max())
{
policy->mMaximumConnectTime = max();
changed = true;
}
else if (policy->mMaximumConnectTime < min())
{
policy->mMaximumConnectTime = min();
changed = true;
}
if (changed)
{
// Transaction limits depend on Connect.
Transaction::fix(policy);
}
}
void Reply::fix(AIHTTPTimeoutPolicy* policy)
{
bool changed = false;
if (policy->mMaximumReplyDelay > max())
{
policy->mMaximumReplyDelay = max();
changed = true;
}
else if (policy->mMaximumReplyDelay < min())
{
policy->mMaximumReplyDelay = min();
changed = true;
}
if (changed)
{
// Transaction limits depend on Reply.
Transaction::fix(policy);
}
}
void Speed::fix(AIHTTPTimeoutPolicy* policy)
{
bool changed = false;
if (policy->mLowSpeedTime > ABS_max_low_speed_time)
{
policy->mLowSpeedTime = ABS_max_low_speed_time;
changed = true;
}
else if (policy->mLowSpeedTime != 0 && policy->mLowSpeedTime < min())
{
policy->mLowSpeedTime = min();
changed = true;
}
if (changed)
{
// Transaction limits depend on Speed time.
Transaction::fix(policy);
}
if (policy->mLowSpeedTime > max(policy))
{
policy->mLowSpeedTime = max(policy);
}
if (policy->mLowSpeedLimit > lmax())
{
policy->mLowSpeedLimit = lmax();
}
else if (policy->mLowSpeedLimit != 0 && policy->mLowSpeedLimit < lmin())
{
policy->mLowSpeedLimit = lmin();
}
}
void Transaction::fix(AIHTTPTimeoutPolicy* policy)
{
bool changed = false;
if (policy->mMaximumCurlTransaction > max())
{
policy->mMaximumCurlTransaction = max();
changed = true;
}
else if (policy->mMaximumCurlTransaction < ABS_min_transaction)
{
policy->mMaximumCurlTransaction = ABS_min_transaction;
changed = true;
}
if (changed)
{
// Totals minimum limit depends on Transaction.
Total::fix(policy);
// Transaction limits depend on Connect, Reply and Speed time.
if (policy->mMaximumCurlTransaction < min(policy))
{
// We need to achieve the following (from Transaction::min()):
// policy->mMaximumCurlTransaction >= policy->mMaximumConnectTime + policy->mMaximumReplyDelay + 4 * policy->mLowSpeedTime
// There isn't a single way to fix this, so we just do something randomly intuitive.
// We consider the vector space <connect_time, reply_delay, low_speed_time>;
// In other words, we need to compare with the dot product of <1, 1, 4>.
LLVector3 const ref(1, 1, 4);
// The shortest allowed vector is:
LLVector3 const vec_min(ABS_min_connect_time, ABS_min_reply_delay, ABS_min_low_speed_time);
// Initialize the result vector to (0, 0, 0) (in the vector space with shifted origin).
LLVector3 vec_res;
// Check if there is a solution at all:
if (policy->mMaximumCurlTransaction > ref * vec_min) // Is vec_min small enough?
{
// The current point is:
LLVector3 vec_cur(policy->mMaximumConnectTime, policy->mMaximumReplyDelay, policy->mLowSpeedTime);
// The default point is:
LLVector3 vec_def(AITP_default_maximum_connect_time, AITP_default_maximum_reply_delay, AITP_default_low_speed_time);
// Move the origin.
vec_cur -= vec_min;
vec_def -= vec_min;
// Normalize the default vector (we only need it's direction).
vec_def.normalize();
// Project the current vector onto the default vector (dp = default projection):
LLVector3 vec_dp = vec_def * (vec_cur * vec_def);
// Check if the projection is a solution and choose the vectors between which the result lays.
LLVector3 a; // vec_min is too small (a = (0, 0, 0) which corresponds to vec_min).
LLVector3 b = vec_cur; // vec_cur is too large.
if (policy->mMaximumCurlTransaction > ref * (vec_dp + vec_min)) // Is vec_dp small enough too?
{
a = vec_dp; // New lower bound.
}
else
{
b = vec_dp; // New upper bound.
}
// Find vec_res = a + lambda * (b - a), where 0 <= lambda <= 1, such that
// policy->mMaximumCurlTransaction == ref * (vec_res + vec_min).
//
// Note that ref * (b - a) must be non-zero because if it wasn't then changing lambda wouldn't have
// any effect on right-hand side of the equation (ref * (vec_res + vec_min)) which in contradiction
// with the fact that a is a solution and b is not.
F32 lambda = (policy->mMaximumCurlTransaction - ref * (a + vec_min)) / (ref * (b - a));
vec_res = a + lambda * (b - a);
}
// Shift origin back and fill in the result.
vec_res += vec_min;
policy->mMaximumConnectTime = vec_res[VX];
policy->mMaximumReplyDelay = vec_res[VY];
policy->mLowSpeedTime = vec_res[VZ];
}
}
if (policy->mMaximumCurlTransaction < min(policy))
{
policy->mMaximumCurlTransaction = min(policy);
}
}
void Total::fix(AIHTTPTimeoutPolicy* policy)
{
bool changed = false;
if (policy->mMaximumTotalDelay > max())
{
policy->mMaximumTotalDelay = max();
changed = true;
}
else if (policy->mMaximumTotalDelay < ABS_min_total_delay)
{
policy->mMaximumTotalDelay = ABS_min_total_delay;
changed = true;
}
if (changed)
{
// Totals minimum limit depends on Transaction.
// We have to correct mMaximumCurlTransaction such that (from Total::min)
// mMaximumTotalDelay >= llmax((int)ABS_min_total_delay, policy->mMaximumCurlTransaction + 1)
if (policy->mMaximumTotalDelay < policy->mMaximumCurlTransaction + 1)
{
policy->mMaximumCurlTransaction = policy->mMaximumTotalDelay - 1;
}
}
if (policy->mMaximumTotalDelay < min(policy))
{
policy->mMaximumTotalDelay = min(policy);
}
}
} // namespace AIHTTPTimeoutPolicyOperators
void AIHTTPTimeoutPolicy::sanity_checks(void) const
{
// Sanity checks.
llassert( DNS::min() <= mDNSLookupGrace && mDNSLookupGrace <= DNS::max());
llassert( Connect::min() <= mMaximumConnectTime && mMaximumConnectTime <= Connect::max());
llassert( Reply::min() <= mMaximumReplyDelay && mMaximumReplyDelay <= Reply::max());
llassert(mLowSpeedTime == 0 ||
(Speed::min() <= mLowSpeedTime && mLowSpeedTime <= Speed::max(this)));
llassert(mLowSpeedLimit == 0 ||
(Speed::lmin() <= mLowSpeedLimit && mLowSpeedLimit <= Speed::lmax()));
llassert(Transaction::min(this) <= mMaximumCurlTransaction && mMaximumCurlTransaction <= Transaction::max());
llassert( Total::min(this) <= mMaximumTotalDelay && mMaximumTotalDelay <= Total::max());
}
//=======================================================================================================
// Start of policy definitions.
// AIFIXME: update all policies whenever a CurlTimeout* settings is changed.
// Policy with hardcoded default values.
AIHTTPTimeoutPolicyBase HTTPTimeoutPolicy_default(
AITP_default_DNS_lookup_grace,
AITP_default_maximum_connect_time,
AITP_default_maximum_reply_delay,
AITP_default_low_speed_time,
AITP_default_low_speed_limit,
AITP_default_maximum_curl_transaction,
AITP_default_maximum_total_delay);
//static. Initialized here, but shortly overwritten by Debug Settings.
AIHTTPTimeoutPolicyBase AIHTTPTimeoutPolicy::sDebugSettingsCurlTimeout(
AITP_default_DNS_lookup_grace,
AITP_default_maximum_connect_time,
AITP_default_maximum_reply_delay,
AITP_default_low_speed_time,
AITP_default_low_speed_limit,
AITP_default_maximum_curl_transaction,
AITP_default_maximum_total_delay);
// This used to be '5 seconds'.
AIHTTPTimeoutPolicyBase transfer_5s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(),
Transaction(5)
);
// This used to be '18 seconds'.
AIHTTPTimeoutPolicyBase transfer_18s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(),
Transaction(18)
);
// This used to be '300 seconds'. We derive this from the hardcoded result so users can't mess with it.
AIHTTPTimeoutPolicyBase transfer_300s(HTTPTimeoutPolicy_default,
Transaction(300)
);
// This used to be a call to setopt(CURLOPT_CONNECTTIMEOUT, 40L) with the remark 'Be a little impatient about establishing connections.'
AIHTTPTimeoutPolicyBase connect_40s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(),
Connect(40));
// End of policy definitions.
//=======================================================================================================
//=======================================================================================================
// Start of Responder timeout policy list.
// Note: to find the actual responder class back, search for the name listed here but with upper case first character.
// For example, if the actual responder class is LLAccountingCostResponder then the name used here is accountingCostResponder.
#undef P
#define P(n) AIHTTPTimeoutPolicy n##_timeout(#n)
#define P2(n, b) AIHTTPTimeoutPolicy n##_timeout(#n, b)
// Policy name Policy
P(accountingCostResponder);
P(agentStateResponder);
P(assetUploadResponder);
P(asyncConsoleResponder);
P(avatarNameResponder);
P2(baseCapabilitiesComplete, transfer_18s);
P(blockingGet);
P(blockingPost);
P(charactersResponder);
P(classifiedStatsResponder);
P(consoleResponder);
P2(crashLoggerResponder, transfer_5s);
P(createInventoryCategoryResponder);
P(emeraldDicDownloader);
P(environmentApplyResponder);
P(environmentRequestResponder);
P(estateChangeInfoResponder);
P(eventPollResponder);
P(eventResponder);
P(fetchInventoryResponder);
P(floaterRegionDebugConsole);
P(fnPtrResponder);
P2(groupProposalBallotResponder, transfer_300s);
P(homeLocationResponder);
P(HTTPGetResponder);
P(iamHereLogin);
P(iamHere);
P(iamHereVoice);
P2(inventoryModelFetchDescendentsResponder, transfer_300s);
P(inventoryModelFetchItemResponder);
P(lcl_responder);
P(mapLayerResponder);
P(mediaTypeResponder);
P(meshDecompositionResponder);
P(meshHeaderResponder);
P(meshLODResponder);
P(meshPhysicsShapeResponder);
P(meshSkinInfoResponder);
P(mimeDiscoveryResponder);
P(moderationModeResponder);
P(muteTextResponder);
P(muteVoiceResponder);
P(navMeshRebakeResponder);
P(navMeshResponder);
P(navMeshStatusResponder);
P(newAgentInventoryVariablePriceResponder);
P(objectCostResponder);
P(objectLinksetsResponder);
P(physicsFlagsResponder);
P(placeAvatarTeleportResponder);
P(productInfoRequestResponder);
P(regionResponder);
P(remoteParcelRequestResponder);
P(responderIgnore);
P(sessionInviteResponder);
P(setDisplayNameResponder);
P2(simulatorFeaturesReceived, transfer_18s);
P(startConferenceChatResponder);
P2(startGroupVoteResponder, transfer_300s);
P(terrainLinksetsResponder);
P(translationReceiver);
P(uploadModelPremissionsResponder);
P(userReportResponder);
P(verifiedDestinationResponder);
P(viewerChatterBoxInvitationAcceptResponder);
P(viewerMediaOpenIDResponder);
P(viewerMediaWebProfileResponder);
P(viewerStatsResponder);
P(viewerVoiceAccountProvisionResponder);
P(voiceCallCapResponder);
P(voiceClientCapResponder);
P(wholeModelFeeResponder);
P(wholeModelUploadResponder);
P2(XMLRPCTransaction, connect_40s);

View File

@@ -0,0 +1,114 @@
/**
* @file aihttptimeoutpolicy.h
* @brief Store the policy on timing out a HTTP curl transaction.
*
* Copyright (c) 2012, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 24/09/2012
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIHTTPTIMEOUTPOLICY_H
#define AIHTTPTIMEOUTPOLICY_H
#include "stdtypes.h"
#include <string>
class AIHTTPTimeoutPolicyBase;
namespace AIHTTPTimeoutPolicyOperators {
struct DNS;
struct Connect;
struct Reply;
struct Speed;
struct Transaction;
struct Total;
} // namespace AIHTTPTimeoutPolicyOperators
class AIHTTPTimeoutPolicy {
protected:
char const* const mName; // The name of this policy, for debugging purposes.
AIHTTPTimeoutPolicyBase* const mBase; // Policy this policy was based on.
static AIHTTPTimeoutPolicyBase sDebugSettingsCurlTimeout; // CurlTimeout* debug settings.
private:
U16 mDNSLookupGrace; // Extra connect timeout the first time we connect to a host (this is to allow for DNS lookups).
U16 mMaximumConnectTime; // Connect timeouts any subsequent connects to the same host, assuming the DNS will be cached now.
U16 mMaximumReplyDelay; // Timeout for the period between sending data to the server and the HTTP header of the reply.
U16 mLowSpeedTime; // The time in seconds that a transfer should be below mLowSpeedLimit before to consider it too slow and abort.
U32 mLowSpeedLimit; // Transfer speed in bytes per second that a transfer should be below during mLowSpeedTime seconds to consider it too slow and abort.
U16 mMaximumCurlTransaction; // Timeout for the whole curl transaction (including connect and DNS lookup).
U16 mMaximumTotalDelay; // Timeout from moment of request (including the time a request is/was queued).
friend struct AIHTTPTimeoutPolicyOperators::DNS;
friend struct AIHTTPTimeoutPolicyOperators::Connect;
friend struct AIHTTPTimeoutPolicyOperators::Reply;
friend struct AIHTTPTimeoutPolicyOperators::Speed;
friend struct AIHTTPTimeoutPolicyOperators::Transaction;
friend struct AIHTTPTimeoutPolicyOperators::Total;
public:
// Construct a HTTP timeout policy object that mimics base, or Debug Settings if none given.
AIHTTPTimeoutPolicy(
char const* name,
AIHTTPTimeoutPolicyBase& base = sDebugSettingsCurlTimeout);
// Construct a HTTP timeout policy with exact specifications.
AIHTTPTimeoutPolicy(
char const* name,
U16 dns_lookup_grace,
U16 subsequent_connects,
U16 reply_delay,
U16 low_speed_time,
U32 low_speed_limit,
U16 curl_transaction,
U16 total_delay);
void sanity_checks(void) const;
// Accessors.
char const* name(void) const { return mName; }
U16 getConnectTimeout(std::string const& hostname) const;
U16 getReplyDelay(void) const { return mMaximumReplyDelay; }
U16 getLowSpeedTime(void) const { return mLowSpeedTime; }
U32 getLowSpeedLimit(void) const { return mLowSpeedLimit; }
U16 getCurlTransaction(void) const { return mMaximumCurlTransaction; }
U16 getTotalDelay(void) const { return mMaximumTotalDelay; }
static AIHTTPTimeoutPolicy const& getDebugSettingsCurlTimeout(void);
// Called once at start up of viewer to set a different default timeout policy than HTTPTimeoutPolicy_default.
static void setDefaultCurlTimeout(AIHTTPTimeoutPolicy const& defaultCurlTimeout);
// Called when a connect to a hostname timed out.
static bool connect_timed_out(std::string const& hostname);
protected:
// Used by AIHTTPTimeoutPolicyBase::AIHTTPTimeoutPolicyBase(AIHTTPTimeoutPolicyBase&).
AIHTTPTimeoutPolicy(AIHTTPTimeoutPolicy&);
// Abused assigned operator (called by AIHTTPTimeoutPolicyBase::operator=).
AIHTTPTimeoutPolicy& operator=(AIHTTPTimeoutPolicy const&);
};
#endif // AIHTTPTIMEOUTPOLICY_H

View File

@@ -171,6 +171,9 @@ namespace LLAvatarNameCache
</llsd> </llsd>
*/ */
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy avatarNameResponder_timeout;
class LLAvatarNameResponder : public LLHTTPClient::Responder class LLAvatarNameResponder : public LLHTTPClient::Responder
{ {
private: private:
@@ -182,6 +185,8 @@ private:
AIHTTPHeaders mHeaders; AIHTTPHeaders mHeaders;
public: public:
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return avatarNameResponder_timeout; }
LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids) LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
: mAgentIDs(agent_ids) : mAgentIDs(agent_ids)
{ } { }

View File

@@ -46,7 +46,6 @@
static const U32 EASY_HANDLE_POOL_SIZE = 5; static const U32 EASY_HANDLE_POOL_SIZE = 5;
static const S32 MULTI_PERFORM_CALL_REPEAT = 5; static const S32 MULTI_PERFORM_CALL_REPEAT = 5;
static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation
static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
//static //static

View File

@@ -76,7 +76,7 @@ bool Request::getByteRange2(std::string const& url, AIHTTPHeaders const& headers
buffered_easy_request_w->addHeader(range.c_str()); buffered_easy_request_w->addHeader(range.c_str());
} }
buffered_easy_request_w->finalizeRequest(url); buffered_easy_request_w->finalizeRequest(url, responder->getHTTPTimeoutPolicy(), buffered_easy_request);
} }
buffered_easy_request->run(); buffered_easy_request->run();
@@ -84,7 +84,7 @@ bool Request::getByteRange2(std::string const& url, AIHTTPHeaders const& headers
return true; // We throw in case of problems. return true; // We throw in case of problems.
} }
bool Request::post2(std::string const& url, AIHTTPHeaders const& headers, std::string const& data, ResponderPtr responder, S32 time_out) bool Request::post2(std::string const& url, AIHTTPHeaders const& headers, std::string const& data, ResponderPtr responder)
{ {
DoutEntering(dc::curl, "Request::post(" << url << ", ...)"); DoutEntering(dc::curl, "Request::post(" << url << ", ...)");
@@ -95,7 +95,7 @@ bool Request::post2(std::string const& url, AIHTTPHeaders const& headers, std::s
AICurlEasyRequest_wat buffered_easy_request_w(*buffered_easy_request->mCurlEasyRequest); AICurlEasyRequest_wat buffered_easy_request_w(*buffered_easy_request->mCurlEasyRequest);
AICurlResponderBuffer_wat buffer_w(*buffered_easy_request->mCurlEasyRequest); AICurlResponderBuffer_wat buffer_w(*buffered_easy_request->mCurlEasyRequest);
buffer_w->prepRequest(buffered_easy_request_w, headers, responder, time_out); buffer_w->prepRequest(buffered_easy_request_w, headers, responder);
U32 bytes = data.size(); U32 bytes = data.size();
bool success = buffer_w->getInput()->append(buffer_w->sChannels.out(), (U8 const*)data.data(), bytes); bool success = buffer_w->getInput()->append(buffer_w->sChannels.out(), (U8 const*)data.data(), bytes);
@@ -106,7 +106,7 @@ bool Request::post2(std::string const& url, AIHTTPHeaders const& headers, std::s
} }
buffered_easy_request_w->setPost(bytes); buffered_easy_request_w->setPost(bytes);
buffered_easy_request_w->addHeader("Content-Type: application/octet-stream"); buffered_easy_request_w->addHeader("Content-Type: application/octet-stream");
buffered_easy_request_w->finalizeRequest(url); buffered_easy_request_w->finalizeRequest(url, responder->getHTTPTimeoutPolicy(), buffered_easy_request);
} }
buffered_easy_request->run(); buffered_easy_request->run();
@@ -114,7 +114,7 @@ bool Request::post2(std::string const& url, AIHTTPHeaders const& headers, std::s
return true; // We throw in case of problems. return true; // We throw in case of problems.
} }
bool Request::post3(std::string const& url, AIHTTPHeaders const& headers, LLSD const& data, ResponderPtr responder, S32 time_out) bool Request::post3(std::string const& url, AIHTTPHeaders const& headers, LLSD const& data, ResponderPtr responder)
{ {
DoutEntering(dc::curl, "Request::post(" << url << ", ...)"); DoutEntering(dc::curl, "Request::post(" << url << ", ...)");
@@ -125,7 +125,7 @@ bool Request::post3(std::string const& url, AIHTTPHeaders const& headers, LLSD c
AICurlEasyRequest_wat buffered_easy_request_w(*buffered_easy_request->mCurlEasyRequest); AICurlEasyRequest_wat buffered_easy_request_w(*buffered_easy_request->mCurlEasyRequest);
AICurlResponderBuffer_wat buffer_w(*buffered_easy_request->mCurlEasyRequest); AICurlResponderBuffer_wat buffer_w(*buffered_easy_request->mCurlEasyRequest);
buffer_w->prepRequest(buffered_easy_request_w, headers, responder, time_out); buffer_w->prepRequest(buffered_easy_request_w, headers, responder);
LLBufferStream buffer_stream(buffer_w->sChannels, buffer_w->getInput().get()); LLBufferStream buffer_stream(buffer_w->sChannels, buffer_w->getInput().get());
LLSDSerialize::toXML(data, buffer_stream); LLSDSerialize::toXML(data, buffer_stream);
@@ -134,7 +134,7 @@ bool Request::post3(std::string const& url, AIHTTPHeaders const& headers, LLSD c
S32 bytes = buffer_w->getInput()->countAfter(buffer_w->sChannels.out(), NULL); S32 bytes = buffer_w->getInput()->countAfter(buffer_w->sChannels.out(), NULL);
buffered_easy_request_w->setPost(bytes); buffered_easy_request_w->setPost(bytes);
buffered_easy_request_w->addHeader("Content-Type: application/llsd+xml"); buffered_easy_request_w->addHeader("Content-Type: application/llsd+xml");
buffered_easy_request_w->finalizeRequest(url); buffered_easy_request_w->finalizeRequest(url, responder->getHTTPTimeoutPolicy(), buffered_easy_request);
lldebugs << "POSTING: " << bytes << " bytes." << llendl; lldebugs << "POSTING: " << bytes << " bytes." << llendl;
} }

View File

@@ -48,8 +48,8 @@ class Request {
public: public:
bool get2(std::string const& url, ResponderPtr responder); bool get2(std::string const& url, ResponderPtr responder);
bool getByteRange2(std::string const& url, AIHTTPHeaders const& headers, S32 offset, S32 length, ResponderPtr responder); bool getByteRange2(std::string const& url, AIHTTPHeaders const& headers, S32 offset, S32 length, ResponderPtr responder);
bool post2(std::string const& url, AIHTTPHeaders const& headers, std::string const& data, ResponderPtr responder, S32 time_out = 0); bool post2(std::string const& url, AIHTTPHeaders const& headers, std::string const& data, ResponderPtr responder);
bool post3(std::string const& url, AIHTTPHeaders const& headers, LLSD const& data, ResponderPtr responder, S32 time_out = 0); bool post3(std::string const& url, AIHTTPHeaders const& headers, LLSD const& data, ResponderPtr responder);
}; };
} // namespace AICurlInterface } // namespace AICurlInterface

View File

@@ -34,7 +34,10 @@
#include "llvfile.h" #include "llvfile.h"
#include "llurlrequest.h" #include "llurlrequest.h"
F32 const HTTP_REQUEST_EXPIRY_SECS = 60.0f; class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy blockingGet_timeout;
extern AIHTTPTimeoutPolicy blockingPost_timeout;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
class LLSDInjector : public Injector class LLSDInjector : public Injector
@@ -146,8 +149,7 @@ static void request(
LLURLRequest::ERequestAction method, LLURLRequest::ERequestAction method,
Injector* body_injector, Injector* body_injector,
LLCurl::ResponderPtr responder, LLCurl::ResponderPtr responder,
AIHTTPHeaders& headers, AIHTTPHeaders& headers)
F32 timeout = HTTP_REQUEST_EXPIRY_SECS)
{ {
if (responder) if (responder)
{ {
@@ -167,40 +169,39 @@ static void request(
return ; return ;
} }
req->setRequestTimeOut(timeout);
req->run(); req->run();
} }
void LLHTTPClient::getByteRange4(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::getByteRange4(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
if(offset > 0 || bytes > 0) if(offset > 0 || bytes > 0)
{ {
headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1)); headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1));
} }
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers, timeout); request(url, LLURLRequest::HTTP_GET, NULL, responder, headers);
} }
void LLHTTPClient::head4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::head4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers, timeout); request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers);
} }
void LLHTTPClient::get4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::get4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers, timeout); request(url, LLURLRequest::HTTP_GET, NULL, responder, headers);
} }
void LLHTTPClient::getHeaderOnly4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::getHeaderOnly4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers, timeout); request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers);
} }
void LLHTTPClient::get4(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::get4(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
LLURI uri; LLURI uri;
uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query); uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
get4(uri.asString(), responder, headers, timeout); get4(uri.asString(), responder, headers);
} }
// A simple class for managing data returned from a curl http request. // A simple class for managing data returned from a curl http request.
@@ -261,7 +262,7 @@ static LLSD blocking_request(
LLURLRequest::ERequestAction method, LLURLRequest::ERequestAction method,
LLSD const& body, LLSD const& body,
AIHTTPHeaders& headers, AIHTTPHeaders& headers,
F32 timeout = 5) AIHTTPTimeoutPolicy const& timeout)
{ {
lldebugs << "blockingRequest of " << url << llendl; lldebugs << "blockingRequest of " << url << llendl;
@@ -347,49 +348,49 @@ static LLSD blocking_request(
LLSD LLHTTPClient::blockingGet(const std::string& url) LLSD LLHTTPClient::blockingGet(const std::string& url)
{ {
AIHTTPHeaders empty_headers; AIHTTPHeaders empty_headers;
return blocking_request(url, LLURLRequest::HTTP_GET, LLSD(), empty_headers); return blocking_request(url, LLURLRequest::HTTP_GET, LLSD(), empty_headers, blockingGet_timeout);
} }
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body) LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
{ {
AIHTTPHeaders empty_headers; AIHTTPHeaders empty_headers;
return blocking_request(url, LLURLRequest::HTTP_POST, body, empty_headers); return blocking_request(url, LLURLRequest::HTTP_POST, body, empty_headers, blockingPost_timeout);
} }
void LLHTTPClient::put4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::put4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers, timeout); request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers);
} }
void LLHTTPClient::post4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::post4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers, timeout); request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers);
} }
void LLHTTPClient::postRaw4(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::postRaw4(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers, timeout); request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers);
} }
void LLHTTPClient::postFile4(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::postFile4(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers, timeout); request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers);
} }
void LLHTTPClient::postFile4(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::postFile4(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers, timeout); request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers);
} }
// static // static
void LLHTTPClient::del4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::del4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers, timeout); request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers);
} }
// static // static
void LLHTTPClient::move4(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout) void LLHTTPClient::move4(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers)
{ {
headers.addHeader("Destination", destination); headers.addHeader("Destination", destination);
request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers, timeout); request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers);
} }

View File

@@ -37,11 +37,12 @@
#include "llcurl.h" #include "llcurl.h"
#include "aihttpheaders.h" #include "aihttpheaders.h"
extern F32 const HTTP_REQUEST_EXPIRY_SECS;
class LLUUID; class LLUUID;
class LLPumpIO; class LLPumpIO;
class LLSD; class LLSD;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy responderIgnore_timeout;
class LLHTTPClient class LLHTTPClient
{ {
@@ -51,54 +52,54 @@ public:
typedef LLCurl::ResponderPtr ResponderPtr; typedef LLCurl::ResponderPtr ResponderPtr;
// The default actually already ignores responses. // The default actually already ignores responses.
class ResponderIgnore : public Responder { }; class ResponderIgnore : public Responder { virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return responderIgnore_timeout;} };
/** @name non-blocking API */ /** @name non-blocking API */
//@{ //@{
static void head4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void head4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void head4(std::string const& url, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void head4(std::string const& url, ResponderPtr responder)
{ AIHTTPHeaders headers; head4(url, responder, headers, timeout); } { AIHTTPHeaders headers; head4(url, responder, headers); }
static void getByteRange4(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void getByteRange4(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers);
static void getByteRange4(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void getByteRange4(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder)
{ AIHTTPHeaders headers; getByteRange4(url, offset, bytes, responder, headers, timeout); } { AIHTTPHeaders headers; getByteRange4(url, offset, bytes, responder, headers); }
static void get4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void get4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void get4(std::string const& url, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void get4(std::string const& url, ResponderPtr responder)
{ AIHTTPHeaders headers; get4(url, responder, headers, timeout); } { AIHTTPHeaders headers; get4(url, responder, headers); }
static void get4(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void get4(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers);
static void get4(std::string const& url, LLSD const& query, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void get4(std::string const& url, LLSD const& query, ResponderPtr responder)
{ AIHTTPHeaders headers; get4(url, query, responder, headers, timeout); } { AIHTTPHeaders headers; get4(url, query, responder, headers); }
static void put4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void put4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
static void put4(std::string const& url, LLSD const& body, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void put4(std::string const& url, LLSD const& body, ResponderPtr responder)
{ AIHTTPHeaders headers; put4(url, body, responder, headers, timeout); } { AIHTTPHeaders headers; put4(url, body, responder, headers); }
static void getHeaderOnly4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void getHeaderOnly4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void getHeaderOnly4(std::string const& url, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void getHeaderOnly4(std::string const& url, ResponderPtr responder)
{ AIHTTPHeaders headers; getHeaderOnly4(url, responder, headers, timeout); } { AIHTTPHeaders headers; getHeaderOnly4(url, responder, headers); }
static void post4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void post4(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
static void post4(std::string const& url, LLSD const& body, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void post4(std::string const& url, LLSD const& body, ResponderPtr responder)
{ AIHTTPHeaders headers; post4(url, body, responder, headers, timeout); } { AIHTTPHeaders headers; post4(url, body, responder, headers); }
/** Takes ownership of data and deletes it when sent */ /** Takes ownership of data and deletes it when sent */
static void postRaw4(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void postRaw4(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers);
static void postRaw4(std::string const& url, const char* data, S32 size, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void postRaw4(std::string const& url, const char* data, S32 size, ResponderPtr responder)
{ AIHTTPHeaders headers; postRaw4(url, data, size, responder, headers, timeout); } { AIHTTPHeaders headers; postRaw4(url, data, size, responder, headers); }
static void postFile4(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void postFile4(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers);
static void postFile4(std::string const& url, std::string const& filename, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void postFile4(std::string const& url, std::string const& filename, ResponderPtr responder)
{ AIHTTPHeaders headers; postFile4(url, filename, responder, headers, timeout); } { AIHTTPHeaders headers; postFile4(url, filename, responder, headers); }
static void postFile4(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void postFile4(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers);
static void postFile4(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void postFile4(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder)
{ AIHTTPHeaders headers; postFile4(url, uuid, asset_type, responder, headers, timeout); } { AIHTTPHeaders headers; postFile4(url, uuid, asset_type, responder, headers); }
static void del4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void del4(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void del4(std::string const& url, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void del4(std::string const& url, ResponderPtr responder)
{ AIHTTPHeaders headers; del4(url, responder, headers, timeout); } { AIHTTPHeaders headers; del4(url, responder, headers); }
///< sends a DELETE method, but we can't call it delete in c++ ///< sends a DELETE method, but we can't call it delete in c++
@@ -111,9 +112,9 @@ public:
* @param headers A map of key:value headers to pass to the request * @param headers A map of key:value headers to pass to the request
* @param timeout The number of seconds to give the server to respond. * @param timeout The number of seconds to give the server to respond.
*/ */
static void move4(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers, F32 timeout = HTTP_REQUEST_EXPIRY_SECS); static void move4(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers);
static void move4(std::string const& url, std::string const& destination, ResponderPtr responder, F32 timeout = HTTP_REQUEST_EXPIRY_SECS) static void move4(std::string const& url, std::string const& destination, ResponderPtr responder)
{ AIHTTPHeaders headers; move4(url, destination, responder, headers, timeout); } { AIHTTPHeaders headers; move4(url, destination, responder, headers); }
//@} //@}

View File

@@ -34,6 +34,9 @@
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
class LLHTTPClientInterface; class LLHTTPClientInterface;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy regionResponder_timeout;
extern AIHTTPTimeoutPolicy verifiedDestinationResponder_timeout;
class LLRegionPresenceVerifier class LLRegionPresenceVerifier
{ {
@@ -58,6 +61,8 @@ public:
class RegionResponder : public LLHTTPClient::Responder class RegionResponder : public LLHTTPClient::Responder
{ {
public: public:
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return regionResponder_timeout; }
RegionResponder(const std::string& uri, ResponsePtr data, RegionResponder(const std::string& uri, ResponsePtr data,
S32 retry_count); S32 retry_count);
virtual ~RegionResponder(); virtual ~RegionResponder();
@@ -73,6 +78,8 @@ public:
class VerifiedDestinationResponder : public LLHTTPClient::Responder class VerifiedDestinationResponder : public LLHTTPClient::Responder
{ {
public: public:
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return verifiedDestinationResponder_timeout; }
VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
const LLSD& content, S32 retry_count); const LLSD& content, S32 retry_count);
virtual ~VerifiedDestinationResponder(); virtual ~VerifiedDestinationResponder();

View File

@@ -77,17 +77,18 @@ bool LLSDMessage::httpListener(const LLSD& request)
out << "request event without 'url' key to '" << mEventPump.getName() << "'"; out << "request event without 'url' key to '" << mEventPump.getName() << "'";
throw ArgError(out.str()); throw ArgError(out.str());
} }
#if 0 // AIFIXME: ignore this for now
// Establish default timeout. This test relies on LLSD::asReal() returning // Establish default timeout. This test relies on LLSD::asReal() returning
// exactly 0.0 for an undef value. // exactly 0.0 for an undef value.
if (! timeout) if (! timeout)
{ {
timeout = HTTP_REQUEST_EXPIRY_SECS; timeout = HTTP_REQUEST_EXPIRY_SECS;
} }
#endif
LLHTTPClient::post4(url, payload, LLHTTPClient::post4(url, payload,
new LLSDMessage::EventResponder(LLEventPumps::instance(), new LLSDMessage::EventResponder(LLEventPumps::instance(),
request, request,
url, "POST", reply, error), url, "POST", reply, error));
(F32)timeout);
return false; return false;
} }

View File

@@ -37,6 +37,8 @@
#include <stdexcept> #include <stdexcept>
class LLSD; class LLSD;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy eventResponder_timeout;
/** /**
* Class managing the messaging API described in * Class managing the messaging API described in
@@ -124,6 +126,8 @@ private:
class EventResponder: public LLHTTPClient::Responder class EventResponder: public LLHTTPClient::Responder
{ {
public: public:
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return eventResponder_timeout; }
/** /**
* LLHTTPClient::Responder that dispatches via named LLEventPump instances. * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
* We bind LLEventPumps, even though it's an LLSingleton, for testability. * We bind LLEventPumps, even though it's an LLSingleton, for testability.

View File

@@ -293,14 +293,14 @@ LLIOPipe::EStatus LLURLRequest::handleError(
LLIOPipe::EStatus status, LLIOPipe::EStatus status,
LLPumpIO* pump) LLPumpIO* pump)
{ {
DoutEntering(dc::curl, "LLURLRequest::handleError(" << LLIOPipe::lookupStatusString(status) << ", " << (void*)pump << ")"); DoutEntering(dc::curl, "LLURLRequest::handleError(" << LLIOPipe::lookupStatusString(status) << ", " << (void*)pump << ") [" << (void*)mCurlEasyRequest.get_ptr().get() << "]");
if (LL_LIKELY(!mDetail->mStateMachine->isBuffered())) // Currently always true. if (LL_LIKELY(!mDetail->mStateMachine->isBuffered())) // Currently always true.
{ {
// The last reference will be deleted when the pump that this chain belongs to // The last reference will be deleted when the pump that this chain belongs to
// is removed from the running chains vector, upon returning from this function. // is removed from the running chains vector, upon returning from this function.
// This keeps the CurlEasyRequest object alive until the curl thread cleanly removed it. // This keeps the CurlEasyRequest object alive until the curl thread cleanly removed it.
Dout(dc::curl, "Calling mDetail->mStateMachine->removeRequest()"); Dout(dc::curl, "Calling mDetail->mStateMachine->removeRequest() [" << (void*)mCurlEasyRequest.get_ptr().get() << "]");
mDetail->mStateMachine->removeRequest(); mDetail->mStateMachine->removeRequest();
} }
else if (!hasNotExpired()) else if (!hasNotExpired())
@@ -546,7 +546,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
} }
if(rv) if(rv)
{ {
curlEasyRequest_w->finalizeRequest(mURL); curlEasyRequest_w->finalizeRequest(mURL, mResponder->getHTTPTimeoutPolicy(), this);
} }
} }
return rv; return rv;

View File

@@ -83,6 +83,9 @@
#include "llmemtype.h" #include "llmemtype.h"
#include "llpacketring.h" #include "llpacketring.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy fnPtrResponder_timeout;
// Constants // Constants
//const char* MESSAGE_LOG_FILENAME = "message.log"; //const char* MESSAGE_LOG_FILENAME = "message.log";
static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f; static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f;
@@ -133,6 +136,8 @@ namespace
if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR); if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return fnPtrResponder_timeout; }
private: private:
void (*mCallback)(void **,S32); void (*mCallback)(void **,S32);

View File

@@ -4227,16 +4227,82 @@
<key>Value</key> <key>Value</key>
<integer>256</integer> <integer>256</integer>
</map> </map>
<key>CurlRequestTimeOut</key> <key>CurlTimeoutDNSLookup</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Max idle time of a curl request before killed (requires restart)</string> <string>Extra time in seconds added to CurlTimeoutConnect for the initial connect to a host (requires restart)</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
<string>F32</string> <string>U32</string>
<key>Value</key> <key>Value</key>
<real>120.0</real> <real>60</real>
</map>
<key>CurlTimeoutConnect</key>
<map>
<key>Comment</key>
<string>Maximum time allowed until a connection is established (after adding the easy handle) until the server is considered unreachable and the connection is terminated (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>10</real>
</map>
<key>CurlTimeoutReplyDelay</key>
<map>
<key>Comment</key>
<string>Maximum time the viewer will wait between sending data to the server and receiving (a partial) reply (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>60</real>
</map>
<key>CurlTimeoutLowSpeedLimit</key>
<map>
<key>Comment</key>
<string>If a transfer speed drops below this value (in bytes/s) during CurlTimeoutLowSpeedTime seconds, the transfer is considered too slow and is terminated (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>56000</real>
</map>
<key>CurlTimeoutLowSpeedTime</key>
<map>
<key>Comment</key>
<string>If a transfer speed drops below CurlTimeoutLowSpeedLimit (in bytes/s) during this amount of seconds, the transfer is considered too slow and is terminated (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>30</real>
</map>
<key>CurlTimeoutMaxTransaction</key>
<map>
<key>Comment</key>
<string>Maximum total time of a curl transaction, from when the easy handle is added till the transaction has completed. This INCLUDES DNS lookups (CurlTimeoutConnect), connect time (CurlTimeoutConnect) and waiting for the first server reply (CurlTimeoutReply) as well as the actually time needed for data transfer (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>300</real>
</map>
<key>CurlTimeoutMaxTotalDelay</key>
<map>
<key>Comment</key>
<string>Maximum total time of a curl request, from when it is requested till the transaction has completed. This includes queuing due to connection throttling on top of the events covered by CurlTimeoutMaxTransaction (requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<real>600</real>
</map> </map>
<key>Cursor3D</key> <key>Cursor3D</key>
<map> <map>

View File

@@ -52,6 +52,8 @@
#include "llvfile.h" #include "llvfile.h"
#include "message.h" #include "message.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy iamHereVoice_timeout;
FloaterVoiceLicense::FloaterVoiceLicense(const LLSD& key) FloaterVoiceLicense::FloaterVoiceLicense(const LLSD& key)
: LLModalDialog( std::string(" "), 100, 100 ), : LLModalDialog( std::string(" "), 100, 100 ),
@@ -73,7 +75,6 @@ class LLIamHereVoice : public LLHTTPClient::Responder
FloaterVoiceLicense* mParent; FloaterVoiceLicense* mParent;
public: public:
static boost::intrusive_ptr< LLIamHereVoice > build( FloaterVoiceLicense* parent ) static boost::intrusive_ptr< LLIamHereVoice > build( FloaterVoiceLicense* parent )
{ {
return boost::intrusive_ptr< LLIamHereVoice >( new LLIamHereVoice( parent ) ); return boost::intrusive_ptr< LLIamHereVoice >( new LLIamHereVoice( parent ) );
@@ -101,6 +102,8 @@ class LLIamHereVoice : public LLHTTPClient::Responder
mParent->setSiteIsAlive( alive ); mParent->setSiteIsAlive( alive );
} }
}; };
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return iamHereVoice_timeout; }
}; };
// this is global and not a class member to keep crud out of the header file // this is global and not a class member to keep crud out of the header file

View File

@@ -19,7 +19,6 @@
#include "hipporestrequest.h" #include "hipporestrequest.h"
// ******************************************************************** // ********************************************************************
// Global Variables // Global Variables
@@ -860,7 +859,6 @@ void HippoGridManager::loadFromFile()
setCurrentGrid(last_grid); setCurrentGrid(last_grid);
} }
void HippoGridManager::parseUrl(const std::string url, bool mergeIfNewer) void HippoGridManager::parseUrl(const std::string url, bool mergeIfNewer)
{ {
llinfos << "Loading grid info from '" << url << "'." << llendl; llinfos << "Loading grid info from '" << url << "'." << llendl;

View File

@@ -319,7 +319,7 @@ int HippoRestRequest::getBlocking(const std::string &url, std::string *result)
llassert_always(curlp); llassert_always(curlp);
curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts 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, 30); // seconds (including DNS lookups)
curl_easy_setopt(curlp, CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str()); curl_easy_setopt(curlp, CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str());
curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, curlWrite); curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, curlWrite);

View File

@@ -49,6 +49,8 @@
#include "llbufferstream.h" #include "llbufferstream.h"
class lggDicDownloadFloater; class lggDicDownloadFloater;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy emeraldDicDownloader_timeout;
class EmeraldDicDownloader : public LLHTTPClient::Responder class EmeraldDicDownloader : public LLHTTPClient::Responder
{ {
@@ -60,6 +62,7 @@ public:
const std::string& reason, const std::string& reason,
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const buffer_ptr_t& buffer); const buffer_ptr_t& buffer);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return emeraldDicDownloader_timeout; }
private: private:
lggDicDownloadFloater* panel; lggDicDownloadFloater* panel;
std::string name; std::string name;

View File

@@ -30,6 +30,9 @@
#include "llcurl.h" #include "llcurl.h"
#include "llhttpclient.h" #include "llhttpclient.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy accountingCostResponder_timeout;
//=============================================================================== //===============================================================================
LLAccountingCostManager::LLAccountingCostManager() LLAccountingCostManager::LLAccountingCostManager()
{ {
@@ -85,6 +88,8 @@ public:
clearPendingRequests(); clearPendingRequests();
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return accountingCostResponder_timeout; }
private: private:
//List of posted objects //List of posted objects
LLSD mObjectIDs; LLSD mObjectIDs;

View File

@@ -119,6 +119,7 @@
#include "lldelayeduidelete.h" #include "lldelayeduidelete.h"
#include "llbuildnewviewsscheduler.h" #include "llbuildnewviewsscheduler.h"
#include "aicurleasyrequeststatemachine.h" #include "aicurleasyrequeststatemachine.h"
#include "aihttptimeoutpolicy.h"
// </edit> // </edit>
// The files below handle dependencies from cleanup. // The files below handle dependencies from cleanup.
#include "llcalc.h" #include "llcalc.h"
@@ -642,7 +643,18 @@ bool LLAppViewer::init()
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
AIStateMachine::setMaxCount(gSavedSettings.getU32("StateMachineMaxTime")); AIStateMachine::setMaxCount(gSavedSettings.getU32("StateMachineMaxTime"));
AICurlEasyRequestStateMachine::setDefaultRequestTimeOut(gSavedSettings.getF32("CurlRequestTimeOut"));
AIHTTPTimeoutPolicy::setDefaultCurlTimeout(
AIHTTPTimeoutPolicy(
"CurlTimeout* Debug Settings",
gSavedSettings.getU32("CurlTimeoutDNSLookup"),
gSavedSettings.getU32("CurlTimeoutConnect"),
gSavedSettings.getU32("CurlTimeoutReplyDelay"),
gSavedSettings.getU32("CurlTimeoutLowSpeedTime"),
gSavedSettings.getU32("CurlTimeoutLowSpeedLimit"),
gSavedSettings.getU32("CurlTimeoutMaxTransaction"),
gSavedSettings.getU32("CurlTimeoutMaxTotalDelay")
));
initThreads(); initThreads();
LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;

View File

@@ -192,8 +192,7 @@ void on_new_single_inventory_upload_complete(
LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
const LLUUID& vfile_id, const LLUUID& vfile_id,
LLAssetType::EType asset_type) LLAssetType::EType asset_type)
: LLHTTPClient::Responder(), : mPostData(post_data),
mPostData(post_data),
mVFileID(vfile_id), mVFileID(vfile_id),
mAssetType(asset_type) mAssetType(asset_type)
{ {
@@ -210,8 +209,7 @@ LLAssetUploadResponder::LLAssetUploadResponder(
const LLSD &post_data, const LLSD &post_data,
const std::string& file_name, const std::string& file_name,
LLAssetType::EType asset_type) LLAssetType::EType asset_type)
: LLHTTPClient::Responder(), : mPostData(post_data),
mPostData(post_data),
mFileName(file_name), mFileName(file_name),
mAssetType(asset_type) mAssetType(asset_type)
{ {

View File

@@ -36,6 +36,10 @@
#include "llhttpclient.h" #include "llhttpclient.h"
#include "llinventory.h" #include "llinventory.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy assetUploadResponder_timeout;
extern AIHTTPTimeoutPolicy newAgentInventoryVariablePriceResponder_timeout;
void on_new_single_inventory_upload_complete(LLAssetType::EType asset_type, void on_new_single_inventory_upload_complete(LLAssetType::EType asset_type,
LLInventoryType::EType inventory_type, LLInventoryType::EType inventory_type,
const std::string inventory_type_string, const std::string inventory_type_string,
@@ -59,6 +63,7 @@ public:
~LLAssetUploadResponder(); ~LLAssetUploadResponder();
virtual void error(U32 statusNum, const std::string& reason); virtual void error(U32 statusNum, const std::string& reason);
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return assetUploadResponder_timeout; }
virtual void uploadUpload(const LLSD& content); virtual void uploadUpload(const LLSD& content);
virtual void uploadComplete(const LLSD& content); virtual void uploadComplete(const LLSD& content);
virtual void uploadFailure(const LLSD& content); virtual void uploadFailure(const LLSD& content);
@@ -110,6 +115,7 @@ public:
const std::string& reason, const std::string& reason,
const LLSD& content); const LLSD& content);
void result(const LLSD& content); void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return newAgentInventoryVariablePriceResponder_timeout; }
virtual void onApplicationLevelError( virtual void onApplicationLevelError(
const LLSD& error); const LLSD& error);

View File

@@ -95,12 +95,14 @@ bool LLCapabilityListener::capListener(const LLSD& request)
<< LL_ENDL; << LL_ENDL;
return false; // in case fatal-error function isn't return false; // in case fatal-error function isn't
} }
#if 0 // AIFIXME: ignore this for now
// Establish default timeout. This test relies on LLSD::asReal() returning // Establish default timeout. This test relies on LLSD::asReal() returning
// exactly 0.0 for an undef value. // exactly 0.0 for an undef value.
if (! timeout) if (! timeout)
{ {
timeout = HTTP_REQUEST_EXPIRY_SECS; timeout = HTTP_REQUEST_EXPIRY_SECS;
} }
#endif
// Look up the url for the requested capability name. // Look up the url for the requested capability name.
std::string url = mProvider.getCapability(cap); std::string url = mProvider.getCapability(cap);
if (! url.empty()) if (! url.empty())
@@ -110,8 +112,7 @@ bool LLCapabilityListener::capListener(const LLSD& request)
new LLSDMessage::EventResponder(LLEventPumps::instance(), new LLSDMessage::EventResponder(LLEventPumps::instance(),
request, request,
mProvider.getDescription(), mProvider.getDescription(),
cap, reply, error), cap, reply, error));
timeout);
} }
else else
{ {

View File

@@ -37,6 +37,9 @@
#include "llview.h" #include "llview.h"
#include "lluuid.h" #include "lluuid.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy classifiedStatsResponder_timeout;
class LLClassifiedStatsResponder : public LLHTTPClient::Responder class LLClassifiedStatsResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -45,6 +48,7 @@ public:
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
//If we get back an error (not found, etc...), handle it here //If we get back an error (not found, etc...), handle it here
virtual void error(U32 status, const std::string& reason); virtual void error(U32 status, const std::string& reason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return classifiedStatsResponder_timeout; }
protected: protected:
LLHandle<LLView> mClassifiedPanelHandle; LLHandle<LLView> mClassifiedPanelHandle;

View File

@@ -46,6 +46,9 @@
#include "message.h" #include "message.h"
#include "lltrans.h" #include "lltrans.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy eventPollResponder_timeout;
namespace namespace
{ {
// We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error. // We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
@@ -72,6 +75,7 @@ namespace
void handleMessage(const LLSD& content); void handleMessage(const LLSD& content);
virtual void error(U32 status, const std::string& reason); virtual void error(U32 status, const std::string& reason);
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return eventPollResponder_timeout; }
virtual void completedRaw(U32 status, virtual void completedRaw(U32 status,
const std::string& reason, const std::string& reason,

View File

@@ -57,6 +57,11 @@
#include "llavatarname.h" #include "llavatarname.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy muteVoiceResponder_timeout;
extern AIHTTPTimeoutPolicy muteTextResponder_timeout;
extern AIHTTPTimeoutPolicy moderationModeResponder_timeout;
using namespace LLOldEvents; using namespace LLOldEvents;
const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
@@ -882,6 +887,8 @@ void LLPanelActiveSpeakers::onModeratorMuteVoice(LLUICtrl* ctrl, void* user_data
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return muteVoiceResponder_timeout; }
private: private:
LLUUID mSessionID; LLUUID mSessionID;
}; };
@@ -947,6 +954,8 @@ void LLPanelActiveSpeakers::onModeratorMuteText(LLUICtrl* ctrl, void* user_data)
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return muteTextResponder_timeout; }
private: private:
LLUUID mSessionID; LLUUID mSessionID;
}; };
@@ -987,6 +996,7 @@ void LLPanelActiveSpeakers::onChangeModerationMode(LLUICtrl* ctrl, void* user_da
{ {
llwarns << status << ": " << reason << llendl; llwarns << status << ": " << reason << llendl;
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return moderationModeResponder_timeout; }
}; };
LLHTTPClient::post4(url, data, new ModerationModeResponder()); LLHTTPClient::post4(url, data, new ModerationModeResponder());

View File

@@ -37,6 +37,10 @@
#include "llviewerregion.h" #include "llviewerregion.h"
#include "lluictrlfactory.h" #include "lluictrlfactory.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy asyncConsoleResponder_timeout;
extern AIHTTPTimeoutPolicy consoleResponder_timeout;
// Two versions of the sim console API are supported. // Two versions of the sim console API are supported.
// //
// SimConsole capability (deprecated): // SimConsole capability (deprecated):
@@ -72,6 +76,7 @@ namespace
// This responder handles the initial response. Unless error() is called // This responder handles the initial response. Unless error() is called
// we assume that the simulator has received our request. Error will be // we assume that the simulator has received our request. Error will be
// called if this request times out. // called if this request times out.
//
class AsyncConsoleResponder : public LLHTTPClient::Responder class AsyncConsoleResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -80,6 +85,7 @@ namespace
{ {
sConsoleReplySignal(UNABLE_TO_SEND_COMMAND); sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return asyncConsoleResponder_timeout; }
}; };
class ConsoleResponder : public LLHTTPClient::Responder class ConsoleResponder : public LLHTTPClient::Responder
@@ -110,11 +116,14 @@ namespace
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return consoleResponder_timeout; }
LLTextEditor * mOutput; LLTextEditor * mOutput;
}; };
// This handles responses for console commands sent via the asynchronous // This handles responses for console commands sent via the asynchronous
// API. // API.
class ConsoleResponseNode : public LLHTTPNode class ConsoleResponseNode : public LLHTTPNode
{ {
public: public:

View File

@@ -34,6 +34,8 @@
#include "llhttpclient.h" #include "llhttpclient.h"
class LLTextEditor; class LLTextEditor;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy floaterRegionDebugConsole_timeout;
typedef boost::signals2::signal< typedef boost::signals2::signal<
void (const std::string& output)> console_reply_signal_t; void (const std::string& output)> console_reply_signal_t;
@@ -44,6 +46,8 @@ public:
LLFloaterRegionDebugConsole(); LLFloaterRegionDebugConsole();
virtual ~LLFloaterRegionDebugConsole(); virtual ~LLFloaterRegionDebugConsole();
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return floaterRegionDebugConsole_timeout; }
// virtual // virtual
BOOL postBuild(); BOOL postBuild();
void onClose(bool app_quitting); void onClose(bool app_quitting);

View File

@@ -91,6 +91,9 @@
const S32 TERRAIN_TEXTURE_COUNT = 4; const S32 TERRAIN_TEXTURE_COUNT = 4;
const S32 CORNER_COUNT = 4; const S32 CORNER_COUNT = 4;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy estateChangeInfoResponder_timeout;
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
/// Local class declaration /// Local class declaration
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
@@ -2325,6 +2328,9 @@ public:
llinfos << "LLEstateChangeInfoResponder::error " llinfos << "LLEstateChangeInfoResponder::error "
<< status << ": " << reason << llendl; << status << ": " << reason << llendl;
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return estateChangeInfoResponder_timeout; }
private: private:
LLPanelEstateInfo* mpPanel; LLPanelEstateInfo* mpPanel;
}; };

View File

@@ -96,6 +96,9 @@
const U32 INCLUDE_SCREENSHOT = 0x01 << 0; const U32 INCLUDE_SCREENSHOT = 0x01 << 0;
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy userReportResponder_timeout;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Globals // Globals
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -858,7 +861,7 @@ public:
class LLUserReportResponder : public LLHTTPClient::Responder class LLUserReportResponder : public LLHTTPClient::Responder
{ {
public: public:
LLUserReportResponder(): LLHTTPClient::Responder() {} LLUserReportResponder() { }
void error(U32 status, const std::string& reason) void error(U32 status, const std::string& reason)
{ {
@@ -870,6 +873,7 @@ public:
// we don't care about what the server returns // we don't care about what the server returns
LLUploadDialog::modalUploadFinished(); LLUploadDialog::modalUploadFinished();
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return userReportResponder_timeout; }
}; };
void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)

View File

@@ -55,6 +55,8 @@
#include "llworld.h" #include "llworld.h"
#include "pipeline.h" // for gPipeline #include "pipeline.h" // for gPipeline
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy placeAvatarTeleportResponder_timeout;
// OGPX HTTP responder for PlaceAvatar cap used for Teleport // OGPX HTTP responder for PlaceAvatar cap used for Teleport
// very similar to the responder in Login, but not as many fields are returned in the TP version // very similar to the responder in Login, but not as many fields are returned in the TP version
@@ -218,6 +220,8 @@ public:
// gViewerWindow->setShowProgress(FALSE); // gViewerWindow->setShowProgress(FALSE);
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return placeAvatarTeleportResponder_timeout; }
}; };
// Statics // Statics

View File

@@ -54,6 +54,8 @@
#include "llvfile.h" #include "llvfile.h"
#include "message.h" #include "message.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy iamHere_timeout;
// static // static
LLFloaterTOS* LLFloaterTOS::sInstance = NULL; LLFloaterTOS* LLFloaterTOS::sInstance = NULL;
@@ -128,6 +130,8 @@ class LLIamHere : public LLHTTPClient::Responder
mParent->setSiteIsAlive( alive ); mParent->setSiteIsAlive( alive );
} }
}; };
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return iamHere_timeout; }
}; };
// this is global and not a class member to keep crud out of the header file // this is global and not a class member to keep crud out of the header file

View File

@@ -45,6 +45,9 @@
#include "llviewerwindow.h" #include "llviewerwindow.h"
#include "llhttpclient.h" #include "llhttpclient.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy mediaTypeResponder_timeout;
static LLFloaterURLEntry* sInstance = NULL; static LLFloaterURLEntry* sInstance = NULL;
// Move this to its own file. // Move this to its own file.
@@ -85,6 +88,8 @@ public:
if ( floater_url_entry ) if ( floater_url_entry )
floater_url_entry->headerFetchComplete( status, resolved_mime_type ); floater_url_entry->headerFetchComplete( status, resolved_mime_type );
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return mediaTypeResponder_timeout; }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -38,11 +38,15 @@
/* File Inclusions */ /* File Inclusions */
#include "llhttpclient.h" #include "llhttpclient.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy homeLocationResponder_timeout;
/* Typedef, Enum, Class, Struct, etc. */ /* Typedef, Enum, Class, Struct, etc. */
class LLHomeLocationResponder : public LLHTTPClient::Responder class LLHomeLocationResponder : public LLHTTPClient::Responder
{ {
virtual void result( const LLSD& content ); virtual void result( const LLSD& content );
virtual void error( U32 status, const std::string& reason ); virtual void error( U32 status, const std::string& reason );
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return homeLocationResponder_timeout; }
}; };
#endif #endif

View File

@@ -84,6 +84,11 @@
#include "rlvhandler.h" #include "rlvhandler.h"
// [/RLVa:KB] // [/RLVa:KB]
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy startConferenceChatResponder_timeout;
extern AIHTTPTimeoutPolicy voiceCallCapResponder_timeout;
extern AIHTTPTimeoutPolicy sessionInviteResponder_timeout;
// //
// Constants // Constants
// //
@@ -214,6 +219,8 @@ public:
//the possible different language translations //the possible different language translations
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return startConferenceChatResponder_timeout; }
private: private:
LLUUID mTempSessionID; LLUUID mTempSessionID;
LLUUID mCreatorID; LLUUID mCreatorID;
@@ -301,6 +308,7 @@ public:
virtual void error(U32 status, const std::string& reason); // called with bad status codes virtual void error(U32 status, const std::string& reason); // called with bad status codes
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return voiceCallCapResponder_timeout; }
private: private:
LLUUID mSessionID; LLUUID mSessionID;
@@ -1564,6 +1572,8 @@ public:
//throw something back to the viewer here? //throw something back to the viewer here?
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return sessionInviteResponder_timeout; }
private: private:
LLUUID mSessionID; LLUUID mSessionID;
}; };

View File

@@ -77,6 +77,9 @@
#include "rlvhandler.h" #include "rlvhandler.h"
// [/RLVa:KB] // [/RLVa:KB]
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy viewerChatterBoxInvitationAcceptResponder_timeout;
// //
// Globals // Globals
// //
@@ -91,7 +94,6 @@ LLIMMgr* gIMMgr = NULL;
//{ //{
// return (LLStringUtil::compareDict( a->mName, b->mName ) < 0); // return (LLStringUtil::compareDict( a->mName, b->mName ) < 0);
//} //}
class LLViewerChatterBoxInvitationAcceptResponder : class LLViewerChatterBoxInvitationAcceptResponder :
public LLHTTPClient::Responder public LLHTTPClient::Responder
{ {
@@ -175,6 +177,8 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return viewerChatterBoxInvitationAcceptResponder_timeout; }
private: private:
LLUUID mSessionID; LLUUID mSessionID;
LLIMMgr::EInvitationType mInvitiationType; LLIMMgr::EInvitationType mInvitiationType;

View File

@@ -60,6 +60,9 @@
#include "process.h" #include "process.h"
#endif #endif
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy createInventoryCategoryResponder_timeout;
// Increment this if the inventory contents change in a non-backwards-compatible way. // Increment this if the inventory contents change in a non-backwards-compatible way.
// For viewers with link items support, former caches are incorrect. // For viewers with link items support, former caches are incorrect.
const S32 LLInventoryModel::sCurrentInvCacheVersion = 2; const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
@@ -511,6 +514,8 @@ public:
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return createInventoryCategoryResponder_timeout; }
private: private:
void (*mCallback)(const LLSD&, void*); void (*mCallback)(const LLSD&, void*);
void* mData; void* mData;

View File

@@ -43,8 +43,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
class LLInventoryObserver; class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy fetchInventoryResponder_timeout;
class LLInventoryObserver;
class LLInventoryObject; class LLInventoryObject;
class LLInventoryItem; class LLInventoryItem;
class LLInventoryCategory; class LLInventoryCategory;
@@ -55,7 +57,6 @@ class LLViewerInventoryCategory;
class LLMessageSystem; class LLMessageSystem;
class LLInventoryCollectFunctor; class LLInventoryCollectFunctor;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLInventoryModel // LLInventoryModel
// //
@@ -88,6 +89,7 @@ public:
fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
void result(const LLSD& content); void result(const LLSD& content);
void error(U32 status, const std::string& reason); void error(U32 status, const std::string& reason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return fetchInventoryResponder_timeout; }
protected: protected:
LLSD mRequestSD; LLSD mRequestSD;
}; };

View File

@@ -38,6 +38,10 @@
#include "llviewerregion.h" #include "llviewerregion.h"
#include "llviewerwindow.h" #include "llviewerwindow.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy inventoryModelFetchDescendentsResponder_timeout;
extern AIHTTPTimeoutPolicy inventoryModelFetchItemResponder_timeout;
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
const S32 MAX_FETCH_RETRIES = 10; const S32 MAX_FETCH_RETRIES = 10;
@@ -374,6 +378,7 @@ public:
LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
void result(const LLSD& content); void result(const LLSD& content);
void error(U32 status, const std::string& reason); void error(U32 status, const std::string& reason);
AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return inventoryModelFetchItemResponder_timeout; }
}; };
void LLInventoryModelFetchItemResponder::result( const LLSD& content ) void LLInventoryModelFetchItemResponder::result( const LLSD& content )
@@ -388,7 +393,6 @@ void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& r
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
} }
class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
{ {
public: public:
@@ -399,6 +403,8 @@ class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
//LLInventoryModelFetchDescendentsResponder() {}; //LLInventoryModelFetchDescendentsResponder() {};
void result(const LLSD& content); void result(const LLSD& content);
void error(U32 status, const std::string& reason); void error(U32 status, const std::string& reason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return inventoryModelFetchDescendentsResponder_timeout; }
protected: protected:
BOOL getIsRecursive(const LLUUID& cat_id) const; BOOL getIsRecursive(const LLUUID& cat_id) const;
private: private:
@@ -699,14 +705,14 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
if (folder_request_body["folders"].size()) if (folder_request_body["folders"].size())
{ {
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
LLHTTPClient::post4(url, folder_request_body, fetcher, 300.0); LLHTTPClient::post4(url, folder_request_body, fetcher);
} }
if (folder_request_body_lib["folders"].size()) if (folder_request_body_lib["folders"].size())
{ {
std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
LLHTTPClient::post4(url_lib, folder_request_body_lib, fetcher, 300.0); LLHTTPClient::post4(url_lib, folder_request_body_lib, fetcher);
} }
} }
if (item_count) if (item_count)

View File

@@ -35,9 +35,13 @@
#include "llhttpclient.h" #include "llhttpclient.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy mapLayerResponder_timeout;
class LLMapLayerResponder : public LLHTTPClient::Responder class LLMapLayerResponder : public LLHTTPClient::Responder
{ {
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return mapLayerResponder_timeout; }
}; };
#endif // LL_LLMAPLAYERRESPONDER_H #endif // LL_LLMAPLAYERRESPONDER_H

View File

@@ -74,6 +74,15 @@
#include <queue> #include <queue>
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy meshHeaderResponder_timeout;
extern AIHTTPTimeoutPolicy meshLODResponder_timeout;
extern AIHTTPTimeoutPolicy meshSkinInfoResponder_timeout;
extern AIHTTPTimeoutPolicy meshDecompositionResponder_timeout;
extern AIHTTPTimeoutPolicy meshPhysicsShapeResponder_timeout;
extern AIHTTPTimeoutPolicy wholeModelFeeResponder_timeout;
extern AIHTTPTimeoutPolicy wholeModelUploadResponder_timeout;
LLMeshRepository gMeshRepo; LLMeshRepository gMeshRepo;
const U32 MAX_MESH_REQUESTS_PER_SECOND = 100; const U32 MAX_MESH_REQUESTS_PER_SECOND = 100;
@@ -221,6 +230,7 @@ public:
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer); const LLIOPipe::buffer_ptr_t& buffer);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshHeaderResponder_timeout; }
}; };
class LLMeshLODResponder : public LLCurl::Responder class LLMeshLODResponder : public LLCurl::Responder
@@ -246,6 +256,7 @@ public:
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer); const LLIOPipe::buffer_ptr_t& buffer);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshLODResponder_timeout; }
}; };
class LLMeshSkinInfoResponder : public LLCurl::Responder class LLMeshSkinInfoResponder : public LLCurl::Responder
@@ -264,6 +275,7 @@ public:
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer); const LLIOPipe::buffer_ptr_t& buffer);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshSkinInfoResponder_timeout; }
}; };
class LLMeshDecompositionResponder : public LLCurl::Responder class LLMeshDecompositionResponder : public LLCurl::Responder
@@ -282,6 +294,7 @@ public:
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer); const LLIOPipe::buffer_ptr_t& buffer);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshDecompositionResponder_timeout; }
}; };
class LLMeshPhysicsShapeResponder : public LLCurl::Responder class LLMeshPhysicsShapeResponder : public LLCurl::Responder
@@ -300,6 +313,7 @@ public:
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer); const LLIOPipe::buffer_ptr_t& buffer);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return meshPhysicsShapeResponder_timeout; }
}; };
#if MESH_IMPORT #if MESH_IMPORT
@@ -403,6 +417,7 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return wholeModelFeeResponder_timeout; }
}; };
class LLWholeModelUploadResponder: public LLCurl::Responder class LLWholeModelUploadResponder: public LLCurl::Responder
@@ -459,6 +474,8 @@ public:
} }
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return wholeModelUploadResponder_timeout; }
}; };
#endif //MESH_IMPORT #endif //MESH_IMPORT

View File

@@ -52,6 +52,10 @@
#include "llviewerwindow.h" #include "llviewerwindow.h"
#include "llviewerregion.h" #include "llviewerregion.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy startGroupVoteResponder_timeout;
extern AIHTTPTimeoutPolicy groupProposalBallotResponder_timeout;
class LLPanelGroupVoting::impl class LLPanelGroupVoting::impl
{ {
public: public:
@@ -705,6 +709,10 @@ public:
LLPanelGroupVoting::handleFailure(mGroupID); LLPanelGroupVoting::handleFailure(mGroupID);
} }
//Return our timeout policy.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return startGroupVoteResponder_timeout; }
private: private:
LLUUID mGroupID; LLUUID mGroupID;
}; };
@@ -735,6 +743,10 @@ public:
LLPanelGroupVoting::handleFailure(mGroupID); LLPanelGroupVoting::handleFailure(mGroupID);
} }
//Return out timeout policy.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return groupProposalBallotResponder_timeout; }
private: private:
LLUUID mGroupID; LLUUID mGroupID;
}; };
@@ -781,8 +793,7 @@ void LLPanelGroupVoting::impl::sendStartGroupProposal()
LLHTTPClient::post4( LLHTTPClient::post4(
url, url,
body, body,
new LLStartGroupVoteResponder(mGroupID), new LLStartGroupVoteResponder(mGroupID));
300);
} }
else else
{ //DEPRECATED!!!!!!! This is a fallback just in case our backend cap is not there. Delete this block ASAP! { //DEPRECATED!!!!!!! This is a fallback just in case our backend cap is not there. Delete this block ASAP!
@@ -828,8 +839,7 @@ void LLPanelGroupVoting::impl::sendGroupProposalBallot(const std::string& vote)
LLHTTPClient::post4( LLHTTPClient::post4(
url, url,
body, body,
new LLGroupProposalBallotResponder(mGroupID), new LLGroupProposalBallotResponder(mGroupID));
300);
} }
else else
{ //DEPRECATED!!!!!!! This is a fallback just in case our backend cap is not there. Delete this block ASAP! { //DEPRECATED!!!!!!! This is a fallback just in case our backend cap is not there. Delete this block ASAP!

View File

@@ -95,6 +95,9 @@
#define USE_VIEWER_AUTH 0 #define USE_VIEWER_AUTH 0
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy iamHereLogin_timeout;
const S32 BLACK_BORDER_HEIGHT = 160; const S32 BLACK_BORDER_HEIGHT = 160;
const S32 MAX_PASSWORD = 16; const S32 MAX_PASSWORD = 16;
@@ -204,6 +207,8 @@ class LLIamHereLogin : public LLHTTPClient::Responder
if ( mParent ) if ( mParent )
mParent->setSiteIsAlive( false ); mParent->setSiteIsAlive( false );
}; };
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return iamHereLogin_timeout; }
}; };
// this is global and not a class member to keep crud out of the header file // this is global and not a class member to keep crud out of the header file

View File

@@ -56,6 +56,15 @@
#include "llviewerregion.h" #include "llviewerregion.h"
#include "llweb.h" #include "llweb.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy navMeshStatusResponder_timeout;
extern AIHTTPTimeoutPolicy navMeshResponder_timeout;
extern AIHTTPTimeoutPolicy agentStateResponder_timeout;
extern AIHTTPTimeoutPolicy navMeshRebakeResponder_timeout;
extern AIHTTPTimeoutPolicy objectLinksetsResponder_timeout;
extern AIHTTPTimeoutPolicy terrainLinksetsResponder_timeout;
extern AIHTTPTimeoutPolicy charactersResponder_timeout;
#define CAP_SERVICE_RETRIEVE_NAVMESH "RetrieveNavMeshSrc" #define CAP_SERVICE_RETRIEVE_NAVMESH "RetrieveNavMeshSrc"
#define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus" #define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus"
@@ -109,6 +118,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string& pReason); virtual void error(U32 pStatus, const std::string& pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return navMeshStatusResponder_timeout; }
protected: protected:
@@ -131,6 +141,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string& pReason); virtual void error(U32 pStatus, const std::string& pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return navMeshResponder_timeout; }
protected: protected:
@@ -152,6 +163,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string& pReason); virtual void error(U32 pStatus, const std::string& pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return agentStateResponder_timeout; }
protected: protected:
@@ -171,6 +183,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string& pReason); virtual void error(U32 pStatus, const std::string& pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return navMeshRebakeResponder_timeout; }
protected: protected:
@@ -222,7 +235,6 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// ObjectLinksetsResponder // ObjectLinksetsResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class ObjectLinksetsResponder : public LLHTTPClient::Responder class ObjectLinksetsResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -231,6 +243,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string &pReason); virtual void error(U32 pStatus, const std::string &pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return objectLinksetsResponder_timeout; }
protected: protected:
@@ -242,7 +255,6 @@ private:
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// TerrainLinksetsResponder // TerrainLinksetsResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class TerrainLinksetsResponder : public LLHTTPClient::Responder class TerrainLinksetsResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -251,6 +263,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string &pReason); virtual void error(U32 pStatus, const std::string &pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return terrainLinksetsResponder_timeout; }
protected: protected:
@@ -262,7 +275,6 @@ private:
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// CharactersResponder // CharactersResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class CharactersResponder : public LLHTTPClient::Responder class CharactersResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -271,6 +283,7 @@ public:
virtual void result(const LLSD &pContent); virtual void result(const LLSD &pContent);
virtual void error(U32 pStatus, const std::string &pReason); virtual void error(U32 pStatus, const std::string &pReason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return charactersResponder_timeout; }
protected: protected:
@@ -778,8 +791,7 @@ void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, c
// NavMeshStatusResponder // NavMeshStatusResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly) NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly) :
: LLHTTPClient::Responder(),
mCapabilityURL(pCapabilityURL), mCapabilityURL(pCapabilityURL),
mRegion(pRegion), mRegion(pRegion),
mRegionUUID(), mRegionUUID(),
@@ -812,8 +824,7 @@ void NavMeshStatusResponder::error(U32 pStatus, const std::string& pReason)
// NavMeshResponder // NavMeshResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) :
: LLHTTPClient::Responder(),
mCapabilityURL(pCapabilityURL), mCapabilityURL(pCapabilityURL),
mNavMeshVersion(pNavMeshVersion), mNavMeshVersion(pNavMeshVersion),
mNavMeshPtr(pNavMeshPtr) mNavMeshPtr(pNavMeshPtr)
@@ -838,9 +849,7 @@ void NavMeshResponder::error(U32 pStatus, const std::string& pReason)
// AgentStateResponder // AgentStateResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL) AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL) : mCapabilityURL(pCapabilityURL)
: LLHTTPClient::Responder()
, mCapabilityURL(pCapabilityURL)
{ {
} }
@@ -866,8 +875,7 @@ void AgentStateResponder::error(U32 pStatus, const std::string &pReason)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// navmesh rebake responder // navmesh rebake responder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) :
: LLHTTPClient::Responder(),
mCapabilityURL(pCapabilityURL), mCapabilityURL(pCapabilityURL),
mRebakeNavMeshCallback(pRebakeNavMeshCallback) mRebakeNavMeshCallback(pRebakeNavMeshCallback)
{ {
@@ -973,8 +981,7 @@ void LinksetsResponder::sendCallback()
// ObjectLinksetsResponder // ObjectLinksetsResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) :
: LLHTTPClient::Responder(),
mCapabilityURL(pCapabilityURL), mCapabilityURL(pCapabilityURL),
mLinksetsResponsderPtr(pLinksetsResponsderPtr) mLinksetsResponsderPtr(pLinksetsResponsderPtr)
{ {
@@ -998,8 +1005,7 @@ void ObjectLinksetsResponder::error(U32 pStatus, const std::string &pReason)
// TerrainLinksetsResponder // TerrainLinksetsResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) :
: LLHTTPClient::Responder(),
mCapabilityURL(pCapabilityURL), mCapabilityURL(pCapabilityURL),
mLinksetsResponsderPtr(pLinksetsResponsderPtr) mLinksetsResponsderPtr(pLinksetsResponsderPtr)
{ {
@@ -1023,8 +1029,7 @@ void TerrainLinksetsResponder::error(U32 pStatus, const std::string &pReason)
// CharactersResponder // CharactersResponder
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) :
: LLHTTPClient::Responder(),
mCapabilityURL(pCapabilityURL), mCapabilityURL(pCapabilityURL),
mRequestId(pRequestId), mRequestId(pRequestId),
mCharactersCallback(pCharactersCallback) mCharactersCallback(pCharactersCallback)

View File

@@ -39,6 +39,9 @@
#include "lltrans.h" #include "lltrans.h"
#include "llviewerregion.h" #include "llviewerregion.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy productInfoRequestResponder_timeout;
class LLProductInfoRequestResponder : public LLHTTPClient::Responder class LLProductInfoRequestResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -54,6 +57,8 @@ public:
llwarns << "LLProductInfoRequest::error(" llwarns << "LLProductInfoRequest::error("
<< status << ": " << reason << ")" << llendl; << status << ": " << reason << ")" << llendl;
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return productInfoRequestResponder_timeout; }
}; };
LLProductInfoRequestManager::LLProductInfoRequestManager() : mSkuDescriptions() LLProductInfoRequestManager::LLProductInfoRequestManager() : mSkuDescriptions()

View File

@@ -38,6 +38,9 @@
#include "llhttpclient.h" #include "llhttpclient.h"
#include "llpanel.h" #include "llpanel.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy remoteParcelRequestResponder_timeout;
class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -46,6 +49,7 @@ public:
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
//If we get back an error (not found, etc...), handle it here //If we get back an error (not found, etc...), handle it here
virtual void error(U32 status, const std::string& reason); virtual void error(U32 status, const std::string& reason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return remoteParcelRequestResponder_timeout; }
protected: protected:
LLHandle<LLPanel> mPlacePanelHandle; LLHandle<LLPanel> mPlacePanelHandle;

View File

@@ -54,6 +54,10 @@
#include "llstartup.h" #include "llstartup.h"
#include "llbuffer.h" #include "llbuffer.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout;
extern AIHTTPTimeoutPolicy lcl_responder_timeout;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
class LLTextureFetchWorker : public LLWorkerClass class LLTextureFetchWorker : public LLWorkerClass
{ {
@@ -288,7 +292,6 @@ private:
}; };
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
class HTTPGetResponder : public LLCurl::Responder class HTTPGetResponder : public LLCurl::Responder
{ {
LOG_CLASS(HTTPGetResponder); LOG_CLASS(HTTPGetResponder);
@@ -301,6 +304,8 @@ public:
{ {
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return HTTPGetResponder_timeout; }
virtual void completedRaw(U32 status, const std::string& reason, virtual void completedRaw(U32 status, const std::string& reason,
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
const buffer_ptr_t& buffer) const buffer_ptr_t& buffer)
@@ -3036,8 +3041,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
volatile const S32 & live_sequence, volatile const S32 & live_sequence,
volatile bool & reporting_break, volatile bool & reporting_break,
volatile bool & reporting_started) volatile bool & reporting_started)
: LLCurl::Responder(), : mFetcher(fetcher),
mFetcher(fetcher),
mExpectedSequence(expected_sequence), mExpectedSequence(expected_sequence),
mLiveSequence(live_sequence), mLiveSequence(live_sequence),
mReportingBreak(reporting_break), mReportingBreak(reporting_break),
@@ -3071,6 +3075,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
mReportingStarted = true; mReportingStarted = true;
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return lcl_responder_timeout; }
private: private:
LLTextureFetch * mFetcher; LLTextureFetch * mFetcher;

View File

@@ -37,6 +37,9 @@
#include "llbufferstream.h" #include "llbufferstream.h"
#include "json/reader.h" #include "json/reader.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy translationReceiver_timeout;
class LLTranslate class LLTranslate
{ {
public : public :
@@ -63,6 +66,8 @@ public :
handleFailure(); handleFailure();
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return translationReceiver_timeout; }
virtual void completedRaw( virtual void completedRaw(
U32 status, U32 status,
const std::string& reason, const std::string& reason,

View File

@@ -37,6 +37,9 @@
#include "llhttpclient.h" #include "llhttpclient.h"
#include "llui.h" #include "llui.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy uploadModelPremissionsResponder_timeout;
class LLUploadPermissionsObserver class LLUploadPermissionsObserver
{ {
public: public:
@@ -105,6 +108,8 @@ public:
void result(const LLSD& content); void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return uploadModelPremissionsResponder_timeout; }
private: private:
LLHandle<LLUploadPermissionsObserver> mObserverHandle; LLHandle<LLUploadPermissionsObserver> mObserverHandle;
}; };

View File

@@ -40,6 +40,9 @@
#include "llnotificationsutil.h" #include "llnotificationsutil.h"
#include "llui.h" // getLanguage() #include "llui.h" // getLanguage()
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy setDisplayNameResponder_timeout;
namespace LLViewerDisplayName namespace LLViewerDisplayName
{ {
// Fired when viewer receives server response to display name change // Fired when viewer receives server response to display name change
@@ -64,6 +67,8 @@ public:
LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return setDisplayNameResponder_timeout; }
}; };
void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot) void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot)

View File

@@ -59,6 +59,11 @@
#include "llfloateravatarinfo.h" // for getProfileURL() function #include "llfloateravatarinfo.h" // for getProfileURL() function
//#include "viewerversion.h" //#include "viewerversion.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy mimeDiscoveryResponder_timeout;
extern AIHTTPTimeoutPolicy viewerMediaOpenIDResponder_timeout;
extern AIHTTPTimeoutPolicy viewerMediaWebProfileResponder_timeout;
// Merov: Temporary definitions while porting the new viewer media code to Snowglobe // Merov: Temporary definitions while porting the new viewer media code to Snowglobe
const int LEFT_BUTTON = 0; const int LEFT_BUTTON = 0;
const int RIGHT_BUTTON = 1; const int RIGHT_BUTTON = 1;
@@ -99,6 +104,8 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return mimeDiscoveryResponder_timeout; }
public: public:
viewer_media_t mMediaImpl; viewer_media_t mMediaImpl;
bool mInitialized; bool mInitialized;
@@ -139,6 +146,7 @@ public:
// We don't care about the content of the response, only the set-cookie header. // We don't care about the content of the response, only the set-cookie header.
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return viewerMediaOpenIDResponder_timeout; }
}; };
class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
@@ -168,7 +176,7 @@ public:
} }
} }
void completedRaw( void completedRaw(
U32 status, U32 status,
const std::string& reason, const std::string& reason,
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -178,6 +186,8 @@ public:
// We don't care about the content of the response, only the set-cookie header. // We don't care about the content of the response, only the set-cookie header.
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return viewerMediaWebProfileResponder_timeout; }
std::string mHost; std::string mHost;
}; };

View File

@@ -92,6 +92,10 @@ extern ImportTracker gImportTracker;
void dialog_refresh_all(); void dialog_refresh_all();
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy objectCostResponder_timeout;
extern AIHTTPTimeoutPolicy physicsFlagsResponder_timeout;
#define CULL_VIS #define CULL_VIS
//#define ORPHAN_SPAM //#define ORPHAN_SPAM
//#define IGNORE_DEAD //#define IGNORE_DEAD
@@ -768,11 +772,12 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return objectCostResponder_timeout; }
private: private:
LLSD mObjectIDs; LLSD mObjectIDs;
}; };
class LLPhysicsFlagsResponder : public LLCurl::Responder class LLPhysicsFlagsResponder : public LLCurl::Responder
{ {
public: public:
@@ -864,6 +869,8 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return physicsFlagsResponder_timeout; }
private: private:
LLSD mObjectIDs; LLSD mObjectIDs;
}; };

View File

@@ -82,13 +82,16 @@
#pragma warning(disable:4355) #pragma warning(disable:4355)
#endif #endif
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy baseCapabilitiesComplete_timeout;
extern AIHTTPTimeoutPolicy simulatorFeaturesReceived_timeout;
const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region const F32 WATER_TEXTURE_SCALE = 8.f; // Number of times to repeat the water texture across a region
const S16 MAX_MAP_DIST = 10; const S16 MAX_MAP_DIST = 10;
// The server only keeps our pending agent info for 60 seconds. // The server only keeps our pending agent info for 60 seconds.
// We want to allow for seed cap retry, but its not useful after that 60 seconds. // We want to allow for seed cap retry, but its not useful after that 60 seconds.
// Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up. // Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up.
const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3; const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3;
const F32 CAP_REQUEST_TIMEOUT = 18;
// Even though we gave up on login, keep trying for caps after we are logged in: // Even though we gave up on login, keep trying for caps after we are logged in:
const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
@@ -262,6 +265,8 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return baseCapabilitiesComplete_timeout; }
static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id ) static boost::intrusive_ptr<BaseCapabilitiesComplete> build( U64 region_handle, S32 id )
{ {
return boost::intrusive_ptr<BaseCapabilitiesComplete>( return boost::intrusive_ptr<BaseCapabilitiesComplete>(
@@ -1662,8 +1667,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
S32 id = ++mImpl->mHttpResponderID; S32 id = ++mImpl->mHttpResponderID;
LLHTTPClient::post4(url, capabilityNames, LLHTTPClient::post4(url, capabilityNames,
BaseCapabilitiesComplete::build(getHandle(), id), BaseCapabilitiesComplete::build(getHandle(), id));
CAP_REQUEST_TIMEOUT);
} }
S32 LLViewerRegion::getNumSeedCapRetries() S32 LLViewerRegion::getNumSeedCapRetries()
@@ -1698,8 +1702,7 @@ void LLViewerRegion::failedSeedCapability()
S32 id = ++mImpl->mHttpResponderID; S32 id = ++mImpl->mHttpResponderID;
LLHTTPClient::post4(url, capabilityNames, LLHTTPClient::post4(url, capabilityNames,
BaseCapabilitiesComplete::build(getHandle(), id), BaseCapabilitiesComplete::build(getHandle(), id));
CAP_REQUEST_TIMEOUT);
} }
else else
{ {
@@ -1736,6 +1739,8 @@ public:
regionp->setSimulatorFeatures(content); regionp->setSimulatorFeatures(content);
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return simulatorFeaturesReceived_timeout; }
private: private:
void retry() void retry()
{ {
@@ -1743,7 +1748,7 @@ private:
{ {
mAttempt++; mAttempt++;
LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL; LL_WARNS2("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'. Retry #" << mAttempt << LL_ENDL;
LLHTTPClient::get4(mRetryURL, new SimulatorFeaturesReceived(*this), CAP_REQUEST_TIMEOUT); LLHTTPClient::get4(mRetryURL, new SimulatorFeaturesReceived(*this));
} }
} }
@@ -1769,7 +1774,7 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
else if (name == "SimulatorFeatures") else if (name == "SimulatorFeatures")
{ {
// kick off a request for simulator features // kick off a request for simulator features
LLHTTPClient::get4(url, new SimulatorFeaturesReceived(url, getHandle()), CAP_REQUEST_TIMEOUT); LLHTTPClient::get4(url, new SimulatorFeaturesReceived(url, getHandle()));
} }
else else
{ {

View File

@@ -63,6 +63,8 @@
#include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived
#include "sgmemstat.h" #include "sgmemstat.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy viewerStatsResponder_timeout;
class StatAttributes class StatAttributes
{ {
@@ -710,6 +712,8 @@ public:
{ {
llinfos << "ViewerStatsResponder::result" << llendl; llinfos << "ViewerStatsResponder::result" << llendl;
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return viewerStatsResponder_timeout; }
}; };
/* /*

View File

@@ -113,6 +113,7 @@
// <edit> // <edit>
#include "llfloaterexploreanimations.h" #include "llfloaterexploreanimations.h"
#include "llimagemetadatareader.h" #include "llimagemetadatareader.h"
#include "aihttptimeoutpolicy.h"
// </edit> // </edit>
#include "llavatarname.h" #include "llavatarname.h"

View File

@@ -82,6 +82,10 @@
#define USE_SESSION_GROUPS 0 #define USE_SESSION_GROUPS 0
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy viewerVoiceAccountProvisionResponder_timeout;
extern AIHTTPTimeoutPolicy voiceClientCapResponder_timeout;
static bool sConnectingToAgni = false; static bool sConnectingToAgni = false;
F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f; F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
@@ -187,6 +191,8 @@ public:
} }
} }
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return viewerVoiceAccountProvisionResponder_timeout; }
private: private:
int mRetries; int mRetries;
}; };
@@ -1008,7 +1014,6 @@ static bool sMuteListListener_listening = false;
static LLVoiceClientFriendsObserver *friendslist_listener = NULL; static LLVoiceClientFriendsObserver *friendslist_listener = NULL;
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
class LLVoiceClientCapResponder : public LLHTTPClient::Responder class LLVoiceClientCapResponder : public LLHTTPClient::Responder
{ {
public: public:
@@ -1016,6 +1021,7 @@ public:
virtual void error(U32 status, const std::string& reason); // called with bad status codes virtual void error(U32 status, const std::string& reason); // called with bad status codes
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return voiceClientCapResponder_timeout; }
private: private:
}; };

View File

@@ -36,6 +36,10 @@
#include "llviewerprecompiledheaders.h" #include "llviewerprecompiledheaders.h"
#include "llhttpclient.h" #include "llhttpclient.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy environmentRequestResponder_timeout;
extern AIHTTPTimeoutPolicy environmentApplyResponder_timeout;
class LLEnvironmentRequest class LLEnvironmentRequest
{ {
LOG_CLASS(LLEnvironmentRequest); LOG_CLASS(LLEnvironmentRequest);
@@ -54,6 +58,7 @@ class LLEnvironmentRequestResponder: public LLHTTPClient::Responder
public: public:
virtual void result(const LLSD& content); virtual void result(const LLSD& content);
virtual void error(U32 status, const std::string& reason); virtual void error(U32 status, const std::string& reason);
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return environmentRequestResponder_timeout; }
private: private:
friend class LLEnvironmentRequest; friend class LLEnvironmentRequest;
@@ -97,6 +102,8 @@ public:
virtual void error(U32 status, const std::string& reason); // non-200 errors only virtual void error(U32 status, const std::string& reason); // non-200 errors only
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return environmentApplyResponder_timeout; }
private: private:
friend class LLEnvironmentApply; friend class LLEnvironmentApply;

View File

@@ -49,6 +49,9 @@
#include <libcwd/buf2str.h> #include <libcwd/buf2str.h>
#endif #endif
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy XMLRPCTransaction_timeout;
LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const
{ {
return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id)); return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id));
@@ -232,7 +235,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
{ {
try try
{ {
mCurlEasyRequestStateMachinePtr = new AICurlEasyRequestStateMachine(false); mCurlEasyRequestStateMachinePtr = new AICurlEasyRequestStateMachine(false); // AIFIXME: This is the only unbuffered AICurlEasyRequestStateMachine left.
} }
catch(AICurlNoEasyHandle const& error) catch(AICurlNoEasyHandle const& error)
{ {
@@ -246,8 +249,6 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert"); BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
curlEasyRequest_w->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert); curlEasyRequest_w->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert);
curlEasyRequest_w->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0); curlEasyRequest_w->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0);
// Be a little impatient about establishing connections.
curlEasyRequest_w->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
/* Setting the DNS cache timeout to -1 disables it completely. /* Setting the DNS cache timeout to -1 disables it completely.
This might help with bug #503 */ This might help with bug #503 */
@@ -271,7 +272,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
setStatus(StatusOtherError); setStatus(StatusOtherError);
} }
curlEasyRequest_w->finalizeRequest(mURI); curlEasyRequest_w->finalizeRequest(mURI, XMLRPCTransaction_timeout, mCurlEasyRequestStateMachinePtr);
} }
if (mStatus == LLXMLRPCTransaction::StatusNotStarted) // It could be LLXMLRPCTransaction::StatusOtherError. if (mStatus == LLXMLRPCTransaction::StatusNotStarted) // It could be LLXMLRPCTransaction::StatusOtherError.
{ {
@@ -479,10 +480,13 @@ size_t LLXMLRPCTransaction::Impl::curlDownloadCallback(
size_t n = size * nmemb; size_t n = size * nmemb;
#ifdef CWDEBUG #ifdef CWDEBUG
void* lockobj = impl.mCurlEasyRequestStateMachinePtr ? impl.mCurlEasyRequestStateMachinePtr->mCurlEasyRequest.get_ptr().get() : NULL;
if (n < 80) if (n < 80)
Dout(dc::curl, "Entering LLXMLRPCTransaction::Impl::curlDownloadCallback(\"" << buf2str(data, n) << "\", " << size << ", " << nmemb << ", " << user_data << ")"); Dout(dc::curl, "Entering LLXMLRPCTransaction::Impl::curlDownloadCallback(\"" <<
buf2str(data, n) << "\", " << size << ", " << nmemb << ", " << user_data << ") [" << lockobj << ']');
else else
Dout(dc::curl, "Entering LLXMLRPCTransaction::Impl::curlDownloadCallback(\"" << buf2str(data, 40) << "\"...\"" << buf2str(data + n - 40, 40) << "\", " << size << ", " << nmemb << ", " << user_data << ")"); Dout(dc::curl, "Entering LLXMLRPCTransaction::Impl::curlDownloadCallback(\"" <<
buf2str(data, 40) << "\"...\"" << buf2str(data + n - 40, 40) << "\", " << size << ", " << nmemb << ", " << user_data << ") [" << lockobj << ']');
#endif #endif
impl.mResponseText.append(data, n); impl.mResponseText.append(data, n);