xref: /aosp_15_r20/external/openscreen/cast/standalone_receiver/cast_service.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cast/standalone_receiver/cast_service.h"
6 
7 #include <stdint.h>
8 
9 #include <array>
10 #include <utility>
11 
12 #include "discovery/common/config.h"
13 #include "platform/api/tls_connection_factory.h"
14 #include "platform/base/interface_info.h"
15 #include "platform/base/tls_listen_options.h"
16 #include "util/crypto/random_bytes.h"
17 #include "util/osp_logging.h"
18 #include "util/stringprintf.h"
19 
20 namespace openscreen {
21 namespace cast {
22 
23 namespace {
24 
25 constexpr uint16_t kDefaultCastServicePort = 8010;
26 constexpr int kCastUniqueIdLength = 6;
27 
28 constexpr int kDefaultMaxBacklogSize = 64;
29 const TlsListenOptions kDefaultListenOptions{kDefaultMaxBacklogSize};
30 
DetermineEndpoint(const InterfaceInfo & interface)31 IPEndpoint DetermineEndpoint(const InterfaceInfo& interface) {
32   const IPAddress address = interface.GetIpAddressV4()
33                                 ? interface.GetIpAddressV4()
34                                 : interface.GetIpAddressV6();
35   OSP_CHECK(address);
36   return IPEndpoint{address, kDefaultCastServicePort};
37 }
38 
MakeDiscoveryConfig(const InterfaceInfo & interface)39 discovery::Config MakeDiscoveryConfig(const InterfaceInfo& interface) {
40   return discovery::Config{.network_info = {interface}};
41 }
42 
43 }  // namespace
44 
CastService(CastService::Configuration config)45 CastService::CastService(CastService::Configuration config)
46     : local_endpoint_(DetermineEndpoint(config.interface)),
47       credentials_(std::move(config.credentials)),
48       agent_(config.task_runner, credentials_.provider.get()),
49       mirroring_application_(config.task_runner,
50                              local_endpoint_.address,
51                              &agent_),
52       socket_factory_(&agent_, agent_.cast_socket_client()),
53       connection_factory_(
54           TlsConnectionFactory::CreateFactory(&socket_factory_,
55                                               config.task_runner)),
56       discovery_service_(config.enable_discovery
57                              ? discovery::CreateDnsSdService(
58                                    config.task_runner,
59                                    this,
60                                    MakeDiscoveryConfig(config.interface))
61                              : LazyDeletedDiscoveryService()),
62       discovery_publisher_(
63           discovery_service_
64               ? MakeSerialDelete<
65                     discovery::DnsSdServicePublisher<ReceiverInfo>>(
66                     config.task_runner,
67                     discovery_service_.get(),
68                     kCastV2ServiceId,
69                     ReceiverInfoToDnsSdInstance)
70               : LazyDeletedDiscoveryPublisher()) {
71   connection_factory_->SetListenCredentials(credentials_.tls_credentials);
72   connection_factory_->Listen(local_endpoint_, kDefaultListenOptions);
73 
74   if (discovery_publisher_) {
75     ReceiverInfo info;
76     info.port = local_endpoint_.port;
77     if (config.interface.HasHardwareAddress()) {
78       info.unique_id = HexEncode(config.interface.hardware_address.data(),
79                                  config.interface.hardware_address.size());
80     } else {
81       OSP_LOG_WARN << "Hardware address for interface " << config.interface.name
82                    << " is empty. Generating a random unique_id.";
83       std::array<uint8_t, kCastUniqueIdLength> random_bytes;
84       GenerateRandomBytes(random_bytes.data(), kCastUniqueIdLength);
85       info.unique_id = HexEncode(random_bytes.data(), kCastUniqueIdLength);
86     }
87     info.friendly_name = config.friendly_name;
88     info.model_name = config.model_name;
89     info.capabilities = kHasVideoOutput | kHasAudioOutput;
90     const Error error = discovery_publisher_->Register(info);
91     if (!error.ok()) {
92       OnFatalError(std::move(error));
93     }
94   }
95 }
96 
~CastService()97 CastService::~CastService() {
98   if (discovery_publisher_) {
99     discovery_publisher_->DeregisterAll();
100   }
101 }
102 
OnFatalError(Error error)103 void CastService::OnFatalError(Error error) {
104   OSP_LOG_FATAL << "Encountered fatal discovery error: " << error;
105 }
106 
OnRecoverableError(Error error)107 void CastService::OnRecoverableError(Error error) {
108   OSP_LOG_ERROR << "Encountered recoverable discovery error: " << error;
109 }
110 
111 }  // namespace cast
112 }  // namespace openscreen
113