diff --git a/src/client/linux/sender/google_crash_report_sender.cc b/src/client/linux/sender/google_crash_report_sender.cc index 0d48cbe6..ec6c06e8 100644 --- a/src/client/linux/sender/google_crash_report_sender.cc +++ b/src/client/linux/sender/google_crash_report_sender.cc @@ -100,5 +100,5 @@ int main(int argc, char *argv[]) { FLAGS_crash_server, FLAGS_proxy_host, FLAGS_proxy_userpasswd); - g.Upload(); + g.Upload(NULL, NULL, NULL); } diff --git a/src/common/linux/google_crashdump_uploader.cc b/src/common/linux/google_crashdump_uploader.cc index 4da1f5e4..6d86fb36 100644 --- a/src/common/linux/google_crashdump_uploader.cc +++ b/src/common/linux/google_crashdump_uploader.cc @@ -161,7 +161,9 @@ bool GoogleCrashdumpUploader::CheckRequiredParametersArePresent() { } -bool GoogleCrashdumpUploader::Upload() { +bool GoogleCrashdumpUploader::Upload(int* http_status_code, + string* http_response_header, + string* http_response_body) { bool ok = http_layer_->Init(); if (!ok) { std::cout << "http layer init failed"; @@ -193,6 +195,8 @@ bool GoogleCrashdumpUploader::Upload() { std::cout << "Sending request to " << crash_server_; return http_layer_->SendRequest(crash_server_, parameters_, - NULL); + http_status_code, + http_response_header, + http_response_body); } } diff --git a/src/common/linux/google_crashdump_uploader.h b/src/common/linux/google_crashdump_uploader.h index 77048ae0..a2d0575b 100644 --- a/src/common/linux/google_crashdump_uploader.h +++ b/src/common/linux/google_crashdump_uploader.h @@ -79,7 +79,9 @@ class GoogleCrashdumpUploader { const string& proxy_host, const string& proxy_userpassword, LibcurlWrapper* http_layer); - bool Upload(); + bool Upload(int* http_status_code, + string* http_response_header, + string* http_response_body); private: bool CheckRequiredParametersArePresent(); diff --git a/src/common/linux/google_crashdump_uploader_test.cc b/src/common/linux/google_crashdump_uploader_test.cc index 957874ad..e94c5d62 100644 --- a/src/common/linux/google_crashdump_uploader_test.cc +++ b/src/common/linux/google_crashdump_uploader_test.cc @@ -32,7 +32,6 @@ #include #include "common/linux/google_crashdump_uploader.h" -#include "common/linux/libcurl_wrapper.h" #include "breakpad_googletest_includes.h" #include "common/using_std_string.h" @@ -48,10 +47,12 @@ class MockLibcurlWrapper : public LibcurlWrapper { const string& proxy_userpwd)); MOCK_METHOD2(AddFile, bool(const string& upload_file_path, const string& basename)); - MOCK_METHOD3(SendRequest, + MOCK_METHOD5(SendRequest, bool(const string& url, const std::map& parameters, - string* server_response)); + int* http_status_code, + string* http_header_data, + string* http_response_data)); }; class GoogleCrashdumpUploaderTest : public ::testing::Test { @@ -72,7 +73,7 @@ TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) { "", "", &m); - ASSERT_FALSE(uploader->Upload()); + ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL)); } TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { @@ -86,7 +87,7 @@ TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true)); EXPECT_CALL(m, AddFile(tempfn, _)).WillOnce(Return(true)); EXPECT_CALL(m, - SendRequest("http://foo.com",_,_)).Times(1).WillOnce(Return(true)); + SendRequest("http://foo.com",_,_,_,_)).Times(1).WillOnce(Return(true)); GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", "1.0", "AAA-BBB", @@ -99,14 +100,14 @@ TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { "", "", &m); - ASSERT_TRUE(uploader->Upload()); + ASSERT_TRUE(uploader->Upload(NULL, NULL, NULL)); } TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) { MockLibcurlWrapper m; EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true)); - EXPECT_CALL(m, SendRequest(_,_,_)).Times(0); + EXPECT_CALL(m, SendRequest(_,_,_,_,_)).Times(0); GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", "1.0", "AAA-BBB", @@ -119,7 +120,7 @@ TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) { "", "", &m); - ASSERT_FALSE(uploader->Upload()); + ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL)); } TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { @@ -135,7 +136,7 @@ TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { "http://foo.com", "", ""); - ASSERT_FALSE(uploader.Upload()); + ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); // Test with empty product version. GoogleCrashdumpUploader uploader1("product", @@ -150,7 +151,7 @@ TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { "", ""); - ASSERT_FALSE(uploader1.Upload()); + ASSERT_FALSE(uploader1.Upload(NULL, NULL, NULL)); // Test with empty client GUID. GoogleCrashdumpUploader uploader2("product", @@ -164,6 +165,6 @@ TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { "", "", ""); - ASSERT_FALSE(uploader2.Upload()); + ASSERT_FALSE(uploader2.Upload(NULL, NULL, NULL)); } } diff --git a/src/common/linux/libcurl_wrapper.cc b/src/common/linux/libcurl_wrapper.cc index 4ff9bb01..fd4e34cd 100644 --- a/src/common/linux/libcurl_wrapper.cc +++ b/src/common/linux/libcurl_wrapper.cc @@ -110,7 +110,9 @@ static size_t WriteCallback(void *ptr, size_t size, bool LibcurlWrapper::SendRequest(const string& url, const std::map& parameters, - string* server_response) { + int* http_status_code, + string* http_header_data, + string* http_response_data) { (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str()); std::map::const_iterator iter = parameters.begin(); for (; iter != parameters.end(); ++iter) @@ -120,10 +122,17 @@ bool LibcurlWrapper::SendRequest(const string& url, CURLFORM_END); (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_); - if (server_response != NULL) { + if (http_response_data != NULL) { + http_response_data->clear(); (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback); (*easy_setopt_)(curl_, CURLOPT_WRITEDATA, - reinterpret_cast(server_response)); + reinterpret_cast(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(http_header_data)); } CURLcode err_code = CURLE_OK; @@ -131,6 +140,10 @@ bool LibcurlWrapper::SendRequest(const string& url, easy_strerror_ = reinterpret_cast (dlsym(curl_lib_, "curl_easy_strerror")); + if (http_status_code != NULL) { + (*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", @@ -211,6 +224,10 @@ bool LibcurlWrapper::SetFunctionPointers() { "curl_easy_cleanup", void(*)(CURL*)); + SET_AND_CHECK_FUNCTION_POINTER(easy_getinfo_, + "curl_easy_getinfo", + CURLcode(*)(CURL *, CURLINFO info, ...)); + SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_, "curl_slist_free_all", void(*)(curl_slist*)); diff --git a/src/common/linux/libcurl_wrapper.h b/src/common/linux/libcurl_wrapper.h index b6786e44..de84a63b 100644 --- a/src/common/linux/libcurl_wrapper.h +++ b/src/common/linux/libcurl_wrapper.h @@ -51,7 +51,9 @@ class LibcurlWrapper { const string& basename); virtual bool SendRequest(const string& url, const std::map& parameters, - string* server_response); + int* http_status_code, + string* http_header_data, + string* http_response_data); private: // This function initializes class state corresponding to function // pointers into the CURL library. @@ -82,6 +84,7 @@ class LibcurlWrapper { CURLcode (*easy_perform_)(CURL *); const char* (*easy_strerror_)(CURLcode); void (*easy_cleanup_)(CURL *); + CURLcode (*easy_getinfo_)(CURL *, CURLINFO info, ...); void (*formfree_)(struct curl_httppost *); };