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 <utility>
8 
9 #include "discovery/common/config.h"
10 #include "platform/api/tls_connection_factory.h"
11 #include "platform/base/interface_info.h"
12 #include "platform/base/tls_listen_options.h"
13 #include "util/osp_logging.h"
14 #include "util/stringprintf.h"
15 
16 namespace openscreen {
17 namespace cast {
18 
19 namespace {
20 
21 constexpr uint16_t kDefaultCastServicePort = 8010;
22 
23 constexpr int kDefaultMaxBacklogSize = 64;
24 const TlsListenOptions kDefaultListenOptions{kDefaultMaxBacklogSize};
25 
DetermineEndpoint(const InterfaceInfo & interface)26 IPEndpoint DetermineEndpoint(const InterfaceInfo& interface) {
27   const IPAddress address = interface.GetIpAddressV4()
28                                 ? interface.GetIpAddressV4()
29                                 : interface.GetIpAddressV6();
30   OSP_CHECK(address);
31   return IPEndpoint{address, kDefaultCastServicePort};
32 }
33 
MakeDiscoveryConfig(const InterfaceInfo & interface)34 discovery::Config MakeDiscoveryConfig(const InterfaceInfo& interface) {
35   discovery::Config config;
36 
37   discovery::Config::NetworkInfo::AddressFamilies supported_address_families =
38       discovery::Config::NetworkInfo::kNoAddressFamily;
39   if (interface.GetIpAddressV4()) {
40     supported_address_families |= discovery::Config::NetworkInfo::kUseIpV4;
41   } else if (interface.GetIpAddressV6()) {
42     supported_address_families |= discovery::Config::NetworkInfo::kUseIpV6;
43   }
44   config.network_info.push_back({interface, supported_address_families});
45 
46   return config;
47 }
48 
49 }  // namespace
50 
CastService(TaskRunner * task_runner,const InterfaceInfo & interface,GeneratedCredentials credentials,const std::string & friendly_name,const std::string & model_name,bool enable_discovery)51 CastService::CastService(TaskRunner* task_runner,
52                          const InterfaceInfo& interface,
53                          GeneratedCredentials credentials,
54                          const std::string& friendly_name,
55                          const std::string& model_name,
56                          bool enable_discovery)
57     : local_endpoint_(DetermineEndpoint(interface)),
58       credentials_(std::move(credentials)),
59       agent_(task_runner, credentials_.provider.get()),
60       mirroring_application_(task_runner, local_endpoint_.address, &agent_),
61       socket_factory_(&agent_, agent_.cast_socket_client()),
62       connection_factory_(
63           TlsConnectionFactory::CreateFactory(&socket_factory_, task_runner)),
64       discovery_service_(enable_discovery ? discovery::CreateDnsSdService(
65                                                 task_runner,
66                                                 this,
67                                                 MakeDiscoveryConfig(interface))
68                                           : LazyDeletedDiscoveryService()),
69       discovery_publisher_(
70           discovery_service_
71               ? MakeSerialDelete<discovery::DnsSdServicePublisher<ServiceInfo>>(
72                     task_runner,
73                     discovery_service_.get(),
74                     kCastV2ServiceId,
75                     ServiceInfoToDnsSdInstance)
76               : LazyDeletedDiscoveryPublisher()) {
77   connection_factory_->SetListenCredentials(credentials_.tls_credentials);
78   connection_factory_->Listen(local_endpoint_, kDefaultListenOptions);
79 
80   if (discovery_publisher_) {
81     ServiceInfo info;
82     info.port = local_endpoint_.port;
83     info.unique_id = HexEncode(interface.hardware_address);
84     info.friendly_name = friendly_name;
85     info.model_name = model_name;
86     info.capabilities = kHasVideoOutput | kHasAudioOutput;
87     Error error = discovery_publisher_->Register(info);
88     if (!error.ok()) {
89       OnFatalError(std::move(error));
90     }
91   }
92 }
93 
~CastService()94 CastService::~CastService() {
95   if (discovery_publisher_) {
96     discovery_publisher_->DeregisterAll();
97   }
98 }
99 
OnFatalError(Error error)100 void CastService::OnFatalError(Error error) {
101   OSP_LOG_FATAL << "Encountered fatal discovery error: " << error;
102 }
103 
OnRecoverableError(Error error)104 void CastService::OnRecoverableError(Error error) {
105   OSP_LOG_ERROR << "Encountered recoverable discovery error: " << error;
106 }
107 
108 }  // namespace cast
109 }  // namespace openscreen
110