aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux/libcurl_wrapper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/linux/libcurl_wrapper.cc')
-rw-r--r--src/common/linux/libcurl_wrapper.cc217
1 files changed, 151 insertions, 66 deletions
diff --git a/src/common/linux/libcurl_wrapper.cc b/src/common/linux/libcurl_wrapper.cc
index fd4e34cd..d935174b 100644
--- a/src/common/linux/libcurl_wrapper.cc
+++ b/src/common/linux/libcurl_wrapper.cc
@@ -38,32 +38,24 @@
namespace google_breakpad {
LibcurlWrapper::LibcurlWrapper()
: init_ok_(false),
- formpost_(NULL),
- lastptr_(NULL),
- headerlist_(NULL) {
- curl_lib_ = dlopen("libcurl.so", RTLD_NOW);
- if (!curl_lib_) {
- curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW);
- }
- if (!curl_lib_) {
- curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW);
- }
- if (!curl_lib_) {
- std::cout << "Could not find libcurl via dlopen";
- return;
+ curl_lib_(nullptr),
+ last_curl_error_(""),
+ curl_(nullptr),
+ formpost_(nullptr),
+ lastptr_(nullptr),
+ headerlist_(nullptr) {}
+
+LibcurlWrapper::~LibcurlWrapper() {
+ if (init_ok_) {
+ (*easy_cleanup_)(curl_);
+ dlclose(curl_lib_);
}
- std::cout << "LibcurlWrapper init succeeded";
- init_ok_ = true;
- return;
}
-LibcurlWrapper::~LibcurlWrapper() {}
-
bool LibcurlWrapper::SetProxy(const string& proxy_host,
const string& proxy_userpwd) {
- if (!init_ok_) {
- return false;
- }
+ if (!CheckInit()) return false;
+
// Set proxy information if necessary.
if (!proxy_host.empty()) {
(*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str());
@@ -83,9 +75,8 @@ bool LibcurlWrapper::SetProxy(const string& proxy_host,
bool LibcurlWrapper::AddFile(const string& upload_file_path,
const string& basename) {
- if (!init_ok_) {
- return false;
- }
+ if (!CheckInit()) return false;
+
std::cout << "Adding " << upload_file_path << " to form upload.";
// Add form file.
(*formadd_)(&formpost_, &lastptr_,
@@ -110,10 +101,11 @@ static size_t WriteCallback(void *ptr, size_t size,
bool LibcurlWrapper::SendRequest(const string& url,
const std::map<string, string>& parameters,
- int* http_status_code,
+ long* http_status_code,
string* http_header_data,
string* http_response_data) {
- (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str());
+ if (!CheckInit()) return false;
+
std::map<string, string>::const_iterator iter = parameters.begin();
for (; iter != parameters.end(); ++iter)
(*formadd_)(&formpost_, &lastptr_,
@@ -122,55 +114,79 @@ bool LibcurlWrapper::SendRequest(const string& url,
CURLFORM_END);
(*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_);
- if (http_response_data != NULL) {
- http_response_data->clear();
- (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback);
- (*easy_setopt_)(curl_, CURLOPT_WRITEDATA,
- reinterpret_cast<void *>(http_response_data));
- }
- if (http_header_data != NULL) {
- http_header_data->clear();
- (*easy_setopt_)(curl_, CURLOPT_HEADERFUNCTION, WriteCallback);
- (*easy_setopt_)(curl_, CURLOPT_HEADERDATA,
- reinterpret_cast<void *>(http_header_data));
- }
- CURLcode err_code = CURLE_OK;
- err_code = (*easy_perform_)(curl_);
- easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)>
- (dlsym(curl_lib_, "curl_easy_strerror"));
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
- if (http_status_code != NULL) {
- (*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code);
- }
+bool LibcurlWrapper::SendGetRequest(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
-#ifndef NDEBUG
- if (err_code != CURLE_OK)
- fprintf(stderr, "Failed to send http request to %s, error: %s\n",
- url.c_str(),
- (*easy_strerror_)(err_code));
-#endif
- if (headerlist_ != NULL) {
- (*slist_free_all_)(headerlist_);
- }
+ (*easy_setopt_)(curl_, CURLOPT_HTTPGET, 1L);
- (*easy_cleanup_)(curl_);
- if (formpost_ != NULL) {
- (*formfree_)(formpost_);
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::SendPutRequest(const string& url,
+ const string& path,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ FILE* file = fopen(path.c_str(), "rb");
+ (*easy_setopt_)(curl_, CURLOPT_UPLOAD, 1L);
+ (*easy_setopt_)(curl_, CURLOPT_PUT, 1L);
+ (*easy_setopt_)(curl_, CURLOPT_READDATA, file);
+
+ bool success = SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+
+ fclose(file);
+ return success;
+}
+
+bool LibcurlWrapper::SendSimplePostRequest(const string& url,
+ const string& body,
+ const string& content_type,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ (*easy_setopt_)(curl_, CURLOPT_POSTFIELDSIZE, body.size());
+ (*easy_setopt_)(curl_, CURLOPT_COPYPOSTFIELDS, body.c_str());
+
+ if (!content_type.empty()) {
+ string content_type_header = "Content-Type: " + content_type;
+ headerlist_ = (*slist_append_)(
+ headerlist_,
+ content_type_header.c_str());
}
- return err_code == CURLE_OK;
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
}
bool LibcurlWrapper::Init() {
- if (!init_ok_) {
- std::cout << "Init_OK was not true in LibcurlWrapper::Init(), check earlier log messages";
+ curl_lib_ = dlopen("libcurl.so", RTLD_NOW);
+ if (!curl_lib_) {
+ curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW);
+ }
+ if (!curl_lib_) {
+ curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW);
+ }
+ if (!curl_lib_) {
+ std::cout << "Could not find libcurl via dlopen";
return false;
}
if (!SetFunctionPointers()) {
std::cout << "Could not find function pointers";
- init_ok_ = false;
return false;
}
@@ -184,11 +200,7 @@ bool LibcurlWrapper::Init() {
return false;
}
- // Disable 100-continue header.
- char buf[] = "Expect:";
-
- headerlist_ = (*slist_append_)(headerlist_, buf);
- (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
+ init_ok_ = true;
return true;
}
@@ -228,6 +240,10 @@ bool LibcurlWrapper::SetFunctionPointers() {
"curl_easy_getinfo",
CURLcode(*)(CURL *, CURLINFO info, ...));
+ SET_AND_CHECK_FUNCTION_POINTER(easy_reset_,
+ "curl_easy_reset",
+ void(*)(CURL*));
+
SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_,
"curl_slist_free_all",
void(*)(curl_slist*));
@@ -238,4 +254,73 @@ bool LibcurlWrapper::SetFunctionPointers() {
return true;
}
+bool LibcurlWrapper::SendRequestInner(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ string url_copy(url);
+ (*easy_setopt_)(curl_, CURLOPT_URL, url_copy.c_str());
+
+ // Disable 100-continue header.
+ char buf[] = "Expect:";
+ headerlist_ = (*slist_append_)(headerlist_, buf);
+ (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
+
+ if (http_response_data != nullptr) {
+ http_response_data->clear();
+ (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback);
+ (*easy_setopt_)(curl_, CURLOPT_WRITEDATA,
+ reinterpret_cast<void*>(http_response_data));
+ }
+ if (http_header_data != nullptr) {
+ http_header_data->clear();
+ (*easy_setopt_)(curl_, CURLOPT_HEADERFUNCTION, WriteCallback);
+ (*easy_setopt_)(curl_, CURLOPT_HEADERDATA,
+ reinterpret_cast<void*>(http_header_data));
+ }
+ CURLcode err_code = CURLE_OK;
+ err_code = (*easy_perform_)(curl_);
+ easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)>
+ (dlsym(curl_lib_, "curl_easy_strerror"));
+
+ if (http_status_code != nullptr) {
+ (*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code);
+ }
+
+#ifndef NDEBUG
+ if (err_code != CURLE_OK)
+ fprintf(stderr, "Failed to send http request to %s, error: %s\n",
+ url.c_str(),
+ (*easy_strerror_)(err_code));
+#endif
+
+ Reset();
+
+ return err_code == CURLE_OK;
+}
+
+void LibcurlWrapper::Reset() {
+ if (headerlist_ != nullptr) {
+ (*slist_free_all_)(headerlist_);
+ headerlist_ = nullptr;
+ }
+
+ if (formpost_ != nullptr) {
+ (*formfree_)(formpost_);
+ formpost_ = nullptr;
+ }
+
+ (*easy_reset_)(curl_);
+}
+
+bool LibcurlWrapper::CheckInit() {
+ if (!init_ok_) {
+ std::cout << "LibcurlWrapper: You must call Init(), and have it return "
+ "'true' before invoking any other methods.\n";
+ return false;
+ }
+
+ return true;
}
+
+} // namespace google_breakpad