Compare commits
19 Commits
curlthread
...
breakforce
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
761439cc8d | ||
|
|
08d72b12ab | ||
|
|
4650636e5a | ||
|
|
725cdc2d69 | ||
|
|
048c57cf0c | ||
|
|
12dcbfbc79 | ||
|
|
32be05fa6c | ||
|
|
ae62b67554 | ||
|
|
9c4f22d85b | ||
|
|
7f64668e55 | ||
|
|
0208942b84 | ||
|
|
783e86990c | ||
|
|
c9715c5b0b | ||
|
|
dd47123bde | ||
|
|
3de21156b5 | ||
|
|
ce2c6ab49e | ||
|
|
d19c5a4a4a | ||
|
|
8945fe4857 | ||
|
|
464919072d |
@@ -34,6 +34,8 @@ if(NOT WORD_SIZE EQUAL 32)
|
||||
endif(WINDOWS)
|
||||
endif (NOT WORD_SIZE EQUAL 32)
|
||||
|
||||
add_definitions(-Dcwdebug_EXPORTS)
|
||||
|
||||
list(APPEND cwdebug_SOURCE_FILES ${cwdebug_HEADER_FILES})
|
||||
|
||||
add_library (cwdebug ${cwdebug_SOURCE_FILES})
|
||||
|
||||
@@ -413,4 +413,71 @@ void cwdebug_backtrace(int n)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CWDEBUG
|
||||
#elif defined(DEBUG_CURLIO)
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
namespace debug
|
||||
{
|
||||
|
||||
libcwd_do_type const libcw_do;
|
||||
CWD_TLS int Indent::S_indentation;
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Indent::print_nt)
|
||||
{
|
||||
if (Indent::S_indentation)
|
||||
os << std::string(Indent::S_indentation, ' ');
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, libcwd::buf2str const& b2s)
|
||||
{
|
||||
static char const c2s_tab[7] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' };
|
||||
size_t size = b2s.mSize;
|
||||
for (char const* p1 = b2s.mBuf; size > 0; --size, ++p1)
|
||||
{
|
||||
char c =*p1;
|
||||
if ((c > 31 && c != 92 && c != 127) || (unsigned char)c > 159)
|
||||
os.put(c);
|
||||
else
|
||||
{
|
||||
os.put('\\');
|
||||
if (c > 6 && c < 14)
|
||||
{
|
||||
os.put(c2s_tab[c - 7]);
|
||||
return os;
|
||||
}
|
||||
else if (c == 27)
|
||||
{
|
||||
os.put('e');
|
||||
return os;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
os.put('\\');
|
||||
return os;
|
||||
}
|
||||
std::ostream::char_type old_fill = os.fill('0');
|
||||
std::ios_base::fmtflags old_flgs = os.flags();
|
||||
os.width(3);
|
||||
os << std::oct << (int)((unsigned char)c);
|
||||
os.setf(old_flgs);
|
||||
os.fill(old_fill);
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace dc
|
||||
{
|
||||
|
||||
fake_channel const warning(1, "WARNING ");
|
||||
fake_channel const curl(1, "CURL ");
|
||||
fake_channel const curlio(1, "CURLIO ");
|
||||
fake_channel const statemachine(1, "STATEMACHINE");
|
||||
fake_channel const notice(1, "NOTICE ");
|
||||
|
||||
} // namespace dc
|
||||
} // namespace debug
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,113 @@
|
||||
|
||||
#ifndef CWDEBUG
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define CWD_DLLEXPORT __declspec(dllexport)
|
||||
#define CWD_DLLIMPORT __declspec(dllimport)
|
||||
#elif LL_LINUX
|
||||
#define CWD_DLLEXPORT __attribute__ ((visibility("default")))
|
||||
#define CWD_DLLIMPORT
|
||||
#else
|
||||
#define CWD_DLLEXPORT
|
||||
#define CWD_DLLIMPORT
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
#if LL_COMMON_LINK_SHARED
|
||||
#if defined(cwdebug_EXPORTS) || defined(llcommon_EXPORTS)
|
||||
#define CWD_API CWD_DLLEXPORT
|
||||
#else // cwdebug_EXPORTS
|
||||
#define CWD_API CWD_DLLIMPORT
|
||||
#endif // cwdebug_EXPORTS
|
||||
#else // LL_COMMON_LINK_SHARED
|
||||
#error LL_COMMON_LINK_SHARED not defined
|
||||
#endif // LL_COMMON_LINK_SHARED
|
||||
|
||||
// If CWDEBUG is not defined, but DEBUG_CURLIO is, then replace
|
||||
// some of the cwd macro's with something that generates viewer
|
||||
// specific debug output. Note that this generates a LOT of
|
||||
// output and should not normally be defined.
|
||||
|
||||
#include <string>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define CWD_API_TLS __declspec(thread)
|
||||
#define CWD_TLS __declspec(thread)
|
||||
#else
|
||||
#define CWD_API_TLS CWD_API __thread
|
||||
#define CWD_TLS __thread
|
||||
#endif
|
||||
|
||||
namespace debug {
|
||||
namespace libcwd {
|
||||
|
||||
struct buf2str {
|
||||
buf2str(char const* buf, int size) : mBuf(buf), mSize(size) { }
|
||||
char const* mBuf;
|
||||
int mSize;
|
||||
};
|
||||
|
||||
} // namespace libcwd
|
||||
|
||||
inline void init() { }
|
||||
struct libcwd_do_type {
|
||||
void on() const { }
|
||||
};
|
||||
extern CWD_API libcwd_do_type const libcw_do;
|
||||
struct Indent {
|
||||
int M_indent;
|
||||
static CWD_API_TLS int S_indentation;
|
||||
enum CWD_API print_nt { print };
|
||||
CWD_API Indent(int indent) : M_indent(indent) { S_indentation += M_indent; }
|
||||
CWD_API ~Indent() { S_indentation -= M_indent; }
|
||||
};
|
||||
|
||||
extern CWD_API std::ostream& operator<<(std::ostream& os, libcwd::buf2str const& b2s);
|
||||
extern CWD_API std::ostream& operator<<(std::ostream& os, Indent::print_nt);
|
||||
|
||||
namespace dc {
|
||||
|
||||
struct fake_channel {
|
||||
int mOn;
|
||||
char const* mLabel;
|
||||
fake_channel(int on, char const* label) : mOn(on), mLabel(label) { }
|
||||
fake_channel(void) : mOn(0) { }
|
||||
bool is_on() const { return !!mOn; }
|
||||
bool is_off() const { return !mOn; }
|
||||
void on() const { }
|
||||
void off() const { }
|
||||
};
|
||||
extern CWD_API fake_channel const warning;
|
||||
extern CWD_API fake_channel const curl;
|
||||
extern CWD_API fake_channel const curlio;
|
||||
extern CWD_API fake_channel const statemachine;
|
||||
extern CWD_API fake_channel const notice;
|
||||
|
||||
} // namespace dc
|
||||
} // namespace debug
|
||||
|
||||
#define Debug(x) do { using namespace debug; x; } while(0)
|
||||
#define Dout(a, b) do { using namespace debug; if ((a).mOn) { llinfos_nf << (a).mLabel << ": " << Indent::print << b << llendl; } } while(0)
|
||||
#define DoutEntering(a, b) \
|
||||
int __slviewer_debug_indentation = 2; \
|
||||
{ \
|
||||
using namespace debug; \
|
||||
if ((a).mOn) \
|
||||
llinfos_nf << (a).mLabel << ": " << Indent::print << "Entering " << b << llendl; \
|
||||
else \
|
||||
__slviewer_debug_indentation = 0; \
|
||||
} \
|
||||
debug::Indent __slviewer_debug_indent(__slviewer_debug_indentation);
|
||||
|
||||
#else // !DEBUG_CURLIO
|
||||
|
||||
#define Debug(x)
|
||||
#define Dout(a, b)
|
||||
#define DoutEntering(a, b)
|
||||
|
||||
#endif // !DEBUG_CURLIO
|
||||
|
||||
#ifndef DOXYGEN // No need to document this. See http://libcwd.sourceforge.net/ for more info.
|
||||
|
||||
#include <iostream>
|
||||
@@ -36,9 +143,6 @@
|
||||
#define AllocTag2(p, desc)
|
||||
#define AllocTag_dynamic_description(p, x)
|
||||
#define AllocTag(p, x)
|
||||
#define Debug(x)
|
||||
#define Dout(a, b)
|
||||
#define DoutEntering(a, b)
|
||||
#define DoutFatal(a, b) LibcwDoutFatal(::std, , a, b)
|
||||
#define ForAllDebugChannels(STATEMENT)
|
||||
#define ForAllDebugObjects(STATEMENT)
|
||||
|
||||
@@ -963,10 +963,14 @@ namespace LLError
|
||||
settings_w->shouldLogCallCounter += 1;
|
||||
|
||||
std::string class_name = className(site.mClassInfo);
|
||||
std::string function_name = functionName(site.mFunction);
|
||||
if (site.mClassInfo != typeid(NoClassInfo))
|
||||
std::string function_name;
|
||||
if (site.mFunction)
|
||||
{
|
||||
function_name = class_name + "::" + function_name;
|
||||
function_name = functionName(site.mFunction);
|
||||
if (site.mClassInfo != typeid(NoClassInfo))
|
||||
{
|
||||
function_name = class_name + "::" + function_name;
|
||||
}
|
||||
}
|
||||
|
||||
ELevel compareLevel = settings_w->defaultLevel;
|
||||
@@ -976,7 +980,7 @@ namespace LLError
|
||||
// So, in increasing order of importance:
|
||||
// Default < Broad Tag < File < Class < Function < Narrow Tag
|
||||
((site.mNarrowTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mNarrowTag, compareLevel) : false)
|
||||
|| checkLevelMap(settings_w->functionLevelMap, function_name, compareLevel)
|
||||
|| (site.mFunction && checkLevelMap(settings_w->functionLevelMap, function_name, compareLevel))
|
||||
|| checkLevelMap(settings_w->classLevelMap, class_name, compareLevel)
|
||||
|| checkLevelMap(settings_w->fileLevelMap, abbreviateFile(site.mFile), compareLevel)
|
||||
|| ((site.mBroadTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mBroadTag, compareLevel) : false);
|
||||
@@ -1083,8 +1087,8 @@ namespace LLError
|
||||
default: prefix << "XXX"; break;
|
||||
};
|
||||
|
||||
bool need_function = true;
|
||||
if (site.mBroadTag && *site.mBroadTag != '\0')
|
||||
bool need_function = site.mFunction;
|
||||
if (need_function && site.mBroadTag && *site.mBroadTag != '\0')
|
||||
{
|
||||
prefix << "(\"" << site.mBroadTag << "\")";
|
||||
#if LL_DEBUG
|
||||
@@ -1112,7 +1116,7 @@ namespace LLError
|
||||
#if LL_WINDOWS
|
||||
// DevStudio: __FUNCTION__ already includes the full class name
|
||||
#else
|
||||
if (need_function && site.mClassInfo != typeid(NoClassInfo))
|
||||
if (site.mClassInfo != typeid(NoClassInfo))
|
||||
{
|
||||
prefix << className(site.mClassInfo) << "::";
|
||||
}
|
||||
|
||||
@@ -238,10 +238,10 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
|
||||
See top of file for common usage.
|
||||
*/
|
||||
|
||||
#define lllog(level, broadTag, narrowTag, once) \
|
||||
#define lllog(level, broadTag, narrowTag, once, nofunction) \
|
||||
do { \
|
||||
static LLError::CallSite _site( \
|
||||
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\
|
||||
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), nofunction ? NULL : __FUNCTION__, broadTag, narrowTag, once);\
|
||||
if (LL_UNLIKELY(_site.shouldLog())) \
|
||||
{ \
|
||||
std::ostringstream* _out = LLError::Log::out(); \
|
||||
@@ -255,33 +255,39 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
|
||||
} while(0)
|
||||
|
||||
// DEPRECATED: Use the new macros that allow tags and *look* like macros.
|
||||
#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)
|
||||
#define llinfos lllog(LLError::LEVEL_INFO, NULL, NULL, false)
|
||||
#define llwarns lllog(LLError::LEVEL_WARN, NULL, NULL, false)
|
||||
#define llerrs lllog(LLError::LEVEL_ERROR, NULL, NULL, false)
|
||||
#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false, false)
|
||||
#define llinfos lllog(LLError::LEVEL_INFO, NULL, NULL, false, false)
|
||||
#define llwarns lllog(LLError::LEVEL_WARN, NULL, NULL, false, false)
|
||||
#define llerrs lllog(LLError::LEVEL_ERROR, NULL, NULL, false, false)
|
||||
#define llcont (*_out)
|
||||
|
||||
// No function name
|
||||
#define lldebugs_nf lllog(LLError::LEVEL_DEBUG, NULL, NULL, false, true)
|
||||
#define llinfos_nf lllog(LLError::LEVEL_INFO, NULL, NULL, false, true)
|
||||
#define llwarns_nf lllog(LLError::LEVEL_WARN, NULL, NULL, false, true)
|
||||
#define llerrs_nf lllog(LLError::LEVEL_ERROR, NULL, NULL, false, true)
|
||||
|
||||
// NEW Macros for debugging, allow the passing of a string tag
|
||||
|
||||
// One Tag
|
||||
#define LL_DEBUGS(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false)
|
||||
#define LL_INFOS(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, false)
|
||||
#define LL_WARNS(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, false)
|
||||
#define LL_ERRS(broadTag) lllog(LLError::LEVEL_ERROR, broadTag, NULL, false)
|
||||
#define LL_DEBUGS(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false, false)
|
||||
#define LL_INFOS(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, false, false)
|
||||
#define LL_WARNS(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, false, false)
|
||||
#define LL_ERRS(broadTag) lllog(LLError::LEVEL_ERROR, broadTag, NULL, false, false)
|
||||
// Two Tags
|
||||
#define LL_DEBUGS2(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false)
|
||||
#define LL_INFOS2(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false)
|
||||
#define LL_WARNS2(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false)
|
||||
#define LL_ERRS2(broadTag, narrowTag) lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false)
|
||||
#define LL_DEBUGS2(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false, false)
|
||||
#define LL_INFOS2(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false, false)
|
||||
#define LL_WARNS2(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false, false)
|
||||
#define LL_ERRS2(broadTag, narrowTag) lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false, false)
|
||||
|
||||
// Only print the log message once (good for warnings or infos that would otherwise
|
||||
// spam the log file over and over, such as tighter loops).
|
||||
#define LL_DEBUGS_ONCE(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true)
|
||||
#define LL_INFOS_ONCE(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, true)
|
||||
#define LL_WARNS_ONCE(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, true)
|
||||
#define LL_DEBUGS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true)
|
||||
#define LL_INFOS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true)
|
||||
#define LL_WARNS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true)
|
||||
#define LL_DEBUGS_ONCE(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true, false)
|
||||
#define LL_INFOS_ONCE(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, true, false)
|
||||
#define LL_WARNS_ONCE(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, true, false)
|
||||
#define LL_DEBUGS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true, false)
|
||||
#define LL_INFOS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true, false)
|
||||
#define LL_WARNS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true, false)
|
||||
|
||||
#define LL_ENDL llendl
|
||||
#define LL_CONT (*_out)
|
||||
|
||||
@@ -123,20 +123,13 @@ void ssl_locking_function(int mode, int n, char const* file, int line)
|
||||
}
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
static unsigned long __cdecl apr_os_thread_current_wrapper()
|
||||
{
|
||||
return (unsigned long)apr_os_thread_current();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_CRYPTO_THREADID
|
||||
// OpenSSL uniq id function.
|
||||
void ssl_id_function(CRYPTO_THREADID* thread_id)
|
||||
{
|
||||
#if LL_WINDOWS // apr_os_thread_current() returns an unsigned long.
|
||||
#if LL_WINDOWS // apr_os_thread_current() returns a pointer,
|
||||
CRYPTO_THREADID_set_pointer(thread_id, apr_os_thread_current());
|
||||
#else // if it would return a pointer.
|
||||
#else // else it returns an unsigned long.
|
||||
CRYPTO_THREADID_set_numeric(thread_id, apr_os_thread_current());
|
||||
#endif
|
||||
}
|
||||
@@ -193,6 +186,13 @@ ssl_dyn_create_function_type old_ssl_dyn_create_function;
|
||||
ssl_dyn_destroy_function_type old_ssl_dyn_destroy_function;
|
||||
ssl_dyn_lock_function_type old_ssl_dyn_lock_function;
|
||||
|
||||
#if LL_WINDOWS
|
||||
static unsigned long __cdecl apr_os_thread_current_wrapper()
|
||||
{
|
||||
return (unsigned long)apr_os_thread_current();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set for openssl-1.0.1...1.0.1c.
|
||||
static bool need_renegotiation_hack = false;
|
||||
|
||||
@@ -200,15 +200,15 @@ static bool need_renegotiation_hack = false;
|
||||
void ssl_init(void)
|
||||
{
|
||||
// The version identifier format is: MMNNFFPPS: major minor fix patch status.
|
||||
int const compiled_openSLL_major = (OPENSSL_VERSION_NUMBER >> 28) & 0xff;
|
||||
int const compiled_openSLL_minor = (OPENSSL_VERSION_NUMBER >> 20) & 0xff;
|
||||
int const compiled_openSSL_major = (OPENSSL_VERSION_NUMBER >> 28) & 0xff;
|
||||
int const compiled_openSSL_minor = (OPENSSL_VERSION_NUMBER >> 20) & 0xff;
|
||||
unsigned long const ssleay = SSLeay();
|
||||
int const linked_openSLL_major = (ssleay >> 28) & 0xff;
|
||||
int const linked_openSLL_minor = (ssleay >> 20) & 0xff;
|
||||
int const linked_openSSL_major = (ssleay >> 28) & 0xff;
|
||||
int const linked_openSSL_minor = (ssleay >> 20) & 0xff;
|
||||
// Check if dynamically loaded version is compatible with the one we compiled against.
|
||||
// As off version 1.0.0 also minor versions are compatible.
|
||||
if (linked_openSLL_major != compiled_openSLL_major ||
|
||||
(compiled_openSLL_major == 0 && linked_openSLL_minor != compiled_openSLL_minor))
|
||||
if (linked_openSSL_major != compiled_openSSL_major ||
|
||||
(linked_openSSL_major == 0 && linked_openSSL_minor != compiled_openSSL_minor))
|
||||
{
|
||||
llerrs << "The viewer was compiled against " << OPENSSL_VERSION_TEXT <<
|
||||
" but linked against " << SSLeay_version(SSLEAY_VERSION) <<
|
||||
@@ -312,10 +312,19 @@ void initCurl(void (*flush_hook)())
|
||||
{
|
||||
llwarns << "libcurl was not compiled with support for asynchronous name lookups!" << llendl;
|
||||
}
|
||||
if (!version_info->ssl_version)
|
||||
{
|
||||
llerrs << "This libcurl has no SSL support!" << llendl;
|
||||
}
|
||||
|
||||
llinfos << "Successful initialization of libcurl " <<
|
||||
version_info->version << " (0x" << std::hex << version_info->version_num << "), (" <<
|
||||
version_info->ssl_version << ", libz/" << version_info->libz_version << ")." << llendl;
|
||||
version_info->ssl_version;
|
||||
if (version_info->libz_version)
|
||||
{
|
||||
llcont << ", libz/" << version_info->libz_version;
|
||||
}
|
||||
llcont << ")." << llendl;
|
||||
|
||||
// Detect SSL library used.
|
||||
gSSLlib = ssl_unknown;
|
||||
@@ -538,12 +547,12 @@ LLAtomicU32 Stats::multi_errors;
|
||||
//static
|
||||
void Stats::print(void)
|
||||
{
|
||||
llinfos << "============ CURL STATS ============" << llendl;
|
||||
llinfos << " Curl multi errors/calls : " << std::dec << multi_errors << "/" << multi_calls << llendl;
|
||||
llinfos << " Curl easy errors/calls : " << std::dec << easy_errors << "/" << easy_calls << llendl;
|
||||
llinfos << " curl_easy_init() errors/calls : " << std::dec << easy_init_errors << "/" << easy_init_calls << llendl;
|
||||
llinfos << " Current number of curl easy handles: " << std::dec << (easy_init_calls - easy_init_errors - easy_cleanup_calls) << llendl;
|
||||
llinfos << "========= END OF CURL STATS =========" << llendl;
|
||||
llinfos_nf << "============ CURL STATS ============" << llendl;
|
||||
llinfos_nf << " Curl multi errors/calls : " << std::dec << multi_errors << "/" << multi_calls << llendl;
|
||||
llinfos_nf << " Curl easy errors/calls : " << std::dec << easy_errors << "/" << easy_calls << llendl;
|
||||
llinfos_nf << " curl_easy_init() errors/calls : " << std::dec << easy_init_errors << "/" << easy_init_calls << llendl;
|
||||
llinfos_nf << " Current number of curl easy handles: " << std::dec << (easy_init_calls - easy_init_errors - easy_cleanup_calls) << llendl;
|
||||
llinfos_nf << "========= END OF CURL STATS =========" << llendl;
|
||||
}
|
||||
|
||||
// THREAD-SAFE
|
||||
@@ -797,7 +806,7 @@ void CurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* us
|
||||
setopt(CURLOPT_SSL_CTX_DATA, userdata ? this : NULL);
|
||||
}
|
||||
|
||||
#define llmaybewarns lllog(LLApp::isExiting() ? LLError::LEVEL_INFO : LLError::LEVEL_WARN, NULL, NULL, false)
|
||||
#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)
|
||||
{
|
||||
@@ -877,9 +886,18 @@ void CurlEasyRequest::addHeader(char const* header)
|
||||
mHeaders = curl_slist_append(mHeaders, header);
|
||||
}
|
||||
|
||||
#ifdef CWDEBUG
|
||||
static int curl_debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
|
||||
#ifndef CWDEBUG
|
||||
#define LIBCWD_DEBUGCHANNELS 0
|
||||
#define LibcwDoutScopeBegin(a, b, c) do { using namespace debug; llinfos_nf << dc::curlio.mLabel << ": ";
|
||||
#define LibcwDoutStream llcont
|
||||
#define LibcwDoutScopeEnd llcont << llendl; } while(0)
|
||||
#endif
|
||||
|
||||
static int curl_debug_cb(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
|
||||
{
|
||||
#ifdef CWDEBUG
|
||||
using namespace ::libcwd;
|
||||
|
||||
CurlEasyRequest* request = (CurlEasyRequest*)user_ptr;
|
||||
@@ -889,6 +907,13 @@ static int curl_debug_callback(CURL*, curl_infotype infotype, char* buf, size_t
|
||||
libcw_do.marker().assign(marker.str().data(), marker.str().size());
|
||||
if (!debug::channels::dc::curlio.is_on())
|
||||
debug::channels::dc::curlio.on();
|
||||
#else
|
||||
if (infotype == CURLINFO_TEXT)
|
||||
{
|
||||
while (size > 0 && (buf[size - 1] == '\r' || buf[size - 1] == '\n'))
|
||||
--size;
|
||||
}
|
||||
#endif
|
||||
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcw_do, dc::curlio|cond_nonewline_cf(infotype == CURLINFO_TEXT))
|
||||
switch (infotype)
|
||||
{
|
||||
@@ -924,7 +949,7 @@ static int curl_debug_callback(CURL*, curl_infotype infotype, char* buf, size_t
|
||||
{
|
||||
LibcwDoutStream << size << " bytes";
|
||||
bool finished = false;
|
||||
int i = 0;
|
||||
size_t i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
char c = buf[i];
|
||||
@@ -967,7 +992,9 @@ static int curl_debug_callback(CURL*, curl_infotype infotype, char* buf, size_t
|
||||
else
|
||||
LibcwDoutStream << size << " bytes";
|
||||
LibcwDoutScopeEnd;
|
||||
#ifdef CWDEBUG
|
||||
libcw_do.pop_marker();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1032,7 +1059,7 @@ void CurlEasyRequest::applyDefaultOptions(void)
|
||||
if (dc::curlio.is_on())
|
||||
{
|
||||
setopt(CURLOPT_VERBOSE, 1);
|
||||
setopt(CURLOPT_DEBUGFUNCTION, &curl_debug_callback);
|
||||
setopt(CURLOPT_DEBUGFUNCTION, &curl_debug_cb);
|
||||
setopt(CURLOPT_DEBUGDATA, this);
|
||||
}
|
||||
);
|
||||
@@ -1118,7 +1145,7 @@ CurlResponderBuffer::CurlResponderBuffer()
|
||||
curl_easy_request_w->send_events_to(this);
|
||||
}
|
||||
|
||||
#define llmaybeerrs lllog(LLApp::isRunning() ? LLError::LEVEL_ERROR : LLError::LEVEL_WARN, NULL, NULL, false)
|
||||
#define llmaybeerrs lllog(LLApp::isRunning() ? LLError::LEVEL_ERROR : LLError::LEVEL_WARN, NULL, NULL, false, true)
|
||||
|
||||
// The callbacks need to be revoked when the CurlResponderBuffer is destructed (because that is what the callbacks use).
|
||||
// The AIThreadSafeSimple<CurlResponderBuffer> is destructed first (right to left), so when we get here then the
|
||||
@@ -1164,9 +1191,7 @@ void CurlResponderBuffer::resetState(AICurlEasyRequest_wat& curl_easy_request_w)
|
||||
curl_easy_request_w->resetState();
|
||||
|
||||
mOutput.reset();
|
||||
|
||||
mInput.str("");
|
||||
mInput.clear();
|
||||
mInput.reset();
|
||||
|
||||
mHeaderOutput.str("");
|
||||
mHeaderOutput.clear();
|
||||
@@ -1184,6 +1209,10 @@ void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w
|
||||
curl_easy_request_w->setoptString(CURLOPT_ENCODING, "");
|
||||
}
|
||||
|
||||
mInput.reset(new LLBufferArray);
|
||||
mInput->setThreaded(true);
|
||||
mLastRead = NULL;
|
||||
|
||||
mOutput.reset(new LLBufferArray);
|
||||
mOutput->setThreaded(true);
|
||||
|
||||
@@ -1244,16 +1273,10 @@ size_t CurlResponderBuffer::curlReadCallback(char* data, size_t size, size_t nme
|
||||
// to make sure that callbacks and destruction aren't done simultaneously.
|
||||
AICurlEasyRequest_wat buffered_easy_request_w(*lockobj);
|
||||
|
||||
S32 bytes = size * nmemb; // The maximum amount to read.
|
||||
AICurlResponderBuffer_wat buffer_w(*lockobj);
|
||||
S32 n = size * nmemb;
|
||||
S32 startpos = buffer_w->getInput().tellg();
|
||||
buffer_w->getInput().seekg(0, std::ios::end);
|
||||
S32 endpos = buffer_w->getInput().tellg();
|
||||
buffer_w->getInput().seekg(startpos, std::ios::beg);
|
||||
S32 maxn = endpos - startpos;
|
||||
n = llmin(n, maxn);
|
||||
buffer_w->getInput().read(data, n);
|
||||
return n;
|
||||
buffer_w->mLastRead = buffer_w->getInput()->readAfter(sChannels.out(), buffer_w->mLastRead, (U8*)data, bytes);
|
||||
return bytes; // Return the amount actually read.
|
||||
}
|
||||
|
||||
//static
|
||||
|
||||
@@ -291,9 +291,9 @@ class CurlResponderBuffer : protected AICurlEasyHandleEvents {
|
||||
void resetState(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
void prepRequest(AICurlEasyRequest_wat& buffered_curl_easy_request_w, std::vector<std::string> const& headers, AICurlInterface::ResponderPtr responder, S32 time_out = 0, bool post = false);
|
||||
|
||||
std::stringstream& getInput() { return mInput; }
|
||||
std::stringstream& getHeaderOutput() { return mHeaderOutput; }
|
||||
LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; }
|
||||
LLIOPipe::buffer_ptr_t& getInput(void) { return mInput; }
|
||||
std::stringstream& getHeaderOutput(void) { return mHeaderOutput; }
|
||||
LLIOPipe::buffer_ptr_t& getOutput(void) { return mOutput; }
|
||||
|
||||
// Called if libcurl doesn't deliver within CurlRequestTimeOut seconds.
|
||||
void timed_out(void);
|
||||
@@ -307,13 +307,14 @@ class CurlResponderBuffer : protected AICurlEasyHandleEvents {
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
|
||||
private:
|
||||
std::stringstream mInput;
|
||||
LLIOPipe::buffer_ptr_t mInput;
|
||||
U8* mLastRead; // Pointer into mInput where we last stopped reading (or NULL to start at the beginning).
|
||||
std::stringstream mHeaderOutput;
|
||||
LLIOPipe::buffer_ptr_t mOutput;
|
||||
AICurlInterface::ResponderPtr mResponder;
|
||||
|
||||
public:
|
||||
static LLChannelDescriptors const sChannels; // Channel object for mOutput: we ONLY use channel 0, so this can be a constant.
|
||||
static LLChannelDescriptors const sChannels; // Channel object for mInput (channel out()) and mOutput (channel in()).
|
||||
|
||||
private:
|
||||
// This class may only be created by constructing a ThreadSafeBufferedCurlEasyRequest.
|
||||
|
||||
@@ -39,7 +39,11 @@
|
||||
#endif
|
||||
#include <deque>
|
||||
|
||||
// On linux, add -DDEBUG_WINDOWS_CODE_ON_LINUX to test the windows code used in this file.
|
||||
#if !defined(DEBUG_WINDOWS_CODE_ON_LINUX) || !defined(LL_LINUX) || defined(LL_RELEASE)
|
||||
#undef DEBUG_WINDOWS_CODE_ON_LINUX
|
||||
#define DEBUG_WINDOWS_CODE_ON_LINUX 0
|
||||
#endif
|
||||
|
||||
#if DEBUG_WINDOWS_CODE_ON_LINUX
|
||||
|
||||
@@ -143,8 +147,40 @@ static void FD_CLR(curl_socket_t s, windows_fd_set* fsp)
|
||||
#define fd_set windows_fd_set
|
||||
#define select windows_select
|
||||
|
||||
int WSAGetLastError(void)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
typedef char* LPTSTR;
|
||||
|
||||
bool FormatMessage(int, void*, int e, int, LPTSTR error_str_ptr, int, void*)
|
||||
{
|
||||
char* error_str = *(LPTSTR*)error_str_ptr;
|
||||
error_str = strerror(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocalFree(LPTSTR)
|
||||
{
|
||||
}
|
||||
|
||||
int const FORMAT_MESSAGE_ALLOCATE_BUFFER = 0;
|
||||
int const FORMAT_MESSAGE_FROM_SYSTEM = 0;
|
||||
int const FORMAT_MESSAGE_IGNORE_INSERTS = 0;
|
||||
int const INVALID_SOCKET = -1;
|
||||
int const SOCKET_ERROR = -1;
|
||||
int const WSAEWOULDBLOCK = EWOULDBLOCK;
|
||||
|
||||
int closesocket(curl_socket_t fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
#endif // DEBUG_WINDOWS_CODE_ON_LINUX
|
||||
|
||||
#define WINDOWS_CODE (LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
|
||||
#undef AICurlPrivate
|
||||
|
||||
namespace AICurlPrivate {
|
||||
@@ -248,7 +284,7 @@ class PollSet
|
||||
// Return a pointer to the underlaying fd_set.
|
||||
fd_set* access(void) { return &mFdSet; }
|
||||
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
// Return the largest fd set in mFdSet by refresh.
|
||||
curl_socket_t get_max_fd(void) const { return mMaxFdSet; }
|
||||
#endif
|
||||
@@ -275,7 +311,7 @@ class PollSet
|
||||
|
||||
fd_set mFdSet; // Output variable for select(). (Re)initialized by calling refresh().
|
||||
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
curl_socket_t mMaxFd; // The largest filedescriptor in the array, or CURL_SOCKET_BAD when it is empty.
|
||||
curl_socket_t mMaxFdSet; // The largest filedescriptor set in mFdSet by refresh(), or CURL_SOCKET_BAD when it was empty.
|
||||
std::vector<curl_socket_t> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet.
|
||||
@@ -307,7 +343,7 @@ static size_t const MAXSIZE = llmax(1024, FD_SETSIZE);
|
||||
// Create an empty PollSet.
|
||||
PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]),
|
||||
mNrFds(0), mNext(0)
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
, mMaxFd(-1), mMaxFdSet(-1)
|
||||
#endif
|
||||
{
|
||||
@@ -319,7 +355,7 @@ void PollSet::add(curl_socket_t s)
|
||||
{
|
||||
llassert_always(mNrFds < (int)MAXSIZE);
|
||||
mFileDescriptors[mNrFds++] = s;
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
mMaxFd = llmax(mMaxFd, s);
|
||||
#endif
|
||||
}
|
||||
@@ -356,7 +392,7 @@ void PollSet::remove(curl_socket_t s)
|
||||
// index: 0 1 2 3 4 5
|
||||
// a b c s d e
|
||||
curl_socket_t cur = mFileDescriptors[i]; // cur = 'e'
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
curl_socket_t max = -1;
|
||||
#endif
|
||||
while (cur != s)
|
||||
@@ -364,7 +400,7 @@ void PollSet::remove(curl_socket_t s)
|
||||
llassert(i > 0);
|
||||
curl_socket_t next = mFileDescriptors[--i]; // next = 'd'
|
||||
mFileDescriptors[i] = cur; // Overwrite 'd' with 'e'.
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
max = llmax(max, cur); // max is the maximum value in 'i' or higher.
|
||||
#endif
|
||||
cur = next; // cur = 'd'
|
||||
@@ -391,7 +427,7 @@ void PollSet::remove(curl_socket_t s)
|
||||
if (mNext > i) // i is where s was.
|
||||
--mNext;
|
||||
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
// If s was the largest file descriptor, we have to update mMaxFd.
|
||||
if (s == mMaxFd)
|
||||
{
|
||||
@@ -408,7 +444,7 @@ void PollSet::remove(curl_socket_t s)
|
||||
|
||||
// ALSO make sure that s is no longer set in mFdSet, or we might confuse libcurl by
|
||||
// calling curl_multi_socket_action for a socket that it told us to remove.
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
clr(s);
|
||||
#else
|
||||
// We have to use a custom implementation here, because we don't want to invalidate mIter.
|
||||
@@ -457,13 +493,13 @@ inline void PollSet::clr(curl_socket_t fd)
|
||||
refresh_t PollSet::refresh(void)
|
||||
{
|
||||
FD_ZERO(&mFdSet);
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
mCopiedFileDescriptors.clear();
|
||||
#endif
|
||||
|
||||
if (mNrFds == 0)
|
||||
{
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
mMaxFdSet = -1;
|
||||
#endif
|
||||
return empty_and_complete;
|
||||
@@ -478,7 +514,7 @@ refresh_t PollSet::refresh(void)
|
||||
if (mNrFds >= FD_SETSIZE)
|
||||
{
|
||||
llwarns << "PollSet::reset: More than FD_SETSIZE (" << FD_SETSIZE << ") file descriptors active!" << llendl;
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
// Calculate mMaxFdSet.
|
||||
// Run over FD_SETSIZE - 1 elements, starting at mNext, wrapping to 0 when we reach the end.
|
||||
int max = -1, i = mNext, count = 0;
|
||||
@@ -489,7 +525,7 @@ refresh_t PollSet::refresh(void)
|
||||
else
|
||||
{
|
||||
mNext = 0; // Start at the beginning if we copy everything anyway.
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
mMaxFdSet = mMaxFd;
|
||||
#endif
|
||||
}
|
||||
@@ -503,7 +539,7 @@ refresh_t PollSet::refresh(void)
|
||||
return not_complete_not_empty;
|
||||
}
|
||||
FD_SET(mFileDescriptors[i], &mFdSet);
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
mCopiedFileDescriptors.push_back(mFileDescriptors[i]);
|
||||
#endif
|
||||
if (++i == mNrFds)
|
||||
@@ -541,7 +577,7 @@ refresh_t PollSet::refresh(void)
|
||||
|
||||
void PollSet::reset(void)
|
||||
{
|
||||
#if LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX
|
||||
#if WINDOWS_CODE
|
||||
mIter = 0;
|
||||
#else
|
||||
if (mCopiedFileDescriptors.empty())
|
||||
@@ -557,7 +593,7 @@ void PollSet::reset(void)
|
||||
|
||||
inline curl_socket_t PollSet::get(void) const
|
||||
{
|
||||
#if LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX
|
||||
#if WINDOWS_CODE
|
||||
return (mIter >= mFdSet.fd_count) ? CURL_SOCKET_BAD : mFdSet.fd_array[mIter];
|
||||
#else
|
||||
return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : *mIter;
|
||||
@@ -566,7 +602,7 @@ inline curl_socket_t PollSet::get(void) const
|
||||
|
||||
void PollSet::next(void)
|
||||
{
|
||||
#if LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX
|
||||
#if WINDOWS_CODE
|
||||
llassert(mIter < mFdSet.fd_count);
|
||||
++mIter;
|
||||
#else
|
||||
@@ -727,10 +763,7 @@ class AICurlThread : public LLThread
|
||||
void create_wakeup_fds(void);
|
||||
void cleanup_wakeup_fds(void);
|
||||
|
||||
#if (!LL_WINDOWS)
|
||||
//On Windows, single socket is used for communicating with itself! -SG
|
||||
curl_socket_t mWakeUpFd_in;
|
||||
#endif
|
||||
curl_socket_t mWakeUpFd;
|
||||
|
||||
int mZeroTimeOut;
|
||||
@@ -743,9 +776,7 @@ AICurlThread* AICurlThread::sInstance = NULL;
|
||||
|
||||
// MAIN-THREAD
|
||||
AICurlThread::AICurlThread(void) : LLThread("AICurlThread"),
|
||||
#if (!LL_WINDOWS)
|
||||
mWakeUpFd_in(CURL_SOCKET_BAD),
|
||||
#endif
|
||||
mWakeUpFd(CURL_SOCKET_BAD),
|
||||
mZeroTimeOut(0), mRunning(true), mWakeUpFlag(false)
|
||||
{
|
||||
@@ -780,45 +811,122 @@ static std::string formatWSAError()
|
||||
}
|
||||
return r.str();
|
||||
}
|
||||
#elif WINDOWS_CODE
|
||||
static std::string formatWSAError()
|
||||
{
|
||||
return strerror(errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LL_WINDOWS
|
||||
/* Copyright 2007, 2010 by Nathan C. Myers <ncm@cantrip.org>
|
||||
* This code is Free Software. It may be copied freely, in original or
|
||||
* modified form, subject only to the restrictions that (1) the author is
|
||||
* relieved from all responsibilities for any use for any purpose, and (2)
|
||||
* this copyright notice must be retained, unchanged, in its entirety. If
|
||||
* for any reason the author might be held responsible for any consequences
|
||||
* of copying or use, license is withheld.
|
||||
*/
|
||||
static int dumb_socketpair(SOCKET socks[2], bool make_overlapped)
|
||||
{
|
||||
union {
|
||||
struct sockaddr_in inaddr;
|
||||
struct sockaddr addr;
|
||||
} a;
|
||||
SOCKET listener;
|
||||
int e;
|
||||
socklen_t addrlen = sizeof(a.inaddr);
|
||||
DWORD flags = (make_overlapped ? WSA_FLAG_OVERLAPPED : 0);
|
||||
int reuse = 1;
|
||||
|
||||
if (socks == 0) {
|
||||
WSASetLastError(WSAEINVAL);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listener == INVALID_SOCKET)
|
||||
return SOCKET_ERROR;
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.inaddr.sin_family = AF_INET;
|
||||
a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
a.inaddr.sin_port = 0;
|
||||
|
||||
socks[0] = socks[1] = INVALID_SOCKET;
|
||||
do {
|
||||
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char*) &reuse, (socklen_t) sizeof(reuse)) == -1)
|
||||
break;
|
||||
if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
|
||||
break;
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
|
||||
break;
|
||||
// win32 getsockname may only set the port number, p=0.0005.
|
||||
// ( http://msdn.microsoft.com/library/ms738543.aspx ):
|
||||
a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
a.inaddr.sin_family = AF_INET;
|
||||
|
||||
if (listen(listener, 1) == SOCKET_ERROR)
|
||||
break;
|
||||
|
||||
socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags);
|
||||
if (socks[0] == INVALID_SOCKET)
|
||||
break;
|
||||
if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
|
||||
break;
|
||||
|
||||
socks[1] = accept(listener, NULL, NULL);
|
||||
if (socks[1] == INVALID_SOCKET)
|
||||
break;
|
||||
|
||||
closesocket(listener);
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
e = WSAGetLastError();
|
||||
closesocket(listener);
|
||||
closesocket(socks[0]);
|
||||
closesocket(socks[1]);
|
||||
WSASetLastError(e);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
#else
|
||||
int dumb_socketpair(int socks[2], int dummy)
|
||||
{
|
||||
(void) dummy;
|
||||
return socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
|
||||
}
|
||||
#endif
|
||||
|
||||
// MAIN-THREAD
|
||||
void AICurlThread::create_wakeup_fds(void)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
mWakeUpFd = socket(AF_INET, SOCK_DGRAM, 0); //Maybe IPPROTO_UDP as last argument? -SG
|
||||
if(mWakeUpFd == INVALID_SOCKET)
|
||||
{
|
||||
llerrs << "Failed to create wake-up socket: " << formatWSAError() << llendl;
|
||||
}
|
||||
int error;
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
int addrlen = sizeof(addr);
|
||||
error = bind(mWakeUpFd, (sockaddr*) &addr, addrlen);
|
||||
if(error)
|
||||
{
|
||||
llerrs << "Failed to bind wake-up socket: " << formatWSAError() << llendl;
|
||||
}
|
||||
error = getsockname(mWakeUpFd, (sockaddr*) &addr, &addrlen);
|
||||
if(error)
|
||||
{
|
||||
llerrs << "Failed to detect wake-up socket: " << formatWSAError() << llendl;
|
||||
}
|
||||
error = connect(mWakeUpFd, (sockaddr*) &addr, addrlen);
|
||||
if(error)
|
||||
{
|
||||
llerrs << "Failed to connect wake-up socket: " <<formatWSAError() << llendl;
|
||||
}
|
||||
u_long nonblocking_enable = TRUE;
|
||||
error = ioctlsocket(mWakeUpFd, FIONBIO, &nonblocking_enable);
|
||||
if(error)
|
||||
{
|
||||
llerrs << "Failed to set wake-up socket nonblocking: " << formatWSAError() << llendl;
|
||||
}
|
||||
|
||||
#if WINDOWS_CODE
|
||||
//SGTODO
|
||||
curl_socket_t socks[2];
|
||||
if (dumb_socketpair(socks, false) == SOCKET_ERROR)
|
||||
{
|
||||
llerrs << "Failed to generate wake-up socket pair" << formatWSAError() << llendl;
|
||||
return;
|
||||
}
|
||||
u_long nonblocking_enable = TRUE;
|
||||
int error = ioctlsocket(socks[0], FIONBIO, &nonblocking_enable);
|
||||
if(error)
|
||||
{
|
||||
llerrs << "Failed to set wake-up socket nonblocking: " << formatWSAError() << llendl;
|
||||
}
|
||||
llassert(nonblocking_enable);
|
||||
error = ioctlsocket(socks[1], FIONBIO, &nonblocking_enable);
|
||||
if(error)
|
||||
{
|
||||
llerrs << "Failed to set wake-up input socket nonblocking: " << formatWSAError() << llendl;
|
||||
}
|
||||
mWakeUpFd = socks[0];
|
||||
mWakeUpFd_in = socks[1];
|
||||
#else
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd))
|
||||
@@ -841,15 +949,24 @@ void AICurlThread::create_wakeup_fds(void)
|
||||
// MAIN-THREAD
|
||||
void AICurlThread::cleanup_wakeup_fds(void)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
if (mWakeUpFd != CURL_SOCKET_BAD)
|
||||
{
|
||||
int error = closesocket(mWakeUpFd);
|
||||
if (error)
|
||||
#if WINDOWS_CODE
|
||||
//SGTODO
|
||||
if (mWakeUpFd != CURL_SOCKET_BAD)
|
||||
{
|
||||
llwarns << "Error closing wake-up socket" << formatWSAError() << llendl;
|
||||
int error = closesocket(mWakeUpFd);
|
||||
if (error)
|
||||
{
|
||||
llwarns << "Error closing wake-up socket" << formatWSAError() << llendl;
|
||||
}
|
||||
}
|
||||
if (mWakeUpFd_in != CURL_SOCKET_BAD)
|
||||
{
|
||||
int error = closesocket(mWakeUpFd_in);
|
||||
if (error)
|
||||
{
|
||||
llwarns << "Error closing wake-up input socket" << formatWSAError() << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (mWakeUpFd_in != CURL_SOCKET_BAD)
|
||||
close(mWakeUpFd_in);
|
||||
@@ -872,13 +989,17 @@ void AICurlThread::wakeup_thread(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#if WINDOWS_CODE
|
||||
//SGTODO
|
||||
int len = send(mWakeUpFd, "!", 1, 0);
|
||||
Dout(dc::curl, "ENTERING send()");
|
||||
int len = send(mWakeUpFd_in, "!", 1, 0);
|
||||
Dout(dc::curl, "LEAVING send()");
|
||||
if (len == SOCKET_ERROR)
|
||||
{
|
||||
llerrs << "Send to wake-up socket failed: " << formatWSAError() << llendl;
|
||||
}
|
||||
llassert_always(len == 1);
|
||||
//SGTODO: handle EAGAIN if needed
|
||||
llinfos << "Sent wakeup signal" << llendl;
|
||||
#else
|
||||
// If write() is interrupted by a signal before it writes any data, it shall return -1 with errno set to [EINTR].
|
||||
@@ -908,32 +1029,50 @@ void AICurlThread::wakeup(AICurlMultiHandle_wat const& multi_handle_w)
|
||||
{
|
||||
DoutEntering(dc::curl, "AICurlThread::wakeup");
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
char buf;
|
||||
int len;
|
||||
#if WINDOWS_CODE
|
||||
//SGTODO
|
||||
char buf[256];
|
||||
bool got_data = false;
|
||||
do
|
||||
for(;;)
|
||||
{
|
||||
len = recv(mWakeUpFd, &buf, sizeof(buf), 0);
|
||||
llinfos << "recv returns " << len << llendl;
|
||||
if(len != SOCKET_ERROR)
|
||||
int len = recv(mWakeUpFd, buf, sizeof(buf), 0);
|
||||
if (len > 0)
|
||||
{
|
||||
// Data was read from the pipe.
|
||||
got_data = true;
|
||||
if (len < sizeof(buf))
|
||||
break;
|
||||
}
|
||||
else if (len == SOCKET_ERROR)
|
||||
{
|
||||
// An error occurred.
|
||||
if (errno == EWOULDBLOCK)
|
||||
{
|
||||
got_data = true;
|
||||
llinfos << "Received wakeup signal" << llendl;
|
||||
if (got_data)
|
||||
break;
|
||||
// There was no data, even though select() said so. If this ever happens at all(?), lets just return and enter select() again.
|
||||
return;
|
||||
}
|
||||
} while(len != SOCKET_ERROR);
|
||||
int error = WSAGetLastError();
|
||||
llinfos << "left loop, errorlevel " << error << llendl;
|
||||
if(error != WSAEWOULDBLOCK)
|
||||
{
|
||||
llerrs << "Wake-up socket drain error: " << formatWSAError() << llendl;
|
||||
}
|
||||
if(!got_data)
|
||||
{
|
||||
llinfos << "Wakeup called but socket is empty" << llendl;
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "read(3) from mWakeUpFd: " << formatWSAError() << llendl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pipe(2) returned 0.
|
||||
llwarns << "read(3) from mWakeUpFd returned 0, indicating that the pipe on the other end was closed! Shutting down curl thread." << llendl;
|
||||
closesocket(mWakeUpFd);
|
||||
mWakeUpFd = CURL_SOCKET_BAD;
|
||||
mRunning = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
llinfos << "Passing control to process_commands" << llendl;
|
||||
#else
|
||||
// If a read() is interrupted by a signal before it reads any data, it shall return -1 with errno set to [EINTR].
|
||||
// If a read() is interrupted by a signal after it has successfully read some data, it shall return the number of bytes read.
|
||||
@@ -1050,7 +1189,7 @@ void AICurlThread::run(void)
|
||||
FD_SET(mWakeUpFd, read_fd_set);
|
||||
fd_set* write_fd_set = ((wres & empty)) ? NULL : multi_handle_w->mWritePollSet->access();
|
||||
// Calculate nfds (ignored on windows).
|
||||
#if !(LL_WINDOWS || DEBUG_WINDOWS_CODE_ON_LINUX)
|
||||
#if !WINDOWS_CODE
|
||||
curl_socket_t const max_rfd = llmax(multi_handle_w->mReadPollSet->get_max_fd(), mWakeUpFd);
|
||||
curl_socket_t const max_wfd = multi_handle_w->mWritePollSet->get_max_fd();
|
||||
int nfds = llmax(max_rfd, max_wfd) + 1;
|
||||
@@ -1213,7 +1352,7 @@ MultiHandle::~MultiHandle()
|
||||
delete mReadPollSet;
|
||||
}
|
||||
|
||||
#ifdef CWDEBUG
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#undef AI_CASE_RETURN
|
||||
#define AI_CASE_RETURN(x) do { case x: return #x; } while(0)
|
||||
char const* action_str(int action)
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#include "llsdserialize.h"
|
||||
#include "llcurlrequest.h"
|
||||
#include "llbuffer.h"
|
||||
#include "llbufferstream.h"
|
||||
#include "statemachine/aicurleasyrequeststatemachine.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -94,8 +96,11 @@ bool Request::post(std::string const& url, headers_t const& headers, std::string
|
||||
|
||||
buffer_w->prepRequest(buffered_easy_request_w, headers, responder);
|
||||
|
||||
buffer_w->getInput().write(data.data(), data.size());
|
||||
S32 bytes = buffer_w->getInput().str().length();
|
||||
U32 bytes = data.size();
|
||||
bool success = buffer_w->getInput()->append(buffer_w->sChannels.out(), (U8 const*)data.data(), bytes);
|
||||
llassert_always(success); // AIFIXME: Maybe throw an error.
|
||||
if (!success)
|
||||
return false;
|
||||
buffered_easy_request_w->setPost(NULL, bytes);
|
||||
buffered_easy_request_w->addHeader("Content-Type: application/octet-stream");
|
||||
buffered_easy_request_w->finalizeRequest(url);
|
||||
@@ -121,8 +126,9 @@ bool Request::post(std::string const& url, headers_t const& headers, LLSD const&
|
||||
|
||||
buffer_w->prepRequest(buffered_easy_request_w, headers, responder);
|
||||
|
||||
LLSDSerialize::toXML(data, buffer_w->getInput());
|
||||
S32 bytes = buffer_w->getInput().str().length();
|
||||
LLBufferStream buffer_stream(buffer_w->sChannels, buffer_w->getInput().get());
|
||||
LLSDSerialize::toXML(data, buffer_stream);
|
||||
S32 bytes = buffer_w->getInput()->countAfter(buffer_w->sChannels.out(), NULL);
|
||||
buffered_easy_request_w->setPost(NULL, bytes);
|
||||
buffered_easy_request_w->addHeader("Content-Type: application/llsd+xml");
|
||||
buffered_easy_request_w->finalizeRequest(url);
|
||||
|
||||
@@ -253,7 +253,7 @@ extern S32 gStartImageHeight;
|
||||
// local globals
|
||||
//
|
||||
|
||||
#ifdef CWDEBUG
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
static bool gCurlIo;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -858,7 +858,7 @@ class Linux_x86_64Manifest(LinuxManifest):
|
||||
self.end_prefix("lib32")
|
||||
|
||||
# 32bit libs needed for voice
|
||||
if self.prefix("../../libraries/x86_64-linux/lib/release/32bit-compat", dst="lib32"):
|
||||
if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"):
|
||||
self.path("libalut.so")
|
||||
self.path("libidn.so.11")
|
||||
self.path("libopenal.so.1")
|
||||
|
||||
Reference in New Issue
Block a user