1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/include/ulib/curl/curl.h
stefanocasazza 493e28dd83 sync
2017-07-29 18:44:48 +02:00

437 lines
10 KiB
C++

// ============================================================================
//
// = LIBRARY
// ULib - c++ library
//
// = FILENAME
// curl.h
//
// = AUTHOR
// Stefano Casazza
//
// ============================================================================
#ifndef ULIB_CURL_H
#define ULIB_CURL_H 1
#include <ulib/container/vector.h>
extern "C" {
#include <curl/curl.h>
}
/**
* @class UCURL
*
* @brief This class is a wrapper around the cURL library
*/
class U_EXPORT UCURL {
public:
// Check for memory error
U_MEMORY_TEST
// Allocator e Deallocator
U_MEMORY_ALLOCATOR
U_MEMORY_DEALLOCATOR
UCURL();
~UCURL();
static const char* apple_cert; // the path to the certificate
static const char* http2_server; // the Apple server url
static const char* app_bundle_id; // the app bundle id
/**
* @param http2_server the Apple server url
* @param apple_cert the path to the certificate
* @param app_bundle_id the app bundle id
*/
static void initHTTP2Push(const char* _http2_server = U_NULLPTR, const char* _apple_cert = U_NULLPTR, const char* _app_bundle_id = U_NULLPTR)
{
U_TRACE(0, "UCURL::initHTTP2Push(%S,%S,%S)", _http2_server, _apple_cert, _app_bundle_id)
if (_http2_server) http2_server = _http2_server;
if (_apple_cert) apple_cert = _apple_cert;
if (_app_bundle_id) app_bundle_id = _app_bundle_id;
}
/**
* @param token the token of the device
* @param message the payload to send (JSON)
*/
static bool sendHTTP2Push(const UString& token, const UString& message, UVector<UString>* pextraHeaders = U_NULLPTR);
UString& getResponse() { return response; }
// EASY
const char* error();
void setOption(CURLoption option, long parameter)
{
U_TRACE(1, "UCURL::setOption(%p,%p)", option, parameter)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(easyHandle)
result = U_SYSCALL(curl_easy_setopt, "%p,%p,%p", easyHandle, option, parameter);
# ifdef DEBUG
if (result) U_DUMP("status = %.*S", 512, error())
# endif
U_INTERNAL_ASSERT_EQUALS(result, CURLE_OK)
}
void setHTTP2()
{
U_TRACE_NO_PARAM(0, "UCURL::setHTTP2()")
setOption(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
}
void setInterface(const char* interfaceIP)
{
U_TRACE(0, "UCURL::setInterface(%S)", interfaceIP)
setOption(CURLOPT_INTERFACE, (long)interfaceIP);
}
void setURL(const char* url)
{
U_TRACE(0, "UCURL::setURL(%S)", url)
U_INTERNAL_ASSERT(u_isURL(url, u__strlen(url, __PRETTY_FUNCTION__)))
setOption(CURLOPT_URL, (long)url);
}
void setCertificate(const char* cert) // the string should be the file name of your client certificate
{
U_TRACE(0, "UCURL::setCertificate(%S)", cert)
setOption(CURLOPT_SSLCERT, (long)cert);
}
void setPort(int port)
{
U_TRACE(0, "UCURL::setPort(%d)", port)
setOption(CURLOPT_PORT, (long)port);
}
void setTimeout(long timeout)
{
U_TRACE(0, "UCURL::setTimeout(%ld)", timeout)
U_INTERNAL_ASSERT_MINOR(timeout, 1000) // NB: must be in seconds...
setOption(CURLOPT_CONNECTTIMEOUT, timeout);
}
void setMaxTime(long maxtime)
{
U_TRACE(0, "UCURL::setMaxTime(%ld)", maxtime)
U_INTERNAL_ASSERT_MINOR(maxtime, 1000) // NB: must be in seconds...
setOption(CURLOPT_TIMEOUT, maxtime);
}
void setInsecure()
{
U_TRACE_NO_PARAM(0, "UCURL::setInsecure()")
// new stuff needed for libcurl 7.10
setOption(CURLOPT_SSL_VERIFYPEER, 0);
setOption(CURLOPT_SSL_VERIFYHOST, 0);
}
void setNoBody()
{
U_TRACE_NO_PARAM(0, "UCURL::setNoBody()")
setOption(CURLOPT_NOBODY, 1L);
}
void setGetMode()
{
U_TRACE_NO_PARAM(0, "UCURL::setGetMode()")
setOption(CURLOPT_HTTPGET, 1L);
}
void setDNSCachingTime(int time)
{
U_TRACE(0, "UCURL::setDNSCachingTime(%d)", time)
setOption(CURLOPT_DNS_CACHE_TIMEOUT, (long)time);
}
void setProgressFunction(curl_progress_callback func, void* data)
{
U_TRACE(0, "UCURL::setProgressFunction(%p,%p)", func, data)
if (func == U_NULLPTR) setOption(CURLOPT_NOPROGRESS, 1L);
else
{
setOption(CURLOPT_PROGRESSFUNCTION, (long)func);
setOption(CURLOPT_PROGRESSDATA, (long)data);
setOption(CURLOPT_NOPROGRESS, 0L);
}
}
void setRequestFileTime(bool request)
{
U_TRACE(0, "UCURL::setRequestFileTime(%b)", request)
setOption(CURLOPT_FILETIME, request ? 1L : 0L);
}
void setTimeCondition(bool modified_since, time_t t)
{
U_TRACE(0, "UCURL::setTimeCondition(%b,%ld)", modified_since, t)
if (modified_since == false) setOption(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
else
{
setOption(CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
setOption(CURLOPT_TIMEVALUE, (long)t);
}
}
// HEADER
void addHeader(const char* value)
{
U_TRACE(0, "UCURL::addHeader(%S)", value)
headerlist = (struct curl_slist*) U_SYSCALL(curl_slist_append, "%p,%S", headerlist, value);
}
void addHeader(UVector<UString>& vec)
{
U_TRACE(0, "UCURL::addHeader(%p)", &vec)
for (uint32_t i = 0, n = vec.size(); i < n; ++i) addHeader(vec[i].c_str());
}
void setUserAgent(const char* userAgent)
{
U_TRACE(0, "UCURL::setUserAgent(%S)", userAgent)
setOption(CURLOPT_USERAGENT, (long)userAgent);
}
void setHeaderList()
{
U_TRACE_NO_PARAM(0, "UCURL::setHeaderList()")
U_INTERNAL_ASSERT_POINTER(headerlist)
setOption(CURLOPT_HTTPHEADER, (long)headerlist);
}
void setHeader() // pass headers to the data stream
{
U_TRACE_NO_PARAM(0, "UCURL::setHeader()")
setOption(CURLOPT_HEADER, 1L);
}
// POST - FORM
void setHTTPPostMode()
{
U_TRACE_NO_PARAM(0, "UCURL::setHTTPPostMode()")
setOption(CURLOPT_HTTPPOST, (long)formPost);
}
void setPostMode(const char* postData, uint32_t size)
{
U_TRACE(0, "UCURL::setPostMode(%.*S,%u)", size, postData, size)
U_INTERNAL_ASSERT_POINTER(postData)
setOption(CURLOPT_POSTFIELDSIZE_LARGE, (long)size); // size of the data to copy from the buffer and send in the request
setOption(CURLOPT_POSTFIELDS, (long)postData); // send data from the local stack
setOption(CURLOPT_POST, 1L);
}
void setPostMode(const UString& postData) { setPostMode(U_STRING_TO_PARAM(postData)); }
void addFormData(const char* key, const char* value)
{
U_TRACE(0, "UCURL::addFormData(%S,%S)", key, value)
CURLFORMcode res = (CURLFORMcode)
U_SYSCALL(curl_formadd, "%p,%p,%d,%S,%d,%S,%d,%d,%d",
&formPost, &formLast,
CURLFORM_COPYNAME, key,
CURLFORM_COPYCONTENTS, value,
CURLFORM_CONTENTSLENGTH, u__strlen(value, __PRETTY_FUNCTION__),
CURLFORM_END);
U_VAR_UNUSED(res)
U_INTERNAL_ASSERT_EQUALS(res, CURL_FORMADD_OK)
U_INTERNAL_ASSERT_POINTER(formPost)
U_INTERNAL_ASSERT_POINTER(formLast)
}
// EXEC
void reserve(uint32_t n)
{
U_TRACE(0, "UCURL::reserve(%u)", n)
(void) response.reserve(n);
}
bool performWait()
{
U_TRACE_NO_PARAM(1, "UCURL::performWait()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(easyHandle)
response.setEmpty();
result = U_SYSCALL(curl_easy_perform, "%p", easyHandle); // perform, then store the expected code in 'result'
infoComplete();
if (result == CURLE_OK) U_RETURN(true);
U_RETURN(false);
}
// INFO
bool getFileTime(time_t& t)
{
U_TRACE(1, "UCURL::getFileTime(%p)", &t)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(easyHandle)
long filetime;
result = U_SYSCALL(curl_easy_getinfo, "%p,%d,%p", easyHandle, CURLINFO_FILETIME, &filetime);
if (result)
{
U_DUMP("status = %.*S", 512, error())
U_RETURN(false);
}
t = (time_t) filetime;
U_RETURN(true);
}
// MULTI
void addHandle()
{
U_TRACE_NO_PARAM(1, "UCURL::addHandle()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_EQUALS(added,false)
U_INTERNAL_ASSERT_POINTER(easyHandle)
U_INTERNAL_ASSERT_POINTER(multiHandle)
added = true;
CURLMcode mresult = (CURLMcode) U_SYSCALL(curl_multi_add_handle, "%p,%p", multiHandle, easyHandle);
U_VAR_UNUSED(mresult)
U_INTERNAL_ASSERT_EQUALS(mresult, CURLM_OK)
}
void removeHandle()
{
U_TRACE_NO_PARAM(1, "UCURL::removeHandle()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT(added)
U_INTERNAL_ASSERT_POINTER(easyHandle)
U_INTERNAL_ASSERT_POINTER(multiHandle)
added = false;
CURLMcode mresult = (CURLMcode) U_SYSCALL(curl_multi_remove_handle, "%p,%p", multiHandle, easyHandle);
U_VAR_UNUSED(mresult)
U_INTERNAL_ASSERT_EQUALS(mresult, CURLM_OK)
}
static int fdset(fd_set& read, fd_set& write)
{
U_TRACE(1, "UCURL::fdset(%p,%p)", &read, &write)
U_INTERNAL_ASSERT_POINTER(multiHandle)
fd_set exc;
int max_fd = -1;
FD_ZERO(&exc);
CURLMcode mresult = (CURLMcode) U_SYSCALL(curl_multi_fdset, "%p,%p,%p,%p,%p", multiHandle, &read, &write, &exc, &max_fd);
U_VAR_UNUSED(mresult)
U_INTERNAL_ASSERT_EQUALS(mresult, CURLM_OK)
U_RETURN(max_fd);
}
static bool perform();
// DEBUG
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
const char* dump(bool reset) const;
#endif
protected:
UCURL* next;
CURL* easyHandle;
struct curl_slist* headerlist;
struct curl_httppost* formPost;
struct curl_httppost* formLast;
UString response;
int result;
bool added;
static bool inited;
static UCURL* first;
static CURLM* multiHandle;
static char errorBuffer[CURL_ERROR_SIZE];
void infoComplete();
private:
static void setup() U_NO_EXPORT;
static size_t writeFunction(void* ptr, size_t size, size_t nmemb, void* stream) U_NO_EXPORT;
U_DISALLOW_COPY_AND_ASSIGN(UCURL)
};
#endif