diff options
Diffstat (limited to 'src/common/linux/libcurl_wrapper.cc')
-rw-r--r-- | src/common/linux/libcurl_wrapper.cc | 217 |
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 |