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