diff options
Diffstat (limited to 'cast/common')
17 files changed, 215 insertions, 222 deletions
diff --git a/cast/common/BUILD.gn b/cast/common/BUILD.gn index ae32bf4a..154d436e 100644 --- a/cast/common/BUILD.gn +++ b/cast/common/BUILD.gn @@ -83,15 +83,15 @@ source_set("public") { sources = [ "public/cast_socket.h", "public/message_port.h", - "public/service_info.cc", - "public/service_info.h", + "public/receiver_info.cc", + "public/receiver_info.h", ] deps = [ - "../../discovery:dnssd", "../../discovery:public", "../../platform", "../../third_party/abseil", + "../../util", ] } @@ -107,6 +107,7 @@ if (!build_with_chromium) { ":public", "../../discovery:dnssd", "../../discovery:public", + "../../platform:standalone_impl", "../../testing/util", "../../third_party/googletest:gtest", ] @@ -129,7 +130,7 @@ source_set("test_helpers") { ":certificate", ":channel", ":public", - "../../discovery:dnssd", + "../../discovery:public", "../../platform:test", "../../testing/util", "../../third_party/abseil", @@ -153,7 +154,7 @@ source_set("unittests") { "channel/message_framer_unittest.cc", "channel/namespace_router_unittest.cc", "channel/virtual_connection_router_unittest.cc", - "public/service_info_unittest.cc", + "public/receiver_info_unittest.cc", ] deps = [ diff --git a/cast/common/certificate/cast_cert_validator.cc b/cast/common/certificate/cast_cert_validator.cc index b66f8859..f8ee66f7 100644 --- a/cast/common/certificate/cast_cert_validator.cc +++ b/cast/common/certificate/cast_cert_validator.cc @@ -103,18 +103,18 @@ CastDeviceCertPolicy GetAudioPolicy(const std::vector<X509*>& path) { int pos = X509_get_ext_by_NID(cert, NID_certificate_policies, -1); if (pos != -1) { X509_EXTENSION* policies_extension = X509_get_ext(cert, pos); - const uint8_t* in = policies_extension->value->data; - CERTIFICATEPOLICIES* policies = d2i_CERTIFICATEPOLICIES( - nullptr, &in, policies_extension->value->length); + const ASN1_STRING* value = X509_EXTENSION_get_data(policies_extension); + const uint8_t* in = ASN1_STRING_get0_data(value); + CERTIFICATEPOLICIES* policies = + d2i_CERTIFICATEPOLICIES(nullptr, &in, ASN1_STRING_length(value)); if (policies) { // Check for |audio_only_policy_oid| in the set of policies. uint32_t policy_count = sk_POLICYINFO_num(policies); for (uint32_t i = 0; i < policy_count; ++i) { POLICYINFO* info = sk_POLICYINFO_value(policies, i); - if (info->policyid->length == - static_cast<int>(audio_only_policy_oid.length) && - memcmp(info->policyid->data, audio_only_policy_oid.data, + if (OBJ_length(info->policyid) == audio_only_policy_oid.length && + memcmp(OBJ_get0_data(info->policyid), audio_only_policy_oid.data, audio_only_policy_oid.length) == 0) { policy = CastDeviceCertPolicy::kAudioOnly; break; @@ -162,10 +162,17 @@ Error VerifyDeviceCert(const std::vector<std::string>& der_certs, // CertVerificationContextImpl. X509_NAME* target_subject = X509_get_subject_name(result_path.target_cert.get()); - std::string common_name(target_subject->canon_enclen, 0); - int len = X509_NAME_get_text_by_NID(target_subject, NID_commonName, - &common_name[0], common_name.size()); - if (len == 0) { + int len = + X509_NAME_get_text_by_NID(target_subject, NID_commonName, nullptr, 0); + if (len <= 0) { + return Error::Code::kErrCertsRestrictions; + } + // X509_NAME_get_text_by_NID writes one more byte than it reports, for a + // trailing NUL. + std::string common_name(len + 1, 0); + len = X509_NAME_get_text_by_NID(target_subject, NID_commonName, + &common_name[0], common_name.size()); + if (len <= 0) { return Error::Code::kErrCertsRestrictions; } common_name.resize(len); diff --git a/cast/common/certificate/cast_cert_validator_internal.cc b/cast/common/certificate/cast_cert_validator_internal.cc index 764ac3e4..073b76ac 100644 --- a/cast/common/certificate/cast_cert_validator_internal.cc +++ b/cast/common/certificate/cast_cert_validator_internal.cc @@ -18,6 +18,7 @@ #include <utility> #include <vector> +#include "absl/strings/str_cat.h" #include "cast/common/certificate/types.h" #include "util/crypto/pem_helpers.h" #include "util/osp_logging.h" @@ -407,29 +408,30 @@ Error FindCertificatePath(const std::vector<std::string>& der_certs, result_path->intermediate_certs; target_cert.reset(ParseX509Der(der_certs[0])); if (!target_cert) { - OSP_DVLOG << "FindCertificatePath: Invalid target certificate"; - return Error::Code::kErrCertsParse; + return Error(Error::Code::kErrCertsParse, + "FindCertificatePath: Invalid target certificate"); } for (size_t i = 1; i < der_certs.size(); ++i) { intermediate_certs.emplace_back(ParseX509Der(der_certs[i])); if (!intermediate_certs.back()) { - OSP_DVLOG - << "FindCertificatePath: Failed to parse intermediate certificate " - << i << " of " << der_certs.size(); - return Error::Code::kErrCertsParse; + return Error( + Error::Code::kErrCertsParse, + absl::StrCat( + "FindCertificatePath: Failed to parse intermediate certificate ", + i, " of ", der_certs.size())); } } // Basic checks on the target certificate. - Error::Code error = VerifyCertTime(target_cert.get(), time); - if (error != Error::Code::kNone) { - OSP_DVLOG << "FindCertificatePath: Failed to verify certificate time"; - return error; + Error::Code valid_time = VerifyCertTime(target_cert.get(), time); + if (valid_time != Error::Code::kNone) { + return Error(valid_time, + "FindCertificatePath: Failed to verify certificate time"); } bssl::UniquePtr<EVP_PKEY> public_key{X509_get_pubkey(target_cert.get())}; if (!VerifyPublicKeyLength(public_key.get())) { - OSP_DVLOG << "FindCertificatePath: Failed with invalid public key length"; - return Error::Code::kErrCertsVerifyGeneric; + return Error(Error::Code::kErrCertsVerifyGeneric, + "FindCertificatePath: Failed with invalid public key length"); } const X509_ALGOR* sig_alg; X509_get0_signature(nullptr, &sig_alg, target_cert.get()); @@ -438,14 +440,14 @@ Error FindCertificatePath(const std::vector<std::string>& der_certs, } bssl::UniquePtr<ASN1_BIT_STRING> key_usage = GetKeyUsage(target_cert.get()); if (!key_usage) { - OSP_DVLOG << "FindCertificatePath: Failed with no key usage"; - return Error::Code::kErrCertsRestrictions; + return Error(Error::Code::kErrCertsRestrictions, + "FindCertificatePath: Failed with no key usage"); } int bit = ASN1_BIT_STRING_get_bit(key_usage.get(), KeyUsageBits::kDigitalSignature); if (bit == 0) { - OSP_DVLOG << "FindCertificatePath: Failed to get digital signature"; - return Error::Code::kErrCertsRestrictions; + return Error(Error::Code::kErrCertsRestrictions, + "FindCertificatePath: Failed to get digital signature"); } X509* path_head = target_cert.get(); @@ -478,8 +480,8 @@ Error FindCertificatePath(const std::vector<std::string>& der_certs, Error::Code last_error = Error::Code::kNone; for (;;) { X509_NAME* target_issuer_name = X509_get_issuer_name(path_head); - OSP_DVLOG << "FindCertificatePath: Target certificate issuer name: " - << X509_NAME_oneline(target_issuer_name, 0, 0); + OSP_VLOG << "FindCertificatePath: Target certificate issuer name: " + << X509_NAME_oneline(target_issuer_name, 0, 0); // The next issuer certificate to add to the current path. X509* next_issuer = nullptr; @@ -488,8 +490,8 @@ Error FindCertificatePath(const std::vector<std::string>& der_certs, X509* trust_store_cert = trust_store->certs[i].get(); X509_NAME* trust_store_cert_name = X509_get_subject_name(trust_store_cert); - OSP_DVLOG << "FindCertificatePath: Trust store certificate issuer name: " - << X509_NAME_oneline(trust_store_cert_name, 0, 0); + OSP_VLOG << "FindCertificatePath: Trust store certificate issuer name: " + << X509_NAME_oneline(trust_store_cert_name, 0, 0); if (X509_NAME_cmp(trust_store_cert_name, target_issuer_name) == 0) { CertPathStep& next_step = path[--path_index]; next_step.cert = trust_store_cert; @@ -524,9 +526,9 @@ Error FindCertificatePath(const std::vector<std::string>& der_certs, if (path_index == first_index) { // There are no more paths to try. Ensure an error is returned. if (last_error == Error::Code::kNone) { - OSP_DVLOG << "FindCertificatePath: Failed after trying all " - "certificate paths, no matches"; - return Error::Code::kErrCertsVerifyUntrustedCert; + return Error(Error::Code::kErrCertsVerifyUntrustedCert, + "FindCertificatePath: Failed after trying all " + "certificate paths, no matches"); } return last_error; } else { @@ -556,7 +558,7 @@ Error FindCertificatePath(const std::vector<std::string>& der_certs, result_path->path.push_back(path[i].cert); } - OSP_DVLOG + OSP_VLOG << "FindCertificatePath: Succeeded at validating receiver certificates"; return Error::Code::kNone; } diff --git a/cast/common/certificate/types.cc b/cast/common/certificate/types.cc index d891c0a9..2c8fecc1 100644 --- a/cast/common/certificate/types.cc +++ b/cast/common/certificate/types.cc @@ -55,7 +55,7 @@ bool DateTimeFromSeconds(uint64_t seconds, DateTime* time) { #if defined(_WIN32) // NOTE: This is for compiling in Chromium and is not validated in any direct // libcast Windows build. - if (!gmtime_s(&tm, &sec)) { + if (gmtime_s(&tm, &sec)) { return false; } #else diff --git a/cast/common/channel/cast_socket.cc b/cast/common/channel/cast_socket.cc index 0479c997..e06cde46 100644 --- a/cast/common/channel/cast_socket.cc +++ b/cast/common/channel/cast_socket.cc @@ -14,6 +14,8 @@ namespace cast { using ::cast::channel::CastMessage; using message_serialization::DeserializeResult; +CastSocket::Client::~Client() = default; + CastSocket::CastSocket(std::unique_ptr<TlsConnection> connection, Client* client) : connection_(std::move(connection)), diff --git a/cast/common/channel/cast_socket_message_port.cc b/cast/common/channel/cast_socket_message_port.cc index 0c51304b..bdc33f20 100644 --- a/cast/common/channel/cast_socket_message_port.cc +++ b/cast/common/channel/cast_socket_message_port.cc @@ -93,7 +93,6 @@ void CastSocketMessagePort::OnMessage(VirtualConnectionRouter* router, return; } - OSP_DVLOG << "Received a cast socket message"; if (!client_) { OSP_DLOG_WARN << "Dropping message due to nullptr client_"; return; diff --git a/cast/common/channel/connection_namespace_handler.cc b/cast/common/channel/connection_namespace_handler.cc index d3b2ea8b..c50b97be 100644 --- a/cast/common/channel/connection_namespace_handler.cc +++ b/cast/common/channel/connection_namespace_handler.cc @@ -221,8 +221,8 @@ void ConnectionNamespaceHandler::HandleConnect(CastSocket* socket, data.ip_fragment = {}; } - OSP_DVLOG << "Connection opened: " << virtual_conn.local_id << ", " - << virtual_conn.peer_id << ", " << virtual_conn.socket_id; + OSP_VLOG << "Connection opened: " << virtual_conn.local_id << ", " + << virtual_conn.peer_id << ", " << virtual_conn.socket_id; // NOTE: Only send a response for senders that actually sent a version. This // maintains compatibility with older senders that don't send a version and @@ -242,9 +242,9 @@ void ConnectionNamespaceHandler::HandleClose(CastSocket* socket, ToCastSocketId(socket)}; const auto reason = GetCloseReason(parsed_message); if (RemoveConnection(conn, reason)) { - OSP_DVLOG << "Connection closed (reason: " << reason - << "): " << conn.local_id << ", " << conn.peer_id << ", " - << conn.socket_id; + OSP_VLOG << "Connection closed (reason: " << reason + << "): " << conn.local_id << ", " << conn.peer_id << ", " + << conn.socket_id; } } diff --git a/cast/common/channel/message_util.cc b/cast/common/channel/message_util.cc index 92ea5007..f7f790bf 100644 --- a/cast/common/channel/message_util.cc +++ b/cast/common/channel/message_util.cc @@ -162,5 +162,12 @@ std::string MakeUniqueSessionId(const char* prefix) { return oss.str(); } +bool HasType(const Json::Value& object, CastMessageType type) { + OSP_DCHECK(object.isObject()); + const Json::Value& value = + object.get(kMessageKeyType, Json::Value::nullSingleton()); + return value.isString() && value.asString() == CastMessageTypeToString(type); +} + } // namespace cast } // namespace openscreen diff --git a/cast/common/channel/message_util.h b/cast/common/channel/message_util.h index 8e8fe823..6eef5b11 100644 --- a/cast/common/channel/message_util.h +++ b/cast/common/channel/message_util.h @@ -9,6 +9,11 @@ #include "absl/strings/string_view.h" #include "cast/common/channel/proto/cast_channel.pb.h" +#include "util/enum_name_table.h" + +namespace Json { +class Value; +} namespace openscreen { namespace cast { @@ -158,63 +163,35 @@ enum class AppAvailabilityResult { std::string ToString(AppAvailabilityResult availability); -// TODO(crbug.com/openscreen/111): When this and/or other enums need the -// string->enum mapping, import EnumTable from Chromium's -// //components/cast_channel/enum_table.h. -inline constexpr const char* CastMessageTypeToString(CastMessageType type) { - switch (type) { - case CastMessageType::kPing: - return "PING"; - case CastMessageType::kPong: - return "PONG"; - case CastMessageType::kRpc: - return "RPC"; - case CastMessageType::kGetAppAvailability: - return "GET_APP_AVAILABILITY"; - case CastMessageType::kGetStatus: - return "GET_STATUS"; - case CastMessageType::kConnect: - return "CONNECT"; - case CastMessageType::kCloseConnection: - return "CLOSE"; - case CastMessageType::kBroadcast: - return "APPLICATION_BROADCAST"; - case CastMessageType::kLaunch: - return "LAUNCH"; - case CastMessageType::kStop: - return "STOP"; - case CastMessageType::kReceiverStatus: - return "RECEIVER_STATUS"; - case CastMessageType::kMediaStatus: - return "MEDIA_STATUS"; - case CastMessageType::kLaunchError: - return "LAUNCH_ERROR"; - case CastMessageType::kOffer: - return "OFFER"; - case CastMessageType::kAnswer: - return "ANSWER"; - case CastMessageType::kCapabilitiesResponse: - return "CAPABILITIES_RESPONSE"; - case CastMessageType::kStatusResponse: - return "STATUS_RESPONSE"; - case CastMessageType::kMultizoneStatus: - return "MULTIZONE_STATUS"; - case CastMessageType::kInvalidPlayerState: - return "INVALID_PLAYER_STATE"; - case CastMessageType::kLoadFailed: - return "LOAD_FAILED"; - case CastMessageType::kLoadCancelled: - return "LOAD_CANCELLED"; - case CastMessageType::kInvalidRequest: - return "INVALID_REQUEST"; - case CastMessageType::kPresentation: - return "PRESENTATION"; - case CastMessageType::kGetCapabilities: - return "GET_CAPABILITIES"; - case CastMessageType::kOther: - default: - return "OTHER"; - } +static const EnumNameTable<CastMessageType, 25> kCastMessageTypeNames{ + {{"PING", CastMessageType::kPing}, + {"PONG", CastMessageType::kPong}, + {"RPC", CastMessageType::kRpc}, + {"GET_APP_AVAILABILITY", CastMessageType::kGetAppAvailability}, + {"GET_STATUS", CastMessageType::kGetStatus}, + {"CONNECT", CastMessageType::kConnect}, + {"CLOSE", CastMessageType::kCloseConnection}, + {"APPLICATION_BROADCAST", CastMessageType::kBroadcast}, + {"LAUNCH", CastMessageType::kLaunch}, + {"STOP", CastMessageType::kStop}, + {"RECEIVER_STATUS", CastMessageType::kReceiverStatus}, + {"MEDIA_STATUS", CastMessageType::kMediaStatus}, + {"LAUNCH_ERROR", CastMessageType::kLaunchError}, + {"OFFER", CastMessageType::kOffer}, + {"ANSWER", CastMessageType::kAnswer}, + {"CAPABILITIES_RESPONSE", CastMessageType::kCapabilitiesResponse}, + {"STATUS_RESPONSE", CastMessageType::kStatusResponse}, + {"MULTIZONE_STATUS", CastMessageType::kMultizoneStatus}, + {"INVALID_PLAYER_STATE", CastMessageType::kInvalidPlayerState}, + {"LOAD_FAILED", CastMessageType::kLoadFailed}, + {"LOAD_CANCELLED", CastMessageType::kLoadCancelled}, + {"INVALID_REQUEST", CastMessageType::kInvalidRequest}, + {"PRESENTATION", CastMessageType::kPresentation}, + {"GET_CAPABILITIES", CastMessageType::kGetCapabilities}, + {"OTHER", CastMessageType::kOther}}}; + +inline const char* CastMessageTypeToString(CastMessageType type) { + return GetEnumName(kCastMessageTypeNames, type).value("OTHER"); } inline bool IsAuthMessage(const ::cast::channel::CastMessage& message) { @@ -242,6 +219,8 @@ inline bool IsTransportNamespace(absl::string_view namespace_) { // |prefix| of "sender" will result in a string like "sender-12345". std::string MakeUniqueSessionId(const char* prefix); +// Returns true if the type field in |object| is set to the given |type|. +bool HasType(const Json::Value& object, CastMessageType type); } // namespace cast } // namespace openscreen diff --git a/cast/common/discovery/e2e_test/tests.cc b/cast/common/discovery/e2e_test/tests.cc index 7c294418..3f316ae3 100644 --- a/cast/common/discovery/e2e_test/tests.cc +++ b/cast/common/discovery/e2e_test/tests.cc @@ -11,7 +11,7 @@ // ASSERTS due to asynchronous concerns around test failures. // Although this causes the entire test binary to fail instead of // just a single test, it makes debugging easier/possible. -#include "cast/common/public/service_info.h" +#include "cast/common/public/receiver_info.h" #include "discovery/common/config.h" #include "discovery/common/reporting_client.h" #include "discovery/public/dns_sd_service_factory.h" @@ -44,12 +44,12 @@ constexpr milliseconds kCheckLoopSleepTime(100); constexpr int kMaxCheckLoopIterations = 25; // Publishes new service instances. -class Publisher : public discovery::DnsSdServicePublisher<ServiceInfo> { +class Publisher : public discovery::DnsSdServicePublisher<ReceiverInfo> { public: explicit Publisher(discovery::DnsSdService* service) // NOLINT - : DnsSdServicePublisher<ServiceInfo>(service, - kCastV2ServiceId, - ServiceInfoToDnsSdInstance) { + : DnsSdServicePublisher<ReceiverInfo>(service, + kCastV2ServiceId, + ReceiverInfoToDnsSdInstance) { OSP_LOG_INFO << "Initializing Publisher...\n"; } @@ -71,40 +71,40 @@ class Publisher : public discovery::DnsSdServicePublisher<ServiceInfo> { }; // Receives incoming services and outputs their results to stdout. -class ServiceReceiver : public discovery::DnsSdServiceWatcher<ServiceInfo> { +class ServiceReceiver : public discovery::DnsSdServiceWatcher<ReceiverInfo> { public: explicit ServiceReceiver(discovery::DnsSdService* service) // NOLINT - : discovery::DnsSdServiceWatcher<ServiceInfo>( + : discovery::DnsSdServiceWatcher<ReceiverInfo>( service, kCastV2ServiceId, - DnsSdInstanceEndpointToServiceInfo, + DnsSdInstanceEndpointToReceiverInfo, [this]( - std::vector<std::reference_wrapper<const ServiceInfo>> infos) { + std::vector<std::reference_wrapper<const ReceiverInfo>> infos) { ProcessResults(std::move(infos)); }) { OSP_LOG_INFO << "Initializing ServiceReceiver..."; } - bool IsServiceFound(const ServiceInfo& check_service) { - return std::find_if(service_infos_.begin(), service_infos_.end(), - [&check_service](const ServiceInfo& info) { + bool IsServiceFound(const ReceiverInfo& check_service) { + return std::find_if(receiver_infos_.begin(), receiver_infos_.end(), + [&check_service](const ReceiverInfo& info) { return info.friendly_name == check_service.friendly_name; - }) != service_infos_.end(); + }) != receiver_infos_.end(); } - void EraseReceivedServices() { service_infos_.clear(); } + void EraseReceivedServices() { receiver_infos_.clear(); } private: void ProcessResults( - std::vector<std::reference_wrapper<const ServiceInfo>> infos) { - service_infos_.clear(); - for (const ServiceInfo& info : infos) { - service_infos_.push_back(info); + std::vector<std::reference_wrapper<const ReceiverInfo>> infos) { + receiver_infos_.clear(); + for (const ReceiverInfo& info : infos) { + receiver_infos_.push_back(info); } } - std::vector<ServiceInfo> service_infos_; + std::vector<ReceiverInfo> receiver_infos_; }; class FailOnErrorReporting : public discovery::ReportingClient { @@ -125,16 +125,7 @@ discovery::Config GetConfigSettings() { // Get the loopback interface to run on. InterfaceInfo loopback = GetLoopbackInterfaceForTesting().value(); OSP_LOG_INFO << "Selected network interface for testing: " << loopback; - discovery::Config::NetworkInfo::AddressFamilies address_families = - discovery::Config::NetworkInfo::kNoAddressFamily; - if (loopback.GetIpAddressV4()) { - address_families |= discovery::Config::NetworkInfo::kUseIpV4; - } - if (loopback.GetIpAddressV6()) { - address_families |= discovery::Config::NetworkInfo::kUseIpV6; - } - - return discovery::Config{{{std::move(loopback), address_families}}}; + return discovery::Config{{std::move(loopback)}}; } class DiscoveryE2ETest : public testing::Test { @@ -154,8 +145,8 @@ class DiscoveryE2ETest : public testing::Test { } protected: - ServiceInfo GetInfo(int id) { - ServiceInfo hosted_service; + ReceiverInfo GetInfo(int id) { + ReceiverInfo hosted_service; hosted_service.port = 1234; hosted_service.unique_id = "id" + std::to_string(id); hosted_service.model_name = "openscreen-Model" + std::to_string(id); @@ -188,8 +179,8 @@ class DiscoveryE2ETest : public testing::Test { OSP_DCHECK(dnssd_service_.get()); OSP_DCHECK(publisher_.get()); - std::vector<ServiceInfo> record_set{std::move(records)...}; - for (ServiceInfo& record : record_set) { + std::vector<ReceiverInfo> record_set{std::move(records)...}; + for (ReceiverInfo& record : record_set) { task_runner_->PostTask([this, r = std::move(record)]() { auto error = publisher_->UpdateRegistration(r); OSP_CHECK(error.ok()) << "\tFailed to update service instance '" @@ -203,8 +194,8 @@ class DiscoveryE2ETest : public testing::Test { OSP_DCHECK(dnssd_service_.get()); OSP_DCHECK(publisher_.get()); - std::vector<ServiceInfo> record_set{std::move(records)...}; - for (ServiceInfo& record : record_set) { + std::vector<ReceiverInfo> record_set{std::move(records)...}; + for (ReceiverInfo& record : record_set) { task_runner_->PostTask([this, r = std::move(record)]() { auto error = publisher_->Register(r); OSP_CHECK(error.ok()) << "\tFailed to publish service instance '" @@ -239,20 +230,20 @@ class DiscoveryE2ETest : public testing::Test { << "Could not find " << waiting_on << " service instances!"; } - void CheckForClaimedIds(ServiceInfo service_info, + void CheckForClaimedIds(ReceiverInfo receiver_info, std::atomic_bool* has_been_seen) { OSP_DCHECK(dnssd_service_.get()); task_runner_->PostTask( - [this, info = std::move(service_info), has_been_seen]() mutable { + [this, info = std::move(receiver_info), has_been_seen]() mutable { CheckForClaimedIds(std::move(info), has_been_seen, 0); }); } - void CheckForPublishedService(ServiceInfo service_info, + void CheckForPublishedService(ReceiverInfo receiver_info, std::atomic_bool* has_been_seen) { OSP_DCHECK(dnssd_service_.get()); task_runner_->PostTask( - [this, info = std::move(service_info), has_been_seen]() mutable { + [this, info = std::move(receiver_info), has_been_seen]() mutable { CheckForPublishedService(std::move(info), has_been_seen, 0, true); }); } @@ -260,11 +251,11 @@ class DiscoveryE2ETest : public testing::Test { // TODO(issuetracker.google.com/159256503): Change this to use a polling // method to wait until the service disappears rather than immediately failing // if it exists, so waits throughout this file can be removed. - void CheckNotPublishedService(ServiceInfo service_info, + void CheckNotPublishedService(ReceiverInfo receiver_info, std::atomic_bool* has_been_seen) { OSP_DCHECK(dnssd_service_.get()); task_runner_->PostTask( - [this, info = std::move(service_info), has_been_seen]() mutable { + [this, info = std::move(receiver_info), has_been_seen]() mutable { CheckForPublishedService(std::move(info), has_been_seen, 0, false); }); } @@ -275,37 +266,38 @@ class DiscoveryE2ETest : public testing::Test { std::unique_ptr<Publisher> publisher_; private: - void CheckForClaimedIds(ServiceInfo service_info, + void CheckForClaimedIds(ReceiverInfo receiver_info, std::atomic_bool* has_been_seen, int attempts) { - if (publisher_->IsInstanceIdClaimed(service_info.GetInstanceId())) { + if (publisher_->IsInstanceIdClaimed(receiver_info.GetInstanceId())) { // TODO(crbug.com/openscreen/110): Log the published service instance. *has_been_seen = true; return; } OSP_CHECK_LE(attempts++, kMaxCheckLoopIterations) - << "Service " << service_info.friendly_name << " publication failed."; + << "Service " << receiver_info.friendly_name << " publication failed."; task_runner_->PostTaskWithDelay( - [this, info = std::move(service_info), has_been_seen, + [this, info = std::move(receiver_info), has_been_seen, attempts]() mutable { CheckForClaimedIds(std::move(info), has_been_seen, attempts); }, kCheckLoopSleepTime); } - void CheckForPublishedService(ServiceInfo service_info, + void CheckForPublishedService(ReceiverInfo receiver_info, std::atomic_bool* has_been_seen, int attempts, bool expect_to_be_present) { - if (!receiver_->IsServiceFound(service_info)) { + if (!receiver_->IsServiceFound(receiver_info)) { if (attempts++ > kMaxCheckLoopIterations) { OSP_CHECK(!expect_to_be_present) - << "Service " << service_info.friendly_name << " discovery failed."; + << "Service " << receiver_info.friendly_name + << " discovery failed."; return; } task_runner_->PostTaskWithDelay( - [this, info = std::move(service_info), has_been_seen, attempts, + [this, info = std::move(receiver_info), has_been_seen, attempts, expect_to_be_present]() mutable { CheckForPublishedService(std::move(info), has_been_seen, attempts, expect_to_be_present); @@ -315,7 +307,8 @@ class DiscoveryE2ETest : public testing::Test { // TODO(crbug.com/openscreen/110): Log the discovered service instance. *has_been_seen = true; } else { - OSP_LOG_FATAL << "Found instance '" << service_info.friendly_name << "'!"; + OSP_LOG_FATAL << "Found instance '" << receiver_info.friendly_name + << "'!"; } } }; diff --git a/cast/common/public/DEPS b/cast/common/public/DEPS index c098d4db..d31bade2 100644 --- a/cast/common/public/DEPS +++ b/cast/common/public/DEPS @@ -4,5 +4,6 @@ include_rules = [ # Dependencies on the implementation are not allowed in public/. '-cast/common', '+cast/common/public', - '+discovery/dnssd/public' + '+discovery/dnssd/public', + '+discovery/mdns/public' ] diff --git a/cast/common/public/cast_socket.h b/cast/common/public/cast_socket.h index 5c0b8775..330b1962 100644 --- a/cast/common/public/cast_socket.h +++ b/cast/common/public/cast_socket.h @@ -28,13 +28,15 @@ class CastSocket : public TlsConnection::Client { public: class Client { public: - virtual ~Client() = default; // Called when a terminal error on |socket| has occurred. virtual void OnError(CastSocket* socket, Error error) = 0; virtual void OnMessage(CastSocket* socket, ::cast::channel::CastMessage message) = 0; + + protected: + virtual ~Client(); }; CastSocket(std::unique_ptr<TlsConnection> connection, Client* client); diff --git a/cast/common/public/message_port.h b/cast/common/public/message_port.h index 23094740..91eabcd1 100644 --- a/cast/common/public/message_port.h +++ b/cast/common/public/message_port.h @@ -20,11 +20,13 @@ class MessagePort { public: class Client { public: - virtual ~Client() = default; virtual void OnMessage(const std::string& source_sender_id, const std::string& message_namespace, const std::string& message) = 0; virtual void OnError(Error error) = 0; + + protected: + virtual ~Client() = default; }; virtual ~MessagePort() = default; diff --git a/cast/common/public/service_info.cc b/cast/common/public/receiver_info.cc index 732688f8..ec45efea 100644 --- a/cast/common/public/service_info.cc +++ b/cast/common/public/receiver_info.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cast/common/public/service_info.h" +#include "cast/common/public/receiver_info.h" #include <cctype> #include <cinttypes> @@ -11,49 +11,47 @@ #include "absl/strings/numbers.h" #include "absl/strings/str_replace.h" +#include "discovery/mdns/public/mdns_constants.h" #include "util/osp_logging.h" namespace openscreen { namespace cast { namespace { -// Maximum size for registered MDNS service instance names. -const size_t kMaxDeviceNameSize = 63; - -// Maximum size for the device model prefix at start of MDNS service instance +// Maximum size for the receiver model prefix at start of MDNS service instance // names. Any model names that are larger than this size will be truncated. -const size_t kMaxDeviceModelSize = 20; +const size_t kMaxReceiverModelSize = 20; -// Build the MDNS instance name for service. This will be the device model (up -// to 20 bytes) appended with the virtual device ID (device UUID) and optionally -// appended with extension at the end to resolve name conflicts. The total MDNS -// service instance name is kept below 64 bytes so it can easily fit into a -// single domain name label. +// Build the MDNS instance name for service. This will be the receiver model (up +// to 20 bytes) appended with the virtual receiver ID (receiver UUID) and +// optionally appended with extension at the end to resolve name conflicts. The +// total MDNS service instance name is kept below 64 bytes so it can easily fit +// into a single domain name label. // // NOTE: This value is based on what is currently done by Eureka, not what is // called out in the CastV2 spec. Eureka uses |model|-|uuid|, so the same // convention will be followed here. That being said, the Eureka receiver does // not use the instance ID in any way, so the specific calculation used should // not be important. -std::string CalculateInstanceId(const ServiceInfo& info) { - // First set the device model, truncated to 20 bytes at most. Replace any - // whitespace characters (" ") with hyphens ("-") in the device model before +std::string CalculateInstanceId(const ReceiverInfo& info) { + // First set the receiver model, truncated to 20 bytes at most. Replace any + // whitespace characters (" ") with hyphens ("-") in the receiver model before // truncation. std::string instance_name = absl::StrReplaceAll(info.model_name, {{" ", "-"}}); - instance_name = std::string(instance_name, 0, kMaxDeviceModelSize); + instance_name = std::string(instance_name, 0, kMaxReceiverModelSize); - // Append the virtual device ID to the instance name separated by a single - // '-' character if not empty. Strip all hyphens from the device ID prior + // Append the receiver ID to the instance name separated by a single + // '-' character if not empty. Strip all hyphens from the receiver ID prior // to appending it. - std::string device_id = absl::StrReplaceAll(info.unique_id, {{"-", ""}}); + std::string receiver_id = absl::StrReplaceAll(info.unique_id, {{"-", ""}}); if (!instance_name.empty()) { instance_name.push_back('-'); } - instance_name.append(device_id); + instance_name.append(receiver_id); - return std::string(instance_name, 0, kMaxDeviceNameSize); + return std::string(instance_name, 0, discovery::kMaxLabelLength); } // Returns the value for the provided |key| in the |txt| record if it exists; @@ -71,7 +69,7 @@ std::string GetStringFromRecord(const discovery::DnsSdTxtRecord& txt, } // namespace -const std::string& ServiceInfo::GetInstanceId() const { +const std::string& ReceiverInfo::GetInstanceId() const { if (instance_id_ == std::string("")) { instance_id_ = CalculateInstanceId(*this); } @@ -79,7 +77,7 @@ const std::string& ServiceInfo::GetInstanceId() const { return instance_id_; } -bool ServiceInfo::IsValid() const { +bool ReceiverInfo::IsValid() const { return ( discovery::IsInstanceValid(GetInstanceId()) && port != 0 && !unique_id.empty() && @@ -98,7 +96,7 @@ bool ServiceInfo::IsValid() const { friendly_name)); } -discovery::DnsSdInstance ServiceInfoToDnsSdInstance(const ServiceInfo& info) { +discovery::DnsSdInstance ReceiverInfoToDnsSdInstance(const ReceiverInfo& info) { OSP_DCHECK(discovery::IsServiceValid(kCastV2ServiceId)); OSP_DCHECK(discovery::IsDomainValid(kCastV2DomainId)); @@ -121,13 +119,13 @@ discovery::DnsSdInstance ServiceInfoToDnsSdInstance(const ServiceInfo& info) { kCastV2DomainId, std::move(txt), info.port); } -ErrorOr<ServiceInfo> DnsSdInstanceEndpointToServiceInfo( +ErrorOr<ReceiverInfo> DnsSdInstanceEndpointToReceiverInfo( const discovery::DnsSdInstanceEndpoint& endpoint) { if (endpoint.service_id() != kCastV2ServiceId) { - return {Error::Code::kParameterInvalid, "Not a Cast device."}; + return {Error::Code::kParameterInvalid, "Not a Cast receiver."}; } - ServiceInfo record; + ReceiverInfo record; for (const IPAddress& address : endpoint.addresses()) { if (!record.v4_address && address.IsV4()) { record.v4_address = address; @@ -148,7 +146,7 @@ ErrorOr<ServiceInfo> DnsSdInstanceEndpointToServiceInfo( record.unique_id = GetStringFromRecord(endpoint.txt(), kUniqueIdKey); if (record.unique_id.empty()) { return {Error::Code::kParameterInvalid, - "Missing device unique ID in record."}; + "Missing receiver unique ID in record."}; } // Cast protocol version supported. Begins at 2 and is incremented by 1 with @@ -169,15 +167,15 @@ ErrorOr<ServiceInfo> DnsSdInstanceEndpointToServiceInfo( } record.protocol_version = static_cast<uint8_t>(version); - // A bitset of device capabilities. + // A bitset of receiver capabilities. a_decimal_number = GetStringFromRecord(endpoint.txt(), kCapabilitiesKey); if (a_decimal_number.empty()) { return {Error::Code::kParameterInvalid, - "Missing device capabilities in record."}; + "Missing receiver capabilities in record."}; } if (!absl::SimpleAtoi(a_decimal_number, &record.capabilities)) { return {Error::Code::kParameterInvalid, - "Invalid device capabilities field in record."}; + "Invalid receiver capabilities field in record."}; } // Receiver status flag. @@ -194,11 +192,11 @@ ErrorOr<ServiceInfo> DnsSdInstanceEndpointToServiceInfo( // [Optional] Receiver model name. record.model_name = GetStringFromRecord(endpoint.txt(), kModelNameKey); - // The friendly name of the device. + // The friendly name of the receiver. record.friendly_name = GetStringFromRecord(endpoint.txt(), kFriendlyNameKey); if (record.friendly_name.empty()) { return {Error::Code::kParameterInvalid, - "Missing device friendly name in record."}; + "Missing receiver friendly name in record."}; } return record; diff --git a/cast/common/public/service_info.h b/cast/common/public/receiver_info.h index 301ef99f..c4e82c82 100644 --- a/cast/common/public/service_info.h +++ b/cast/common/public/receiver_info.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CAST_COMMON_PUBLIC_SERVICE_INFO_H_ -#define CAST_COMMON_PUBLIC_SERVICE_INFO_H_ +#ifndef CAST_COMMON_PUBLIC_RECEIVER_INFO_H_ +#define CAST_COMMON_PUBLIC_RECEIVER_INFO_H_ #include <memory> #include <string> @@ -53,14 +53,13 @@ constexpr uint64_t kIsDevModeEnabled = 1 << 4; constexpr uint64_t kNoCapabilities = 0; -// This is the top-level service info class for CastV2. It describes a specific +// This is the top-level receiver info class for CastV2. It describes a specific // service instance. -// TODO(crbug.com/openscreen/112): Rename this to CastReceiverInfo or similar. -struct ServiceInfo { - // returns the instance id associated with this ServiceInfo instance. +struct ReceiverInfo { + // returns the instance id associated with this ReceiverInfo instance. const std::string& GetInstanceId() const; - // Returns whether all fields of this ServiceInfo are valid. + // Returns whether all fields of this ReceiverInfo are valid. bool IsValid() const; // Addresses for the service. Present if an address of this address type @@ -88,17 +87,17 @@ struct ServiceInfo { // Status of the service instance. ReceiverStatus status = ReceiverStatus::kIdle; - // The model name of the device, e.g. “Eureka v1”, “Mollie”. + // The model name of the receiver, e.g. “Eureka v1”, “Mollie”. std::string model_name; - // The friendly name of the device, e.g. “Living Room TV". + // The friendly name of the receiver, e.g. “Living Room TV". std::string friendly_name; private: mutable std::string instance_id_ = ""; }; -inline bool operator==(const ServiceInfo& lhs, const ServiceInfo& rhs) { +inline bool operator==(const ReceiverInfo& lhs, const ReceiverInfo& rhs) { return lhs.v4_address == rhs.v4_address && lhs.v6_address == rhs.v6_address && lhs.port == rhs.port && lhs.unique_id == rhs.unique_id && lhs.protocol_version == rhs.protocol_version && @@ -107,18 +106,19 @@ inline bool operator==(const ServiceInfo& lhs, const ServiceInfo& rhs) { lhs.friendly_name == rhs.friendly_name; } -inline bool operator!=(const ServiceInfo& lhs, const ServiceInfo& rhs) { +inline bool operator!=(const ReceiverInfo& lhs, const ReceiverInfo& rhs) { return !(lhs == rhs); } // Functions responsible for converting between CastV2 and DNS-SD // representations of a service instance. -discovery::DnsSdInstance ServiceInfoToDnsSdInstance(const ServiceInfo& service); +discovery::DnsSdInstance ReceiverInfoToDnsSdInstance( + const ReceiverInfo& service); -ErrorOr<ServiceInfo> DnsSdInstanceEndpointToServiceInfo( +ErrorOr<ReceiverInfo> DnsSdInstanceEndpointToReceiverInfo( const discovery::DnsSdInstanceEndpoint& endpoint); } // namespace cast } // namespace openscreen -#endif // CAST_COMMON_PUBLIC_SERVICE_INFO_H_ +#endif // CAST_COMMON_PUBLIC_RECEIVER_INFO_H_ diff --git a/cast/common/public/service_info_unittest.cc b/cast/common/public/receiver_info_unittest.cc index 08401a45..a7b16e2d 100644 --- a/cast/common/public/service_info_unittest.cc +++ b/cast/common/public/receiver_info_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cast/common/public/service_info.h" +#include "cast/common/public/receiver_info.h" #include <cstdio> #include <sstream> @@ -20,13 +20,13 @@ constexpr NetworkInterfaceIndex kNetworkInterface = 0; } -TEST(ServiceInfoTests, ConvertValidFromDnsSd) { +TEST(ReceiverInfoTests, ConvertValidFromDnsSd) { std::string instance = "InstanceId"; discovery::DnsSdTxtRecord txt = CreateValidTxt(); discovery::DnsSdInstanceEndpoint record( instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); - ErrorOr<ServiceInfo> info = DnsSdInstanceEndpointToServiceInfo(record); + ErrorOr<ReceiverInfo> info = DnsSdInstanceEndpointToReceiverInfo(record); ASSERT_TRUE(info.is_value()) << info; EXPECT_EQ(info.value().unique_id, kTestUniqueId); EXPECT_TRUE(info.value().v4_address); @@ -44,7 +44,7 @@ TEST(ServiceInfoTests, ConvertValidFromDnsSd) { record = discovery::DnsSdInstanceEndpoint(instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4); - info = DnsSdInstanceEndpointToServiceInfo(record); + info = DnsSdInstanceEndpointToReceiverInfo(record); ASSERT_TRUE(info.is_value()); EXPECT_EQ(info.value().unique_id, kTestUniqueId); EXPECT_TRUE(info.value().v4_address); @@ -60,7 +60,7 @@ TEST(ServiceInfoTests, ConvertValidFromDnsSd) { record = discovery::DnsSdInstanceEndpoint(instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV6); - info = DnsSdInstanceEndpointToServiceInfo(record); + info = DnsSdInstanceEndpointToReceiverInfo(record); ASSERT_TRUE(info.is_value()); EXPECT_EQ(info.value().unique_id, kTestUniqueId); EXPECT_FALSE(info.value().v4_address); @@ -74,42 +74,42 @@ TEST(ServiceInfoTests, ConvertValidFromDnsSd) { EXPECT_EQ(info.value().friendly_name, kFriendlyName); } -TEST(ServiceInfoTests, ConvertInvalidFromDnsSd) { +TEST(ReceiverInfoTests, ConvertInvalidFromDnsSd) { std::string instance = "InstanceId"; discovery::DnsSdTxtRecord txt = CreateValidTxt(); txt.ClearValue(kUniqueIdKey); discovery::DnsSdInstanceEndpoint record( instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); - EXPECT_TRUE(DnsSdInstanceEndpointToServiceInfo(record).is_error()); + EXPECT_TRUE(DnsSdInstanceEndpointToReceiverInfo(record).is_error()); txt = CreateValidTxt(); txt.ClearValue(kVersionKey); record = discovery::DnsSdInstanceEndpoint( instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); - EXPECT_TRUE(DnsSdInstanceEndpointToServiceInfo(record).is_error()); + EXPECT_TRUE(DnsSdInstanceEndpointToReceiverInfo(record).is_error()); txt = CreateValidTxt(); txt.ClearValue(kCapabilitiesKey); record = discovery::DnsSdInstanceEndpoint( instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); - EXPECT_TRUE(DnsSdInstanceEndpointToServiceInfo(record).is_error()); + EXPECT_TRUE(DnsSdInstanceEndpointToReceiverInfo(record).is_error()); txt = CreateValidTxt(); txt.ClearValue(kStatusKey); record = discovery::DnsSdInstanceEndpoint( instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); - EXPECT_TRUE(DnsSdInstanceEndpointToServiceInfo(record).is_error()); + EXPECT_TRUE(DnsSdInstanceEndpointToReceiverInfo(record).is_error()); txt = CreateValidTxt(); txt.ClearValue(kFriendlyNameKey); record = discovery::DnsSdInstanceEndpoint( instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); - EXPECT_TRUE(DnsSdInstanceEndpointToServiceInfo(record).is_error()); + EXPECT_TRUE(DnsSdInstanceEndpointToReceiverInfo(record).is_error()); txt = CreateValidTxt(); txt.ClearValue(kModelNameKey); @@ -117,11 +117,11 @@ TEST(ServiceInfoTests, ConvertInvalidFromDnsSd) { instance, kCastV2ServiceId, kCastV2DomainId, txt, kNetworkInterface, kEndpointV4, kEndpointV6); // Note: Model name is an optional field. - EXPECT_FALSE(DnsSdInstanceEndpointToServiceInfo(record).is_error()); + EXPECT_FALSE(DnsSdInstanceEndpointToReceiverInfo(record).is_error()); } -TEST(ServiceInfoTests, ConvertValidToDnsSd) { - ServiceInfo info; +TEST(ReceiverInfoTests, ConvertValidToDnsSd) { + ReceiverInfo info; info.v4_address = kAddressV4; info.v6_address = kAddressV6; info.port = kPort; @@ -131,7 +131,7 @@ TEST(ServiceInfoTests, ConvertValidToDnsSd) { info.status = kStatusParsed; info.model_name = kModelName; info.friendly_name = kFriendlyName; - discovery::DnsSdInstance instance = ServiceInfoToDnsSdInstance(info); + discovery::DnsSdInstance instance = ReceiverInfoToDnsSdInstance(info); CompareTxtString(instance.txt(), kUniqueIdKey, kTestUniqueId); CompareTxtString(instance.txt(), kCapabilitiesKey, kCapabilitiesString); CompareTxtString(instance.txt(), kModelNameKey, kModelName); @@ -140,7 +140,7 @@ TEST(ServiceInfoTests, ConvertValidToDnsSd) { CompareTxtInt(instance.txt(), kStatusKey, kStatus); } -TEST(ServiceInfoTests, ParseServiceInfoFromRealTXT) { +TEST(ReceiverInfoTests, ParseReceiverInfoFromRealTXT) { constexpr struct { const char* key; const char* value; @@ -168,9 +168,9 @@ TEST(ServiceInfoTests, ParseServiceInfoFromRealTXT) { "InstanceId", kCastV2ServiceId, kCastV2DomainId, std::move(txt), kNetworkInterface, kEndpointV4, kEndpointV6); - const ErrorOr<ServiceInfo> result = - DnsSdInstanceEndpointToServiceInfo(record); - const ServiceInfo& info = result.value(); + const ErrorOr<ReceiverInfo> result = + DnsSdInstanceEndpointToReceiverInfo(record); + const ReceiverInfo& info = result.value(); EXPECT_EQ(info.unique_id, "4ef522244a5a877f35ddead7d98702e6"); EXPECT_EQ(info.protocol_version, 5); EXPECT_TRUE(info.capabilities & (kHasVideoOutput | kHasAudioOutput)); diff --git a/cast/common/public/testing/discovery_utils.h b/cast/common/public/testing/discovery_utils.h index b0d7d03b..6e805e74 100644 --- a/cast/common/public/testing/discovery_utils.h +++ b/cast/common/public/testing/discovery_utils.h @@ -7,7 +7,7 @@ #include <string> -#include "cast/common/public/service_info.h" +#include "cast/common/public/receiver_info.h" #include "discovery/dnssd/public/dns_sd_txt_record.h" #include "gmock/gmock.h" #include "gtest/gtest.h" |