xref: /aosp_15_r20/external/webrtc/p2p/base/transport_description.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2013 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "p2p/base/transport_description.h"
12 
13 #include "absl/strings/ascii.h"
14 #include "absl/strings/match.h"
15 #include "absl/strings/string_view.h"
16 #include "p2p/base/p2p_constants.h"
17 #include "rtc_base/arraysize.h"
18 #include "rtc_base/logging.h"
19 #include "rtc_base/strings/string_builder.h"
20 
21 using webrtc::RTCError;
22 using webrtc::RTCErrorOr;
23 using webrtc::RTCErrorType;
24 
25 namespace cricket {
26 namespace {
27 
IsIceChar(char c)28 bool IsIceChar(char c) {
29   // Note: '-', '=', '#' and '_' are *not* valid ice-chars but temporarily
30   // permitted in order to allow external software to upgrade.
31   if (c == '-' || c == '=' || c == '#' || c == '_') {
32     RTC_LOG(LS_WARNING)
33         << "'-', '=', '#' and '-' are not valid ice-char and thus not "
34         << "permitted in ufrag or pwd. This is a protocol violation that "
35         << "is permitted to allow upgrading but will be rejected in "
36         << "the future. See https://crbug.com/1053756";
37     return true;
38   }
39   return absl::ascii_isalnum(c) || c == '+' || c == '/';
40 }
41 
ValidateIceUfrag(absl::string_view raw_ufrag)42 RTCError ValidateIceUfrag(absl::string_view raw_ufrag) {
43   if (!(ICE_UFRAG_MIN_LENGTH <= raw_ufrag.size() &&
44         raw_ufrag.size() <= ICE_UFRAG_MAX_LENGTH)) {
45     rtc::StringBuilder sb;
46     sb << "ICE ufrag must be between " << ICE_UFRAG_MIN_LENGTH << " and "
47        << ICE_UFRAG_MAX_LENGTH << " characters long.";
48     return RTCError(RTCErrorType::SYNTAX_ERROR, sb.Release());
49   }
50 
51   if (!absl::c_all_of(raw_ufrag, IsIceChar)) {
52     return RTCError(
53         RTCErrorType::SYNTAX_ERROR,
54         "ICE ufrag must contain only alphanumeric characters, '+', and '/'.");
55   }
56 
57   return RTCError::OK();
58 }
59 
ValidateIcePwd(absl::string_view raw_pwd)60 RTCError ValidateIcePwd(absl::string_view raw_pwd) {
61   if (!(ICE_PWD_MIN_LENGTH <= raw_pwd.size() &&
62         raw_pwd.size() <= ICE_PWD_MAX_LENGTH)) {
63     rtc::StringBuilder sb;
64     sb << "ICE pwd must be between " << ICE_PWD_MIN_LENGTH << " and "
65        << ICE_PWD_MAX_LENGTH << " characters long.";
66     return RTCError(RTCErrorType::SYNTAX_ERROR, sb.Release());
67   }
68 
69   if (!absl::c_all_of(raw_pwd, IsIceChar)) {
70     return RTCError(
71         RTCErrorType::SYNTAX_ERROR,
72         "ICE pwd must contain only alphanumeric characters, '+', and '/'.");
73   }
74 
75   return RTCError::OK();
76 }
77 
78 }  // namespace
79 
Parse(absl::string_view raw_ufrag,absl::string_view raw_pwd)80 RTCErrorOr<IceParameters> IceParameters::Parse(absl::string_view raw_ufrag,
81                                                absl::string_view raw_pwd) {
82   IceParameters parameters(std::string(raw_ufrag), std::string(raw_pwd),
83                            /* renomination= */ false);
84   auto result = parameters.Validate();
85   if (!result.ok()) {
86     return result;
87   }
88   return parameters;
89 }
90 
Validate() const91 RTCError IceParameters::Validate() const {
92   // For legacy protocols.
93   // TODO(zhihuang): Remove this once the legacy protocol is no longer
94   // supported.
95   if (ufrag.empty() && pwd.empty()) {
96     return RTCError::OK();
97   }
98 
99   auto ufrag_result = ValidateIceUfrag(ufrag);
100   if (!ufrag_result.ok()) {
101     return ufrag_result;
102   }
103 
104   auto pwd_result = ValidateIcePwd(pwd);
105   if (!pwd_result.ok()) {
106     return pwd_result;
107   }
108 
109   return RTCError::OK();
110 }
111 
StringToConnectionRole(absl::string_view role_str)112 absl::optional<ConnectionRole> StringToConnectionRole(
113     absl::string_view role_str) {
114   const char* const roles[] = {
115       CONNECTIONROLE_ACTIVE_STR, CONNECTIONROLE_PASSIVE_STR,
116       CONNECTIONROLE_ACTPASS_STR, CONNECTIONROLE_HOLDCONN_STR};
117 
118   for (size_t i = 0; i < arraysize(roles); ++i) {
119     if (absl::EqualsIgnoreCase(roles[i], role_str)) {
120       return static_cast<ConnectionRole>(CONNECTIONROLE_ACTIVE + i);
121     }
122   }
123   return absl::nullopt;
124 }
125 
ConnectionRoleToString(const ConnectionRole & role,std::string * role_str)126 bool ConnectionRoleToString(const ConnectionRole& role, std::string* role_str) {
127   switch (role) {
128     case cricket::CONNECTIONROLE_ACTIVE:
129       *role_str = cricket::CONNECTIONROLE_ACTIVE_STR;
130       break;
131     case cricket::CONNECTIONROLE_ACTPASS:
132       *role_str = cricket::CONNECTIONROLE_ACTPASS_STR;
133       break;
134     case cricket::CONNECTIONROLE_PASSIVE:
135       *role_str = cricket::CONNECTIONROLE_PASSIVE_STR;
136       break;
137     case cricket::CONNECTIONROLE_HOLDCONN:
138       *role_str = cricket::CONNECTIONROLE_HOLDCONN_STR;
139       break;
140     default:
141       return false;
142   }
143   return true;
144 }
145 
TransportDescription()146 TransportDescription::TransportDescription()
147     : ice_mode(ICEMODE_FULL), connection_role(CONNECTIONROLE_NONE) {}
148 
TransportDescription(const std::vector<std::string> & transport_options,absl::string_view ice_ufrag,absl::string_view ice_pwd,IceMode ice_mode,ConnectionRole role,const rtc::SSLFingerprint * identity_fingerprint)149 TransportDescription::TransportDescription(
150     const std::vector<std::string>& transport_options,
151     absl::string_view ice_ufrag,
152     absl::string_view ice_pwd,
153     IceMode ice_mode,
154     ConnectionRole role,
155     const rtc::SSLFingerprint* identity_fingerprint)
156     : transport_options(transport_options),
157       ice_ufrag(ice_ufrag),
158       ice_pwd(ice_pwd),
159       ice_mode(ice_mode),
160       connection_role(role),
161       identity_fingerprint(CopyFingerprint(identity_fingerprint)) {}
162 
TransportDescription(absl::string_view ice_ufrag,absl::string_view ice_pwd)163 TransportDescription::TransportDescription(absl::string_view ice_ufrag,
164                                            absl::string_view ice_pwd)
165     : ice_ufrag(ice_ufrag),
166       ice_pwd(ice_pwd),
167       ice_mode(ICEMODE_FULL),
168       connection_role(CONNECTIONROLE_NONE) {}
169 
TransportDescription(const TransportDescription & from)170 TransportDescription::TransportDescription(const TransportDescription& from)
171     : transport_options(from.transport_options),
172       ice_ufrag(from.ice_ufrag),
173       ice_pwd(from.ice_pwd),
174       ice_mode(from.ice_mode),
175       connection_role(from.connection_role),
176       identity_fingerprint(CopyFingerprint(from.identity_fingerprint.get())) {}
177 
178 TransportDescription::~TransportDescription() = default;
179 
operator =(const TransportDescription & from)180 TransportDescription& TransportDescription::operator=(
181     const TransportDescription& from) {
182   // Self-assignment
183   if (this == &from)
184     return *this;
185 
186   transport_options = from.transport_options;
187   ice_ufrag = from.ice_ufrag;
188   ice_pwd = from.ice_pwd;
189   ice_mode = from.ice_mode;
190   connection_role = from.connection_role;
191 
192   identity_fingerprint.reset(CopyFingerprint(from.identity_fingerprint.get()));
193   return *this;
194 }
195 
196 }  // namespace cricket
197