blob: 661e1b498ef3f6fe1583902b949ace8301904749 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/bin/cobalt/app/cobalt_app.h"
#include "garnet/bin/cobalt/app/utils.h"
#include "garnet/bin/cobalt/utils/fuchsia_http_client.h"
#include "lib/backoff/exponential_backoff.h"
#include "third_party/cobalt/encoder/memory_observation_store.h"
namespace cobalt {
namespace http = ::fuchsia::net::oldhttp;
using clearcut::ClearcutUploader;
using config::ClientConfig;
using encoder::ClearcutV1ShippingManager;
using encoder::ClientSecret;
using encoder::CobaltEncoderFactoryImpl;
using encoder::LegacyShippingManager;
using encoder::MemoryObservationStore;
using encoder::ShippingManager;
using utils::FuchsiaHTTPClient;
// Each "send attempt" is actually a cycle of potential retries. These
// two parameters configure the SendRetryer.
const std::chrono::seconds kInitialRpcDeadline(10);
const std::chrono::seconds kDeadlinePerSendAttempt(60);
const size_t kMaxBytesPerEnvelope = 512 * 1024; // 0.5 MiB.
const size_t kMaxBytesTotal = 1024 * 1024; // 1 MiB
constexpr char kCloudShufflerUri[] = "shuffler.cobalt-api.fuchsia.com:443";
const char kClearcutServerUri[] = "https://jmt17.google.com/log";
constexpr char kConfigBinProtoPath[] = "/pkg/data/cobalt_config.binproto";
constexpr char kAnalyzerPublicKeyPemPath[] =
"/pkg/data/certs/cobaltv0.1/analyzer_public.pem";
constexpr char kShufflerPublicKeyPemPath[] =
"/pkg/data/certs/cobaltv0.1/shuffler_public.pem";
CobaltApp::CobaltApp(async_dispatcher_t* dispatcher,
std::chrono::seconds schedule_interval,
std::chrono::seconds min_interval,
const std::string& product_name)
: system_data_(product_name),
context_(component::StartupContext::CreateFromStartupInfo()),
shuffler_client_(kCloudShufflerUri, true),
send_retryer_(&shuffler_client_),
network_wrapper_(
dispatcher, std::make_unique<backoff::ExponentialBackoff>(),
[this] {
return context_->ConnectToEnvironmentService<http::HttpService>();
}),
encrypt_to_analyzer_(ReadPublicKeyPem(kAnalyzerPublicKeyPemPath),
EncryptedMessage::HYBRID_ECDH_V1),
encrypt_to_shuffler_(ReadPublicKeyPem(kShufflerPublicKeyPemPath),
EncryptedMessage::HYBRID_ECDH_V1),
timer_manager_(dispatcher),
controller_impl_(
new CobaltControllerImpl(dispatcher, &shipping_dispatcher_)) {
store_dispatcher_.Register(ObservationMetadata::LEGACY_BACKEND,
std::make_unique<MemoryObservationStore>(
fuchsia::cobalt::MAX_BYTES_PER_OBSERVATION,
kMaxBytesPerEnvelope, kMaxBytesTotal));
store_dispatcher_.Register(ObservationMetadata::V1_BACKEND,
std::make_unique<MemoryObservationStore>(
fuchsia::cobalt::MAX_BYTES_PER_OBSERVATION,
kMaxBytesPerEnvelope, kMaxBytesTotal));
auto schedule_params =
ShippingManager::ScheduleParams(schedule_interval, min_interval);
shipping_dispatcher_.Register(
ObservationMetadata::LEGACY_BACKEND,
std::make_unique<LegacyShippingManager>(
schedule_params,
store_dispatcher_.GetStore(ObservationMetadata::LEGACY_BACKEND)
.ConsumeValueOrDie(),
&encrypt_to_shuffler_,
LegacyShippingManager::SendRetryerParams(kInitialRpcDeadline,
kDeadlinePerSendAttempt),
&send_retryer_));
shipping_dispatcher_.Register(
ObservationMetadata::V1_BACKEND,
std::make_unique<ClearcutV1ShippingManager>(
schedule_params,
store_dispatcher_.GetStore(ObservationMetadata::V1_BACKEND)
.ConsumeValueOrDie(),
&encrypt_to_shuffler_,
std::make_unique<ClearcutUploader>(
kClearcutServerUri, std::make_unique<FuchsiaHTTPClient>(
&network_wrapper_, dispatcher))));
shipping_dispatcher_.Start();
// Open the cobalt config file.
std::ifstream config_file_stream;
config_file_stream.open(kConfigBinProtoPath);
FXL_CHECK(config_file_stream && config_file_stream.good())
<< "Could not open the Cobalt config file: " << kConfigBinProtoPath;
std::string cobalt_config_bytes;
cobalt_config_bytes.assign(
(std::istreambuf_iterator<char>(config_file_stream)),
std::istreambuf_iterator<char>());
FXL_CHECK(!cobalt_config_bytes.empty())
<< "Could not read the Cobalt config file: " << kConfigBinProtoPath;
// Parse the data as a CobaltConfig, then extract the metric and encoding
// configs and construct a ClientConfig to house them.
client_config_.reset(
ClientConfig::CreateFromCobaltConfigBytes(cobalt_config_bytes).release());
FXL_CHECK(client_config_)
<< "Could not parse the Cobalt config file: " << kConfigBinProtoPath;
factory_impl_.reset(new CobaltEncoderFactoryImpl(
client_config_, getClientSecret(), &store_dispatcher_,
&encrypt_to_analyzer_, &shipping_dispatcher_, &system_data_,
&timer_manager_));
context_->outgoing().AddPublicService(
factory_bindings_.GetHandler(factory_impl_.get()));
context_->outgoing().AddPublicService(
controller_bindings_.GetHandler(controller_impl_.get()));
}
ClientSecret CobaltApp::getClientSecret() {
// TODO(rudominer): Generate a client secret only once, store it
// persistently and reuse it in future instances.
return ClientSecret::GenerateNewSecret();
}
} // namespace cobalt