WIP: make everything use AICurlEasyRequestStateMachine
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
#include "lltimer.h" // ms_sleep
|
||||
#include "llproxy.h"
|
||||
#include "llhttpstatuscodes.h"
|
||||
#include "aihttpheaders.h"
|
||||
#ifdef CWDEBUG
|
||||
#include <libcwd/buf2str.h>
|
||||
#endif
|
||||
@@ -797,7 +798,7 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value)
|
||||
setopt(option, value.c_str());
|
||||
}
|
||||
|
||||
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, S32 size)
|
||||
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size)
|
||||
{
|
||||
llassert_always(postdata->data());
|
||||
|
||||
@@ -807,7 +808,7 @@ void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, S32 size)
|
||||
setPost_raw(size, postdata->data());
|
||||
}
|
||||
|
||||
void CurlEasyRequest::setPost_raw(S32 size, char const* data)
|
||||
void CurlEasyRequest::setPost_raw(U32 size, char const* data)
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
@@ -815,6 +816,9 @@ void CurlEasyRequest::setPost_raw(S32 size, char const* data)
|
||||
Dout(dc::curl, "POST size is " << size << " bytes.");
|
||||
}
|
||||
|
||||
// Accept everything (send an Accept-Encoding header containing all encodings we support (zlib and gzip)).
|
||||
setoptString(CURLOPT_ENCODING, ""); // CURLOPT_ACCEPT_ENCODING
|
||||
|
||||
// The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default.
|
||||
addHeader("Expect:");
|
||||
if (size > 0)
|
||||
@@ -823,7 +827,7 @@ void CurlEasyRequest::setPost_raw(S32 size, char const* data)
|
||||
addHeader("Keep-alive: 300");
|
||||
}
|
||||
setopt(CURLOPT_POSTFIELDSIZE, size);
|
||||
setopt(CURLOPT_POSTFIELDS, data);
|
||||
setopt(CURLOPT_POSTFIELDS, data); // Implies CURLOPT_POST
|
||||
}
|
||||
|
||||
ThreadSafeCurlEasyRequest* CurlEasyRequest::get_lockobj(void)
|
||||
@@ -979,6 +983,12 @@ void CurlEasyRequest::addHeader(char const* header)
|
||||
mHeaders = curl_slist_append(mHeaders, header);
|
||||
}
|
||||
|
||||
void CurlEasyRequest::addHeaders(AIHTTPHeaders const& headers)
|
||||
{
|
||||
llassert(!mRequestFinalized);
|
||||
headers.append_to(mHeaders);
|
||||
}
|
||||
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
|
||||
static int curl_debug_cb(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
|
||||
@@ -1307,14 +1317,8 @@ ThreadSafeBufferedCurlEasyRequest* CurlResponderBuffer::get_lockobj(void)
|
||||
return static_cast<ThreadSafeBufferedCurlEasyRequest*>(AIThreadSafeSimple<CurlResponderBuffer>::wrapper_cast(this));
|
||||
}
|
||||
|
||||
void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w, std::vector<std::string> const& headers, AICurlInterface::ResponderPtr responder, S32 time_out, bool post)
|
||||
void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w, AIHTTPHeaders const& headers, AICurlInterface::ResponderPtr responder, S32 time_out)
|
||||
{
|
||||
if (post)
|
||||
{
|
||||
// Accept everything (send an Accept-Encoding header containing all encodings we support (zlib and gzip)).
|
||||
curl_easy_request_w->setoptString(CURLOPT_ENCODING, ""); // CURLOPT_ACCEPT_ENCODING
|
||||
}
|
||||
|
||||
mInput.reset(new LLBufferArray);
|
||||
mInput->setThreaded(true);
|
||||
mLastRead = NULL;
|
||||
@@ -1343,14 +1347,8 @@ void CurlResponderBuffer::prepRequest(AICurlEasyRequest_wat& curl_easy_request_w
|
||||
// Keep responder alive.
|
||||
mResponder = responder;
|
||||
|
||||
if (!post)
|
||||
{
|
||||
// Add extra headers.
|
||||
for (std::vector<std::string>::const_iterator iter = headers.begin(); iter != headers.end(); ++iter)
|
||||
{
|
||||
curl_easy_request_w->addHeader((*iter).c_str());
|
||||
}
|
||||
}
|
||||
// Add extra headers.
|
||||
curl_easy_request_w->addHeaders(headers);
|
||||
}
|
||||
|
||||
//static
|
||||
@@ -1500,7 +1498,12 @@ void CurlResponderBuffer::processOutput(AICurlEasyRequest_wat& curl_easy_request
|
||||
if (code == CURLE_OK)
|
||||
{
|
||||
curl_easy_request_w->getinfo(CURLINFO_RESPONSE_CODE, &responseCode);
|
||||
//AIFIXME: fill responseReason if (responseCode < 200 || responseCode >= 300).
|
||||
// If getResult code is CURLE_OK then we should have decoded the first header line ourselves.
|
||||
llassert(responseCode == mStatus);
|
||||
if (responseCode == mStatus)
|
||||
responseReason = mReason;
|
||||
else
|
||||
responseReason = "Unknown reason.";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include "llpreprocessor.h"
|
||||
@@ -49,11 +50,12 @@
|
||||
#define CURLOPT_DNS_USE_GLOBAL_CACHE do_not_use_CURLOPT_DNS_USE_GLOBAL_CACHE
|
||||
|
||||
#include "stdtypes.h" // U32
|
||||
#include "lliopipe.h" // LLIOPipe::buffer_ptr_t
|
||||
#include "llatomic.h" // LLAtomicU32
|
||||
#include "aithreadsafe.h"
|
||||
|
||||
class LLSD;
|
||||
class LLBufferArray;
|
||||
class LLChannelDescriptors;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exceptions.
|
||||
@@ -76,6 +78,11 @@ class AICurlNoMultiHandle : public AICurlError {
|
||||
AICurlNoMultiHandle(std::string const& message) : AICurlError(message) { }
|
||||
};
|
||||
|
||||
class AICurlNoBody : public AICurlError {
|
||||
public:
|
||||
AICurlNoBody(std::string const& message) : AICurlError(message) { }
|
||||
};
|
||||
|
||||
// End Exceptions.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -147,6 +154,9 @@ void setCAPath(std::string const& file);
|
||||
// destructed too.
|
||||
//
|
||||
class Responder {
|
||||
public:
|
||||
typedef boost::shared_ptr<LLBufferArray> buffer_ptr_t;
|
||||
|
||||
protected:
|
||||
Responder(void);
|
||||
virtual ~Responder();
|
||||
@@ -169,7 +179,7 @@ class Responder {
|
||||
|
||||
// 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().
|
||||
virtual void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, LLIOPipe::buffer_ptr_t const& buffer);
|
||||
virtual void completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer);
|
||||
|
||||
// Called from LLHTTPClient request calls, if an error occurs even before we can call one of the above.
|
||||
// It calls completed() with a fake status U32_MAX, as that is what some derived clients expect (bad design).
|
||||
@@ -272,13 +282,19 @@ typedef LLPointer<AIPostField> AIPostFieldPtr;
|
||||
|
||||
// AICurlEasyRequest: a thread safe, reference counting, auto-cleaning curl easy handle.
|
||||
class AICurlEasyRequest {
|
||||
public:
|
||||
private:
|
||||
// Use AICurlEasyRequestStateMachine, not AICurlEasyRequest.
|
||||
friend class AICurlEasyRequestStateMachine;
|
||||
|
||||
// Initial construction is allowed (thread-safe).
|
||||
// Note: If ThreadSafeCurlEasyRequest() throws then the memory allocated is still freed.
|
||||
// 'new' never returned however and neither the constructor nor destructor of mCurlEasyRequest is called in this case.
|
||||
// This might throw AICurlNoEasyHandle.
|
||||
AICurlEasyRequest(bool buffered) :
|
||||
mCurlEasyRequest(buffered ? new AICurlPrivate::ThreadSafeBufferedCurlEasyRequest : new AICurlPrivate::ThreadSafeCurlEasyRequest) { }
|
||||
|
||||
public:
|
||||
// Used for storing this object in a standard container (see MultiHandle::add_easy_request).
|
||||
AICurlEasyRequest(AICurlEasyRequest const& orig) : mCurlEasyRequest(orig.mCurlEasyRequest) { }
|
||||
|
||||
// For the rest, only allow read operations.
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <sstream>
|
||||
#include "llatomic.h"
|
||||
|
||||
class AIHTTPHeaders;
|
||||
|
||||
namespace AICurlPrivate {
|
||||
namespace curlthread { class MultiHandle; }
|
||||
|
||||
@@ -213,13 +215,14 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
|
||||
// and the CurlEasyRequest destructed.
|
||||
class CurlEasyRequest : public CurlEasyHandle {
|
||||
private:
|
||||
void setPost_raw(S32 size, char const* data);
|
||||
void setPost_raw(U32 size, char const* data);
|
||||
public:
|
||||
void setPost(S32 size) { setPost_raw(size, NULL); }
|
||||
void setPost(AIPostFieldPtr const& postdata, S32 size);
|
||||
void setPost(char const* data, S32 size) { setPost(new AIPostField(data), size); }
|
||||
void setPost(U32 size) { setPost_raw(size, NULL); }
|
||||
void setPost(AIPostFieldPtr const& postdata, U32 size);
|
||||
void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); }
|
||||
void setoptString(CURLoption option, std::string const& value);
|
||||
void addHeader(char const* str);
|
||||
void addHeaders(AIHTTPHeaders const& headers);
|
||||
|
||||
private:
|
||||
// Callback stubs.
|
||||
@@ -324,11 +327,13 @@ class CurlEasyRequest : public CurlEasyHandle {
|
||||
// is deleted and the CurlResponderBuffer destructed.
|
||||
class CurlResponderBuffer : protected AICurlEasyHandleEvents {
|
||||
public:
|
||||
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);
|
||||
typedef AICurlInterface::Responder::buffer_ptr_t buffer_ptr_t;
|
||||
|
||||
LLIOPipe::buffer_ptr_t& getInput(void) { return mInput; }
|
||||
LLIOPipe::buffer_ptr_t& getOutput(void) { return mOutput; }
|
||||
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);
|
||||
|
||||
buffer_ptr_t& getInput(void) { return mInput; }
|
||||
buffer_ptr_t& getOutput(void) { return mOutput; }
|
||||
|
||||
// Called if libcurl doesn't deliver within mRequestTimeOut seconds.
|
||||
void timed_out(void);
|
||||
@@ -346,9 +351,9 @@ class CurlResponderBuffer : protected AICurlEasyHandleEvents {
|
||||
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
|
||||
|
||||
private:
|
||||
LLIOPipe::buffer_ptr_t mInput;
|
||||
buffer_ptr_t mInput;
|
||||
U8* mLastRead; // Pointer into mInput where we last stopped reading (or NULL to start at the beginning).
|
||||
LLIOPipe::buffer_ptr_t mOutput;
|
||||
buffer_ptr_t mOutput;
|
||||
AICurlInterface::ResponderPtr mResponder;
|
||||
//U32 mBodyLimit; // From the old LLURLRequestDetail::mBodyLimit, but never used.
|
||||
U32 mStatus; // HTTP status, decoded from the first header line.
|
||||
|
||||
@@ -702,7 +702,11 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
|
||||
{
|
||||
LibcwDoutStream << "NULL";
|
||||
}
|
||||
LibcwDoutStream << "](" << (is_postfield ? postfieldsize : size) << " bytes))";
|
||||
LibcwDoutStream << "]";
|
||||
if (str)
|
||||
{
|
||||
LibcwDoutStream << "(" << (is_postfield ? postfieldsize : size) << " bytes))";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user