| // Copyright (c) 2023 The Chromium 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 "quiche/quic/moqt/moqt_messages.h" |
| |
| #include <array> |
| #include <cstdint> |
| #include <string> |
| |
| #include "absl/algorithm/container.h" |
| #include "absl/strings/str_cat.h" |
| #include "quiche/quic/core/quic_time.h" |
| #include "quiche/quic/core/quic_types.h" |
| #include "quiche/quic/moqt/moqt_error.h" |
| #include "quiche/quic/moqt/moqt_key_value_pair.h" |
| #include "quiche/quic/platform/api/quic_bug_tracker.h" |
| |
| namespace moqt { |
| |
| void MoqtSessionParameters::ToSetupParameters(SetupParameters& out) const { |
| if (perspective == quic::Perspective::IS_CLIENT && !using_webtrans) { |
| out.path = path; |
| out.authority = authority; |
| } |
| if (max_request_id != kDefaultMaxRequestId) { |
| out.max_request_id = max_request_id; |
| } |
| if (max_auth_token_cache_size != kDefaultMaxAuthTokenCacheSize) { |
| out.max_auth_token_cache_size = max_auth_token_cache_size; |
| } |
| if (support_object_acks != kDefaultSupportObjectAcks) { |
| out.support_object_acks = support_object_acks; |
| } |
| if (!moqt_implementation.empty()) { |
| out.moqt_implementation = moqt_implementation; |
| } |
| for (const AuthToken& token : authorization_token) { |
| out.authorization_tokens.push_back(token); |
| } |
| } |
| |
| MoqtObjectStatus IntegerToObjectStatus(uint64_t integer) { |
| if (integer >= |
| static_cast<uint64_t>(MoqtObjectStatus::kInvalidObjectStatus)) { |
| return MoqtObjectStatus::kInvalidObjectStatus; |
| } |
| return static_cast<MoqtObjectStatus>(integer); |
| } |
| |
| MoqtError SetupParametersAllowedByMessage(const SetupParameters& parameters, |
| MoqtMessageType message_type, |
| bool webtrans) { |
| bool should_have_path_and_authority = |
| !webtrans && message_type == MoqtMessageType::kClientSetup; |
| if (should_have_path_and_authority != parameters.path.has_value()) { |
| return MoqtError::kInvalidPath; |
| } |
| if (should_have_path_and_authority != parameters.authority.has_value()) { |
| return MoqtError::kInvalidAuthority; |
| } |
| return MoqtError::kNoError; |
| } |
| |
| // Parameter types are not enforced by message in draft-16, but apparently this |
| // is coming back later. |
| #if 0 |
| const std::array<MoqtMessageType, 9> kAllowsAuthorization = { |
| MoqtMessageType::kClientSetup, |
| MoqtMessageType::kServerSetup, |
| MoqtMessageType::kPublish, |
| MoqtMessageType::kSubscribe, |
| MoqtMessageType::kRequestUpdate, |
| MoqtMessageType::kSubscribeNamespace, |
| MoqtMessageType::kPublishNamespace, |
| MoqtMessageType::kTrackStatus, |
| MoqtMessageType::kFetch}; |
| const std::array<MoqtMessageType, 7> kAllowsDeliveryTimeout = { |
| MoqtMessageType::kTrackStatus, MoqtMessageType::kRequestOk, |
| MoqtMessageType::kPublish, MoqtMessageType::kPublishOk, |
| MoqtMessageType::kSubscribe, MoqtMessageType::kSubscribeOk, |
| MoqtMessageType::kRequestUpdate}; |
| bool MessageParametersAllowedByMessage( |
| const MessageParameters& parameters, MoqtMessageType message_type) { |
| if (!parameters.authorization_tokens.empty() && |
| !absl::c_linear_search(kAllowsAuthorization, message_type)) { |
| return false; |
| } |
| if (parameters.delivery_timeout != quic::QuicTimeDelta::Infinite() && |
| !absl::c_linear_search(kAllowsDeliveryTimeout, message_type)) { |
| return false; |
| } |
| return true; |
| } |
| #endif |
| |
| std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { |
| switch (message_type) { |
| case MoqtMessageType::kClientSetup: |
| return "CLIENT_SETUP"; |
| case MoqtMessageType::kServerSetup: |
| return "SERVER_SETUP"; |
| case MoqtMessageType::kSubscribe: |
| return "SUBSCRIBE"; |
| case MoqtMessageType::kSubscribeOk: |
| return "SUBSCRIBE_OK"; |
| case MoqtMessageType::kRequestError: |
| return "REQUEST_ERROR"; |
| case MoqtMessageType::kUnsubscribe: |
| return "UNSUBSCRIBE"; |
| case MoqtMessageType::kPublishDone: |
| return "PUBLISH_DONE"; |
| case MoqtMessageType::kRequestUpdate: |
| return "REQUEST_UPDATE"; |
| case MoqtMessageType::kPublishNamespaceCancel: |
| return "PUBLISH_NAMESPACE_CANCEL"; |
| case MoqtMessageType::kTrackStatus: |
| return "TRACK_STATUS"; |
| case MoqtMessageType::kPublishNamespace: |
| return "PUBLISH_NAMESPACE"; |
| case MoqtMessageType::kNamespace: |
| return "NAMESPACE"; |
| case MoqtMessageType::kNamespaceDone: |
| return "NAMESPACE_DONE"; |
| case MoqtMessageType::kRequestOk: |
| return "REQUEST_OK"; |
| case MoqtMessageType::kPublishNamespaceDone: |
| return "PUBLISH_NAMESPACE_DONE"; |
| case MoqtMessageType::kGoAway: |
| return "GOAWAY"; |
| case MoqtMessageType::kSubscribeNamespace: |
| return "SUBSCRIBE_NAMESPACE"; |
| case MoqtMessageType::kMaxRequestId: |
| return "MAX_REQUEST_ID"; |
| case MoqtMessageType::kPublish: |
| return "PUBLISH"; |
| case MoqtMessageType::kPublishOk: |
| return "PUBLISH_OK"; |
| case MoqtMessageType::kFetch: |
| return "FETCH"; |
| case MoqtMessageType::kFetchCancel: |
| return "FETCH_CANCEL"; |
| case MoqtMessageType::kFetchOk: |
| return "FETCH_OK"; |
| case MoqtMessageType::kRequestsBlocked: |
| return "REQUESTS_BLOCKED"; |
| case MoqtMessageType::kObjectAck: |
| return "OBJECT_ACK"; |
| } |
| return "Unknown message " + std::to_string(static_cast<int>(message_type)); |
| } |
| |
| std::string MoqtDataStreamTypeToString(MoqtDataStreamType type) { |
| if (type.IsPadding()) { |
| return "PADDING"; |
| } else if (type.IsFetch()) { |
| return "STREAM_HEADER_FETCH"; |
| } |
| return absl::StrCat("STREAM_HEADER_SUBGROUP_", type.value()); |
| } |
| |
| std::string MoqtDatagramTypeToString(MoqtDatagramType type) { |
| return absl::StrCat("DATAGRAM", type.has_status() ? "_STATUS" : "", |
| type.has_extension() ? "_EXTENSION" : ""); |
| } |
| |
| std::string MoqtForwardingPreferenceToString( |
| MoqtForwardingPreference preference) { |
| switch (preference) { |
| case MoqtForwardingPreference::kDatagram: |
| return "DATAGRAM"; |
| case MoqtForwardingPreference::kSubgroup: |
| return "SUBGROUP"; |
| } |
| QUIC_BUG(quic_bug_bad_moqt_message_type_01) |
| << "Unknown preference " << std::to_string(static_cast<int>(preference)); |
| return "Unknown preference " + std::to_string(static_cast<int>(preference)); |
| } |
| |
| } // namespace moqt |