| Index: common/ping.cc
|
| diff --git a/common/ping.cc b/common/ping.cc
|
| deleted file mode 100644
|
| index 181df73c6951a5e9b6ef04a7a19b09029347093a..0000000000000000000000000000000000000000
|
| --- a/common/ping.cc
|
| +++ /dev/null
|
| @@ -1,440 +0,0 @@
|
| -// Copyright 2010 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -
|
| -#include "omaha/common/ping.h"
|
| -#include "base/scoped_ptr.h"
|
| -#include "omaha/base/constants.h"
|
| -#include "omaha/base/debug.h"
|
| -#include "omaha/base/logging.h"
|
| -#include "omaha/base/scoped_any.h"
|
| -#include "omaha/base/scoped_impersonation.h"
|
| -#include "omaha/base/string.h"
|
| -#include "omaha/base/utils.h"
|
| -#include "omaha/base/vista_utils.h"
|
| -#include "omaha/common/app_registry_utils.h"
|
| -#include "omaha/common/command_line.h"
|
| -#include "omaha/common/command_line_builder.h"
|
| -#include "omaha/common/config_manager.h"
|
| -#include "omaha/common/goopdate_utils.h"
|
| -#include "omaha/common/update_request.h"
|
| -#include "omaha/common/update_response.h"
|
| -#include "omaha/goopdate/app.h"
|
| -#include "omaha/goopdate/app_bundle.h"
|
| -#include "omaha/goopdate/update_request_utils.h"
|
| -#include "omaha/goopdate/update_response_utils.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -const TCHAR* const Ping::kRegKeyPing = _T("Pings");
|
| -const time64 Ping::kPingExpiry100ns = 10 * kDaysTo100ns; // 10 days.
|
| -
|
| -Ping::Ping(bool is_machine,
|
| - const CString& session_id,
|
| - const CString& install_source)
|
| - : is_machine_(is_machine),
|
| - ping_request_(xml::UpdateRequest::Create(is_machine,
|
| - session_id,
|
| - install_source,
|
| - CString())) {
|
| -}
|
| -
|
| -Ping::~Ping() {
|
| -}
|
| -
|
| -void Ping::BuildRequest(const App* app, bool is_update_check) {
|
| - update_request_utils::BuildRequest(app, is_update_check, ping_request_.get());
|
| -}
|
| -
|
| -void Ping::LoadAppDataFromExtraArgs(const CommandLineExtraArgs& extra_args) {
|
| - const CString installation_id = GuidToString(extra_args.installation_id);
|
| - for (size_t i = 0; i != extra_args.apps.size(); ++i) {
|
| - AppData app_data;
|
| - app_data.app_id = GuidToString(extra_args.apps[i].app_guid);
|
| - app_data.language = extra_args.language;
|
| - app_data.brand_code = extra_args.brand_code;
|
| - app_data.client_id = extra_args.client_id;
|
| - app_data.installation_id = installation_id;
|
| - app_data.experiment_labels = extra_args.apps[i].experiment_labels;
|
| - apps_data_.push_back(app_data);
|
| - }
|
| -
|
| - omaha_data_.app_id = kGoogleUpdateAppId;
|
| - omaha_data_.language = extra_args.language;
|
| - omaha_data_.brand_code = extra_args.brand_code;
|
| - omaha_data_.client_id = extra_args.client_id;
|
| - omaha_data_.installation_id = installation_id;
|
| - omaha_data_.experiment_labels = extra_args.experiment_labels;
|
| -}
|
| -
|
| -void Ping::LoadOmahaDataFromRegistry() {
|
| - omaha_data_.app_id = kGoogleUpdateAppId;
|
| - app_registry_utils::GetClientStateData(
|
| - is_machine_,
|
| - kGoogleUpdateAppId,
|
| - NULL,
|
| - NULL, // ap is not used yet.
|
| - &omaha_data_.language,
|
| - &omaha_data_.brand_code,
|
| - &omaha_data_.client_id,
|
| - &omaha_data_.installation_id,
|
| - &omaha_data_.experiment_labels);
|
| -}
|
| -
|
| -void Ping::LoadAppDataFromRegistry(const std::vector<CString>& app_ids) {
|
| - for (size_t i = 0; i != app_ids.size(); ++i) {
|
| - AppData app_data;
|
| - app_data.app_id = app_ids[i];
|
| - app_registry_utils::GetClientStateData(
|
| - is_machine_,
|
| - app_data.app_id,
|
| - &app_data.pv,
|
| - NULL, // ap is not used yet.
|
| - &app_data.language,
|
| - &app_data.brand_code,
|
| - &app_data.client_id,
|
| - &app_data.installation_id,
|
| - &app_data.experiment_labels);
|
| - apps_data_.push_back(app_data);
|
| - }
|
| -
|
| - LoadOmahaDataFromRegistry();
|
| -}
|
| -
|
| -HRESULT Ping::Send(bool is_fire_and_forget) {
|
| - CORE_LOG(L3, (_T("[Ping::Send]")));
|
| -
|
| - ASSERT1(ConfigManager::Instance()->CanUseNetwork(is_machine_));
|
| -
|
| - if (ping_request_->IsEmpty()) {
|
| - CORE_LOG(L3, (_T("[Ping::Send did not send empty ping]")));
|
| - return S_FALSE;
|
| - }
|
| -
|
| - CString request_string;
|
| - HRESULT hr = BuildRequestString(&request_string);
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LE, (_T("[BuildRequestString failed][0x%08x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - const DWORD wait_timeout_ms = is_fire_and_forget ? 0 : INFINITE;
|
| - hr = SendUsingGoogleUpdate(request_string, wait_timeout_ms);
|
| - if (SUCCEEDED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - CORE_LOG(LE, (_T("[Ping::SendUsingGoogleUpdate failed][0x%x]"), hr));
|
| -
|
| - hr = SendInProcess(request_string);
|
| - if (SUCCEEDED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - CORE_LOG(LE, (_T("[Ping::SendInProcess failed][0x%x]"), hr));
|
| -
|
| - return PersistPing(is_machine_, request_string);
|
| -}
|
| -
|
| -void Ping::BuildOmahaPing(const CString& version,
|
| - const CString& next_version,
|
| - const PingEventPtr& ping_event) {
|
| - xml::request::App app(BuildOmahaApp(version, next_version));
|
| - app.ping_events.push_back(ping_event);
|
| - ping_request_->AddApp(app);
|
| -}
|
| -
|
| -void Ping::BuildOmahaPing(const CString& version,
|
| - const CString& next_version,
|
| - const PingEventPtr& ping_event1,
|
| - const PingEventPtr& ping_event2) {
|
| - xml::request::App app(BuildOmahaApp(version, next_version));
|
| - app.ping_events.push_back(ping_event1);
|
| - app.ping_events.push_back(ping_event2);
|
| - ping_request_->AddApp(app);
|
| -}
|
| -
|
| -xml::request::App Ping::BuildOmahaApp(const CString& version,
|
| - const CString& next_version) const {
|
| - xml::request::App app;
|
| -
|
| - app.app_id = omaha_data_.app_id;
|
| - app.lang = omaha_data_.language;
|
| - app.brand_code = omaha_data_.brand_code;
|
| - app.client_id = omaha_data_.client_id;
|
| - app.experiments = omaha_data_.experiment_labels;
|
| - app.iid = omaha_data_.installation_id;
|
| -
|
| - app.version = version;
|
| - app.next_version = next_version;
|
| -
|
| - return app;
|
| -}
|
| -
|
| -void Ping::BuildAppsPing(const PingEventPtr& ping_event) {
|
| - for (size_t i = 0; i != apps_data_.size(); ++i) {
|
| - xml::request::App app;
|
| -
|
| - app.version = apps_data_[i].pv;
|
| - app.app_id = apps_data_[i].app_id;
|
| - app.lang = apps_data_[i].language;
|
| - app.brand_code = apps_data_[i].brand_code;
|
| - app.client_id = apps_data_[i].client_id;
|
| - app.experiments = apps_data_[i].experiment_labels;
|
| - app.iid = apps_data_[i].installation_id;
|
| -
|
| - app.ping_events.push_back(ping_event);
|
| - ping_request_->AddApp(app);
|
| - }
|
| -}
|
| -
|
| -HRESULT Ping::SendUsingGoogleUpdate(const CString& request_string,
|
| - DWORD wait_timeout_ms) const {
|
| - CStringA request_string_utf8(WideToUtf8(request_string));
|
| - CStringA ping_string_utf8;
|
| - WebSafeBase64Escape(request_string_utf8, &ping_string_utf8);
|
| -
|
| - CommandLineBuilder builder(COMMANDLINE_MODE_PING);
|
| - builder.set_ping_string(Utf8ToWideChar(ping_string_utf8,
|
| - ping_string_utf8.GetLength()));
|
| - CString args = builder.GetCommandLineArgs();
|
| -
|
| - scoped_process ping_process;
|
| - HRESULT hr = goopdate_utils::StartGoogleUpdateWithArgs(is_machine_,
|
| - args,
|
| - address(ping_process));
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LE, (_T("[failed to start ping process][0x%08x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - if (wait_timeout_ms) {
|
| - DWORD result = ::WaitForSingleObject(get(ping_process), wait_timeout_ms);
|
| - DWORD exit_code(0);
|
| - if (result == WAIT_OBJECT_0 &&
|
| - ::GetExitCodeProcess(get(ping_process), &exit_code)) {
|
| - ASSERT1(exit_code == 0 || FAILED(exit_code));
|
| - return (exit_code == 0) ? S_OK : exit_code;
|
| - } else {
|
| - if (result == WAIT_TIMEOUT) {
|
| - CORE_LOG(LW, (_T("[ping process did not finish in time][pid=%u]"),
|
| - ::GetProcessId(get(ping_process))));
|
| - VERIFY1(::TerminateProcess(get(ping_process), UINT_MAX));
|
| - }
|
| - return E_FAIL;
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -HRESULT Ping::SendInProcess(const CString& request_string) const {
|
| - HRESULT hr = SendString(is_machine_, HeadersVector(), request_string);
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LE, (_T("[SendString failed][0x%08x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -HRESULT Ping::BuildRequestString(CString* request_string) const {
|
| - ASSERT1(request_string);
|
| - return ping_request_->Serialize(request_string);
|
| -}
|
| -
|
| -CString Ping::GetPingRegPath(bool is_machine) {
|
| - CString ping_reg_path = is_machine ? MACHINE_REG_UPDATE : USER_REG_UPDATE;
|
| - return AppendRegKeyPath(ping_reg_path, kRegKeyPing);
|
| -}
|
| -
|
| -HRESULT Ping::LoadPersistedPings(bool is_machine, PingsVector* pings) {
|
| - ASSERT1(pings);
|
| -
|
| - RegKey ping_reg_key;
|
| - HRESULT hr = ping_reg_key.Open(GetPingRegPath(is_machine), KEY_READ);
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LW, (_T("[Unable to open Ping regkey][0x%x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - int num_pings = ping_reg_key.GetValueCount();
|
| - for (int i = 0; i < num_pings; ++i) {
|
| - CString persisted_time_string;
|
| - hr = ping_reg_key.GetValueNameAt(i, &persisted_time_string, NULL);
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LW, (_T("[GetValueNameAt failed][%d]"), i));
|
| - continue;
|
| - }
|
| -
|
| - time64 persisted_time = _tcstoui64(persisted_time_string, NULL, 10);
|
| - if (persisted_time == 0 || persisted_time == _UI64_MAX) {
|
| - CORE_LOG(LW, (_T("[Incorrect time value][%s]"), persisted_time_string));
|
| - continue;
|
| - }
|
| -
|
| - CString ping_string;
|
| - hr = ping_reg_key.GetValue(persisted_time_string, &ping_string);
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LW, (_T("[GetValue failed][%s]"), persisted_time_string));
|
| - continue;
|
| - }
|
| -
|
| - pings->push_back(std::make_pair(persisted_time, ping_string));
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -bool Ping::IsPingExpired(time64 persisted_time) {
|
| - const time64 now = GetCurrent100NSTime();
|
| -
|
| - if (now < persisted_time) {
|
| - CORE_LOG(LW, (_T("[Incorrect clock time][%I64u][%I64u]"),
|
| - now, persisted_time));
|
| - return true;
|
| - }
|
| -
|
| - const time64 time_difference = now - persisted_time;
|
| - CORE_LOG(L3, (_T("[%I64u][%I64u][%I64u]"),
|
| - now, persisted_time, time_difference));
|
| -
|
| - const bool result = time_difference >= kPingExpiry100ns;
|
| - CORE_LOG(L3, (_T("[IsPingExpired][%d]"), result));
|
| - return result;
|
| -}
|
| -
|
| -HRESULT Ping::DeletePersistedPing(bool is_machine, time64 persisted_time) {
|
| - CString persisted_time_string;
|
| - persisted_time_string.Format(_T("%I64u"), persisted_time);
|
| - CORE_LOG(L3, (_T("[Ping::DeletePersistedPing][%s]"), persisted_time_string));
|
| -
|
| - CString ping_reg_path(GetPingRegPath(is_machine));
|
| - HRESULT hr = RegKey::DeleteValue(ping_reg_path, persisted_time_string);
|
| -
|
| - if (RegKey::IsKeyEmpty(ping_reg_path)) {
|
| - VERIFY1(SUCCEEDED(RegKey::DeleteKey(ping_reg_path)));
|
| - }
|
| -
|
| - return hr;
|
| -}
|
| -
|
| -HRESULT Ping::PersistPing(bool is_machine, const CString& ping_string) {
|
| - CString time_now_str;
|
| - time_now_str.Format(_T("%I64u"), GetCurrent100NSTime());
|
| - CORE_LOG(L3, (_T("[Ping::PersistPing][%s][%s]"), time_now_str, ping_string));
|
| -
|
| - return RegKey::SetValue(GetPingRegPath(is_machine),
|
| - time_now_str,
|
| - ping_string);
|
| -}
|
| -
|
| -HRESULT Ping::SendPersistedPings(bool is_machine) {
|
| - PingsVector pings;
|
| - HRESULT hr = LoadPersistedPings(is_machine, &pings);
|
| - if (FAILED(hr) && (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))) {
|
| - return hr;
|
| - }
|
| -
|
| - for (size_t i = 0; i != pings.size(); ++i) {
|
| - time64 persisted_time = pings[i].first;
|
| - int32 request_age = Time64ToInt32(GetCurrent100NSTime()) -
|
| - Time64ToInt32(persisted_time);
|
| - const CString& ping_string(pings[i].second);
|
| -
|
| - CORE_LOG(L3, (_T("[Resending ping][%I64u][%d][%s]"),
|
| - persisted_time, request_age, ping_string));
|
| -
|
| - CString request_age_string;
|
| - request_age_string.Format(_T("%d"), request_age);
|
| - HeadersVector headers;
|
| - headers.push_back(std::make_pair(kHeaderXRequestAge, request_age_string));
|
| -
|
| - hr = SendString(is_machine, headers, ping_string);
|
| -
|
| - if (SUCCEEDED(hr) || IsPingExpired(persisted_time)) {
|
| - CORE_LOG(L3, (_T("[Deleting ping][0x%x]"), hr));
|
| - VERIFY1(SUCCEEDED(DeletePersistedPing(is_machine, persisted_time)));
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// TODO(omaha): Ping support for authenticated proxies.
|
| -HRESULT Ping::SendString(bool is_machine,
|
| - const HeadersVector& headers,
|
| - const CString& request_string) {
|
| - ASSERT1(ConfigManager::Instance()->CanUseNetwork(is_machine));
|
| -
|
| - CORE_LOG(L3, (_T("[ping request string][%s]"), request_string));
|
| -
|
| - CString url;
|
| - ConfigManager::Instance()->GetPingUrl(&url);
|
| -
|
| - // Impersonate the user if the caller is machine, running as local system,
|
| - // and a user is logged on to the system.
|
| - scoped_handle impersonation_token(
|
| - goopdate_utils::GetImpersonationTokenForMachineProcess(is_machine));
|
| - scoped_impersonation impersonate_user(get(impersonation_token));
|
| -
|
| - WebServicesClient web_service_client(is_machine);
|
| - HRESULT hr(web_service_client.Initialize(url, headers, false));
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LE, (_T("[WebServicesClient::Initialize failed][0x%08x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - scoped_ptr<xml::UpdateResponse> response(xml::UpdateResponse::Create());
|
| - hr = web_service_client.SendString(&request_string, response.get());
|
| - if (FAILED(hr)) {
|
| - CORE_LOG(LE, (_T("[WebServicesClient::SendString failed][0x%08x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - // If a ping is sent but the response is corrupted in some way (or we can't
|
| - // persist the labels for some reason), returning a failure code would result
|
| - // in the ping being persisted and re-sent later. For this reason, we always
|
| - // return a success code if we sent the ping, even if following actions fail.
|
| - VERIFY1(SUCCEEDED(update_response_utils::ApplyExperimentLabelDeltas(
|
| - is_machine,
|
| - response.get())));
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -HRESULT Ping::HandlePing(bool is_machine, const CString& ping_string) {
|
| - CORE_LOG(L3, (_T("[Ping::HandlePing][%s]"), ping_string));
|
| -
|
| - CStringA ping_string_utf8(WideToUtf8(ping_string));
|
| -
|
| - CStringA request_string_utf8;
|
| - int out_buffer_length = ping_string_utf8.GetLength();
|
| - char* out_buffer = request_string_utf8.GetBufferSetLength(out_buffer_length);
|
| -
|
| - out_buffer_length = WebSafeBase64Unescape(ping_string_utf8,
|
| - ping_string_utf8.GetLength(),
|
| - out_buffer,
|
| - out_buffer_length);
|
| - ASSERT1(out_buffer_length <= ping_string_utf8.GetLength());
|
| - request_string_utf8.ReleaseBufferSetLength(out_buffer_length);
|
| -
|
| - CString request_string(Utf8ToWideChar(request_string_utf8,
|
| - request_string_utf8.GetLength()));
|
| -
|
| - return Ping::SendString(is_machine, HeadersVector(), request_string);
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
|
|