Source code
Revision control
Copy as Markdown
Other Tools
// Copyright (c) 2019 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "common/linux/symbol_collector_client.h"
#include <stdio.h>
#include <iostream>
#include <regex>
#include "common/linux/libcurl_wrapper.h"
namespace google_breakpad {
namespace sym_upload {
// static
bool SymbolCollectorClient::CreateUploadUrl(
LibcurlWrapper* libcurl_wrapper,
const string& api_url,
const string& api_key,
UploadUrlResponse* uploadUrlResponse) {
string header, response;
long response_code;
string url = api_url + "/v1/uploads:create";
if (!api_key.empty()) {
url += "?key=" + api_key;
}
if (!libcurl_wrapper->SendSimplePostRequest(url,
/*body=*/"",
/*content_type=*/"",
&response_code,
&header,
&response)) {
printf("Failed to create upload url.\n");
printf("Response code: %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
return false;
}
// Note camel-case rather than underscores.
std::regex upload_url_regex("\"uploadUrl\": \"([^\"]+)\"");
std::regex upload_key_regex("\"uploadKey\": \"([^\"]+)\"");
std::smatch upload_url_match;
if (!std::regex_search(response, upload_url_match, upload_url_regex) ||
upload_url_match.size() != 2) {
printf("Failed to parse create url response.");
printf("Response:\n");
printf("%s\n", response.c_str());
return false;
}
string upload_url = upload_url_match[1].str();
std::smatch upload_key_match;
if (!std::regex_search(response, upload_key_match, upload_key_regex) ||
upload_key_match.size() != 2) {
printf("Failed to parse create url response.");
printf("Response:\n");
printf("%s\n", response.c_str());
return false;
}
string upload_key = upload_key_match[1].str();
uploadUrlResponse->upload_url = upload_url;
uploadUrlResponse->upload_key = upload_key;
return true;
}
// static
CompleteUploadResult SymbolCollectorClient::CompleteUpload(
LibcurlWrapper* libcurl_wrapper,
const string& api_url,
const string& api_key,
const string& upload_key,
const string& debug_file,
const string& debug_id,
const string& type) {
string header, response;
long response_code;
string url = api_url + "/v1/uploads/" + upload_key + ":complete";
if (!api_key.empty()) {
url += "?key=" + api_key;
}
string body =
"{ symbol_id: {"
"debug_file: \"" + debug_file + "\", "
"debug_id: \"" + debug_id + "\" }, "
"symbol_upload_type: \"" + type + "\" }";
if (!libcurl_wrapper->SendSimplePostRequest(url,
body,
"application/son",
&response_code,
&header,
&response)) {
printf("Failed to complete upload.\n");
printf("Response code: %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
return CompleteUploadResult::Error;
}
std::regex result_regex("\"result\": \"([^\"]+)\"");
std::smatch result_match;
if (!std::regex_search(response, result_match, result_regex) ||
result_match.size() != 2) {
printf("Failed to parse complete upload response.");
printf("Response:\n");
printf("%s\n", response.c_str());
return CompleteUploadResult::Error;
}
string result = result_match[1].str();
if (result.compare("DUPLICATE_DATA") == 0) {
return CompleteUploadResult::DuplicateData;
}
return CompleteUploadResult::Ok;
}
// static
SymbolStatus SymbolCollectorClient::CheckSymbolStatus(
LibcurlWrapper* libcurl_wrapper,
const string& api_url,
const string& api_key,
const string& debug_file,
const string& debug_id) {
string header, response;
long response_code;
string url = api_url +
"/v1/symbols/" + debug_file + "/" + debug_id + ":checkStatus";
if (!api_key.empty()) {
url += "?key=" + api_key;
}
if (!libcurl_wrapper->SendGetRequest(
url,
&response_code,
&header,
&response)) {
printf("Failed to check symbol status, error message.\n");
printf("Response code: %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
return SymbolStatus::Unknown;
}
std::regex status_regex("\"status\": \"([^\"]+)\"");
std::smatch status_match;
if (!std::regex_search(response, status_match, status_regex) ||
status_match.size() != 2) {
printf("Failed to parse check symbol status response.");
printf("Response:\n");
printf("%s\n", response.c_str());
return SymbolStatus::Unknown;
}
string status = status_match[1].str();
return (status.compare("FOUND") == 0) ?
SymbolStatus::Found :
SymbolStatus::Missing;
}
} // namespace sym_upload
} // namespace google_breakpad