host/curlwrapperlib/curlwrapper.h (193 lines of code) (raw):
///
/// \file curlwrapper.h
///
/// \brief
///
#ifndef CURLWRAPPER_H
#define CURLWRAPPER_H
#include <boost/shared_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>
#include <curl/curl.h>
#include <openssl/ssl.h>
#include "errorexception.h"
#include "atloc.h"
typedef size_t (*curlReadCallback) (void *buffer, size_t size, size_t nitems, void *istream);
typedef size_t (*curlWriteCallback) (void *buffer, size_t size, size_t nitems, void *ostream);
class CurlOptions {
public:
CurlOptions(const std::string &fullUrl) : m_server(std::string()),
m_port(0),
m_partialurl("/request_handler.php"),
m_secure(true),
m_debug(false),
m_ignorepartialError(false),
m_encode(false),
m_timeout(300),
m_responsetimeout(300),
m_speedlimit(0),
m_speedtime(0),
m_rdcallback(0),
m_istream(0),
m_wrcallback(0),
m_ostream(0),
m_minValidResCode(200),
m_maxValidResCode(200),
m_caFile(std::string())
{
m_fullUrl = fullUrl;
parseUrl(m_fullUrl);
}
CurlOptions(const std::string &server, const int port, const std::string &partialurl, const bool secure = true) : m_server(std::string()),
m_port(0),
m_partialurl("/request_handler.php"),
m_secure(true),
m_debug(false),
m_ignorepartialError(false),
m_encode(false),
m_timeout(300),
m_responsetimeout(300),
m_speedlimit(0),
m_speedtime(0),
m_rdcallback(0),
m_istream(0),
m_wrcallback(0),
m_ostream(0),
m_minValidResCode(200),
m_maxValidResCode(200),
m_caFile(std::string())
{
if (secure) {
m_fullUrl = std::string("https://");
}
else {
m_fullUrl = std::string("http://");
}
m_fullUrl += server;
m_fullUrl += ":";
m_fullUrl += boost::lexical_cast<std::string>(port);
if ('/' != partialurl[0]) {
m_fullUrl += "/";
}
m_fullUrl += partialurl;
parseUrl(m_fullUrl);
}
// Set the onoff parameter to 1 to make the library encode the post data
// default: no encoding
CurlOptions& encode(const bool onoff) { m_encode = onoff; return *this; }
// CURLOPT_VERBOSE - display verbose information
// Set the onoff parameter to 1 to make the library display a lot of verbose information
// about its operations on the curl handle. Very useful for libcurl and/or protocol debugging
// and understanding. The verbose information will be sent to stderr, or the stream set with CURLOPT_STDERR.
// default: off
CurlOptions& debug(const bool onoff) { m_debug = onoff; return *this; }
// NOTE: we have seen some cases where curl thinks it got partial or no file data but it really got everything (as best that we can tell)
// this will allow the code to continue if the IgnoreCurlPartialFileErrors has been enabled in drscout conf
// default: false
CurlOptions& ignorePartialError(const bool ignore) { m_ignorepartialError = ignore ; return *this; }
// CURLOPT_TIMEOUT - maximum time the request is allowed to take
// maximum time in seconds that you allow the libcurl transfer operation to take.
// Normally, name lookups can take a considerable time and limiting operations to
// less than a few minutes risk aborting perfectly normal operations.
// default: 300 secs
CurlOptions& transferTimeout(const int secs) { m_timeout = secs ; return *this; }
// CURLOPT_FTP_RESPONSE_TIMEOUT - time allowed to wait for server response
// causes libcurl to set a timeout period (in seconds) on the amount of time that the
// server is allowed to take in order to send a response message for a command before
// the session is considered dead. While libcurl is waiting for a response,
// this value overrides CURLOPT_TIMEOUT. It is recommended that if used in conjunction
// with CURLOPT_TIMEOUT, you set CURLOPT_FTP_RESPONSE_TIMEOUT to a value smaller than CURLOPT_TIMEOUT.
// default: 300 secs
CurlOptions& responseTimeout(const int secs) { m_responsetimeout = secs ; return *this; }
// CURLOPT_LOW_SPEED_LIMIT - Low speed limit to abort transfer
// CURLOPT_LOW_SPEED_TIME - Time to be below the speed to trigger low speed abort.
// average transfer speed in bytes per second that the transfer should be below
// during lowSpeedTime seconds for libcurl to consider it to be too slow and abort
// default: disabled
CurlOptions& lowSpeedLimit(const int speedlimit) { m_speedlimit = speedlimit ; return *this; }
CurlOptions& lowSpeedTime(const int speedtime) { m_speedtime = speedtime ; return *this; }
// callback - set read callback for data uploads
// istream - application maintained pointer to pass to the callback
// default : none
CurlOptions & readCallback(void * istream, curlReadCallback fun)
{ m_rdcallback = fun ; m_istream = istream; return *this; }
// callback - set callback for writing received data
// ostream - application maintained pointer to pass to the callback
// default: return data in passed in string
CurlOptions & writeCallback(void * ostream, curlWriteCallback callback)
{ m_wrcallback = callback ; m_ostream = ostream ; return *this; }
// Set the range of valid response codes [min:max] for curl operation
// default : 200
CurlOptions & validResponseRange(int min, int max) {
if(max < min ) {
throw ERROR_EXCEPTION << "invalid inputs" << " min:" << min << " max:" << max << "\n";
}
m_minValidResCode = min ; m_maxValidResCode = max;
return *this;
}
// Set ca File
// default : empty string
CurlOptions & caFile(const std::string caFile){ m_caFile = caFile; return *this; }
std::string server() const {return m_server ; }
int port() const {return m_port ; }
std::string partialUrl() const { return m_partialurl; }
std::string parameters() const { return m_parameters; }
bool isSecure() const {return m_secure;}
std::string fullUrl() const {return m_fullUrl ; }
bool debug() const { return m_debug ; }
bool ignorePartialError() const { return m_ignorepartialError ; }
bool encode() const { return m_encode ; }
int transferTimeout() const { return m_timeout ; }
int responseTimeout() const { return m_responsetimeout ; }
int lowSpeedLimit() const { return m_speedlimit ; }
int lowSpeedTime() const { return m_speedtime ; }
curlReadCallback readCallback() const { return m_rdcallback ;}
void * readStream() const { return m_istream ; }
curlWriteCallback writeCallback() const { return m_wrcallback ;}
void * writeStream() const { return m_ostream ; }
int minValidResCode() const {return m_minValidResCode;}
int maxValidResCode() const {return m_maxValidResCode;}
std::string caFile() const {return m_caFile;}
private:
void parseUrl(const std::string & fullUrl) {
std::vector<std::string> url_fields;
boost::regex url_expression(
// protocol csip csport csfolder file parameters
"^(\?:([^:/\?#]+)://)\?(\\w+[^/\?#:]*)(\?::(\\d+))\?(/\?(\?:[^\?#/]*/)*)\?([^\?#]*)\?(\\\?(.*))\?"
);
std::string url_to_parse = fullUrl;
if (boost::regex_split(std::back_inserter(url_fields), url_to_parse, url_expression)) {
if (url_fields[0] == "https") {
m_secure = true;
} else {
m_secure = false;
}
m_server = url_fields[1];
m_port = boost::lexical_cast<int>(url_fields[2]);
m_partialurl = url_fields[3] + url_fields[4];
m_parameters = url_fields[5];
}
else {
throw ERROR_EXCEPTION << "invalid url" << fullUrl << "\n";
}
}
std::string m_server;
int m_port;
std::string m_partialurl;
std::string m_parameters;
bool m_secure;
std::string m_fullUrl;
bool m_debug;
bool m_ignorepartialError;
bool m_encode;
int m_timeout;
int m_responsetimeout;
int m_speedlimit;
int m_speedtime;
curlReadCallback m_rdcallback;
void * m_istream;
curlWriteCallback m_wrcallback;
void * m_ostream;
int m_minValidResCode;
int m_maxValidResCode;
std::string m_caFile;
};
class CurlWrapper {
public:
CurlWrapper()
:m_handle( curl_easy_init(), curl_easy_cleanup )
{
}
void post(const CurlOptions & options, std::string const& data) {
std::string result;
post(options,data.c_str(), result);
}
void post(const CurlOptions & options, std::string const& data, std::string & result) {
post(options, data.c_str(), result);
}
void post(const CurlOptions & options, const char * msg) {
std::string result;
post(options, msg, result);
}
void post(const CurlOptions & options, const char * msg, std::string & result);
void formPost(const CurlOptions & options, struct curl_httppost *formpost, struct curl_slist **ppheaders = NULL);
void formPost(const CurlOptions & options, struct curl_httppost *formpost, std::string & result, struct curl_slist **ppheaders = NULL);
bool opensslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx)
{
return true;
}
std::string server() const { return m_server; }
int port() const { return m_port; }
protected:
void configCa(std::string const& caFile);
void setOptions(const CurlOptions & options);
void processCurlResponse(CURLcode curlCode, bool ignorePartialError,int minValidResCode, int maxValidResCode);
std::string generateSignature(const CurlOptions & options, const std::string &requestId, const std::string & http_method, const std::string& functionName);
void loadPassphrase();
private:
std::string m_server;
std::string m_caFile;
int m_port;
bool m_secure;
boost::shared_ptr<CURL> m_handle;
};
#endif // CURLWRAPPER_H