OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/jingle_messages.h" | 5 #include "remoting/protocol/jingle_messages.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "remoting/base/constants.h" | 9 #include "remoting/base/constants.h" |
10 #include "remoting/protocol/content_description.h" | 10 #include "remoting/protocol/content_description.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 const char kIceTransportNamespace[] = "google:remoting:ice"; | 26 const char kIceTransportNamespace[] = "google:remoting:ice"; |
27 | 27 |
28 const char kWebrtcTransportNamespace[] = "google:remoting:webrtc"; | 28 const char kWebrtcTransportNamespace[] = "google:remoting:webrtc"; |
29 | 29 |
30 const char kEmptyNamespace[] = ""; | 30 const char kEmptyNamespace[] = ""; |
31 const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace"; | 31 const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace"; |
32 | 32 |
33 const int kPortMin = 1000; | 33 const int kPortMin = 1000; |
34 const int kPortMax = 65535; | 34 const int kPortMax = 65535; |
35 | 35 |
| 36 const NameMapElement<SignalingAddress::Channel> kChannelTypes[] = { |
| 37 {SignalingAddress::Channel::LCS, "lcs"}, |
| 38 {SignalingAddress::Channel::XMPP, "xmpp"}, |
| 39 }; |
| 40 |
36 const NameMapElement<JingleMessage::ActionType> kActionTypes[] = { | 41 const NameMapElement<JingleMessage::ActionType> kActionTypes[] = { |
37 { JingleMessage::SESSION_INITIATE, "session-initiate" }, | 42 { JingleMessage::SESSION_INITIATE, "session-initiate" }, |
38 { JingleMessage::SESSION_ACCEPT, "session-accept" }, | 43 { JingleMessage::SESSION_ACCEPT, "session-accept" }, |
39 { JingleMessage::SESSION_TERMINATE, "session-terminate" }, | 44 { JingleMessage::SESSION_TERMINATE, "session-terminate" }, |
40 { JingleMessage::SESSION_INFO, "session-info" }, | 45 { JingleMessage::SESSION_INFO, "session-info" }, |
41 { JingleMessage::TRANSPORT_INFO, "transport-info" }, | 46 { JingleMessage::TRANSPORT_INFO, "transport-info" }, |
42 }; | 47 }; |
43 | 48 |
44 const NameMapElement<JingleMessage::Reason> kReasons[] = { | 49 const NameMapElement<JingleMessage::Reason> kReasons[] = { |
45 { JingleMessage::SUCCESS, "success" }, | 50 { JingleMessage::SUCCESS, "success" }, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); | 141 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); |
137 result->SetAttr(QName(kEmptyNamespace, "protocol"), | 142 result->SetAttr(QName(kEmptyNamespace, "protocol"), |
138 candidate.candidate.protocol()); | 143 candidate.candidate.protocol()); |
139 result->SetAttr(QName(kEmptyNamespace, "priority"), | 144 result->SetAttr(QName(kEmptyNamespace, "priority"), |
140 base::UintToString(candidate.candidate.priority())); | 145 base::UintToString(candidate.candidate.priority())); |
141 result->SetAttr(QName(kEmptyNamespace, "generation"), | 146 result->SetAttr(QName(kEmptyNamespace, "generation"), |
142 base::UintToString(candidate.candidate.generation())); | 147 base::UintToString(candidate.candidate.generation())); |
143 return result; | 148 return result; |
144 } | 149 } |
145 | 150 |
| 151 // Represents the XML attrbute names for the various address fields in the |
| 152 // iq stanza. |
| 153 enum class Field { JID, CHANNEL, ENDPOINT_ID }; |
| 154 |
| 155 buzz::QName GetQNameByField(Field attr, bool from) { |
| 156 std::string attribute_name; |
| 157 switch (attr) { |
| 158 case Field::JID: |
| 159 attribute_name = (from) ? "from" : "to"; |
| 160 break; |
| 161 case Field::ENDPOINT_ID: |
| 162 attribute_name = (from) ? "from-endpoint-id" : "to-endpoint-id"; |
| 163 break; |
| 164 case Field::CHANNEL: |
| 165 attribute_name = (from) ? "from-channel" : "to-channel"; |
| 166 break; |
| 167 default: |
| 168 NOTREACHED(); |
| 169 } |
| 170 return QName(kEmptyNamespace, attribute_name); |
| 171 } |
| 172 |
| 173 SignalingAddress ParseAddress( |
| 174 const buzz::XmlElement* stanza, bool from, std::string* error) { |
| 175 SignalingAddress empty_instance; |
| 176 |
| 177 std::string jid(stanza->Attr(GetQNameByField(Field::JID, from))); |
| 178 std::string endpoint_id( |
| 179 stanza->Attr(GetQNameByField(Field::ENDPOINT_ID, from))); |
| 180 std::string channel_str(stanza->Attr(GetQNameByField(Field::CHANNEL, from))); |
| 181 SignalingAddress::Channel channel; |
| 182 |
| 183 if (channel_str.empty()) { |
| 184 channel = SignalingAddress::Channel::XMPP; |
| 185 } else if (!NameToValue(kChannelTypes, channel_str, &channel)) { |
| 186 *error = "Unknown channel: " + channel_str; |
| 187 return empty_instance; |
| 188 } |
| 189 |
| 190 bool isLcs = (channel == SignalingAddress::Channel::LCS); |
| 191 |
| 192 if (isLcs == endpoint_id.empty()) { |
| 193 *error = (isLcs ? "Missing |endpoint-id| for LCS channel" |
| 194 : "|endpoint_id| should be empty for XMPP channel"); |
| 195 return empty_instance; |
| 196 } |
| 197 |
| 198 return SignalingAddress(jid, endpoint_id, channel); |
| 199 } |
| 200 |
| 201 void SetAddress(buzz::XmlElement* iqElement, |
| 202 const SignalingAddress& address, |
| 203 bool from) { |
| 204 if (address.empty()) { |
| 205 return; |
| 206 } |
| 207 |
| 208 iqElement->AddAttr(GetQNameByField(Field::JID, from), address.jid); |
| 209 |
| 210 if (address.channel == SignalingAddress::Channel::LCS) { |
| 211 iqElement->AddAttr(GetQNameByField(Field::ENDPOINT_ID, from), |
| 212 address.endpoint_id); |
| 213 const char* channel_str = ValueToName(kChannelTypes, address.channel); |
| 214 iqElement->AddAttr(GetQNameByField(Field::CHANNEL, from), channel_str); |
| 215 } |
| 216 } |
| 217 |
146 } // namespace | 218 } // namespace |
147 | 219 |
148 IceTransportInfo::NamedCandidate::NamedCandidate( | 220 IceTransportInfo::NamedCandidate::NamedCandidate( |
149 const std::string& name, | 221 const std::string& name, |
150 const cricket::Candidate& candidate) | 222 const cricket::Candidate& candidate) |
151 : name(name), | 223 : name(name), |
152 candidate(candidate) { | 224 candidate(candidate) { |
153 } | 225 } |
154 | 226 |
155 IceTransportInfo::IceCredentials::IceCredentials(std::string channel, | 227 IceTransportInfo::IceCredentials::IceCredentials(std::string channel, |
156 std::string ufrag, | 228 std::string ufrag, |
157 std::string password) | 229 std::string password) |
158 : channel(channel), ufrag(ufrag), password(password) { | 230 : channel(channel), ufrag(ufrag), password(password) { |
159 } | 231 } |
160 | 232 |
| 233 SignalingAddress::SignalingAddress() |
| 234 : channel(SignalingAddress::Channel::XMPP) {} |
| 235 |
| 236 SignalingAddress::SignalingAddress(const std::string& jid) |
| 237 : jid(jid), channel(SignalingAddress::Channel::XMPP) {} |
| 238 |
| 239 SignalingAddress::SignalingAddress(const std::string& jid, |
| 240 const std::string& endpoint_id, |
| 241 Channel channel) |
| 242 : jid(jid), endpoint_id(endpoint_id), channel(channel) {} |
| 243 |
| 244 bool SignalingAddress::operator==(const SignalingAddress& other) { |
| 245 return (other.endpoint_id == endpoint_id) && (other.jid == jid) && |
| 246 (other.channel == channel); |
| 247 } |
| 248 |
| 249 bool SignalingAddress::operator!=(const SignalingAddress& other) { |
| 250 return !(*this == other); |
| 251 } |
| 252 |
161 // static | 253 // static |
162 bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) { | 254 bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) { |
163 return stanza->Name() == QName(kJabberNamespace, "iq") && | 255 return stanza->Name() == QName(kJabberNamespace, "iq") && |
164 stanza->Attr(QName(std::string(), "type")) == "set" && | 256 stanza->Attr(QName(std::string(), "type")) == "set" && |
165 stanza->FirstNamed(QName(kJingleNamespace, "jingle")) != nullptr; | 257 stanza->FirstNamed(QName(kJingleNamespace, "jingle")) != nullptr; |
166 } | 258 } |
167 | 259 |
168 // static | 260 // static |
169 std::string JingleMessage::GetActionName(ActionType action) { | 261 std::string JingleMessage::GetActionName(ActionType action) { |
170 return ValueToName(kActionTypes, action); | 262 return ValueToName(kActionTypes, action); |
171 } | 263 } |
172 | 264 |
173 JingleMessage::JingleMessage() {} | 265 JingleMessage::JingleMessage() {} |
174 | 266 |
175 JingleMessage::JingleMessage(const std::string& to, | 267 JingleMessage::JingleMessage(const SignalingAddress& to, |
176 ActionType action, | 268 ActionType action, |
177 const std::string& sid) | 269 const std::string& sid) |
178 : to(to), action(action), sid(sid) {} | 270 : to(to), action(action), sid(sid) {} |
179 | 271 |
180 JingleMessage::~JingleMessage() {} | 272 JingleMessage::~JingleMessage() {} |
181 | 273 |
182 bool JingleMessage::ParseXml(const buzz::XmlElement* stanza, | 274 bool JingleMessage::ParseXml(const buzz::XmlElement* stanza, |
183 std::string* error) { | 275 std::string* error) { |
184 if (!IsJingleMessage(stanza)) { | 276 if (!IsJingleMessage(stanza)) { |
185 *error = "Not a jingle message"; | 277 *error = "Not a jingle message"; |
186 return false; | 278 return false; |
187 } | 279 } |
188 | 280 |
189 const XmlElement* jingle_tag = | 281 const XmlElement* jingle_tag = |
190 stanza->FirstNamed(QName(kJingleNamespace, "jingle")); | 282 stanza->FirstNamed(QName(kJingleNamespace, "jingle")); |
191 if (!jingle_tag) { | 283 if (!jingle_tag) { |
192 *error = "Not a jingle message"; | 284 *error = "Not a jingle message"; |
193 return false; | 285 return false; |
194 } | 286 } |
195 | 287 |
196 from = stanza->Attr(QName(kEmptyNamespace, "from")); | 288 from = ParseAddress(stanza, true, error); |
197 to = stanza->Attr(QName(kEmptyNamespace, "to")); | 289 if (!error->empty()) { |
| 290 return false; |
| 291 } |
| 292 |
| 293 to = ParseAddress(stanza, false, error); |
| 294 if (!error->empty()) { |
| 295 return false; |
| 296 } |
| 297 |
198 initiator = jingle_tag->Attr(QName(kEmptyNamespace, "initiator")); | 298 initiator = jingle_tag->Attr(QName(kEmptyNamespace, "initiator")); |
199 | 299 |
200 std::string action_str = jingle_tag->Attr(QName(kEmptyNamespace, "action")); | 300 std::string action_str = jingle_tag->Attr(QName(kEmptyNamespace, "action")); |
201 if (action_str.empty()) { | 301 if (action_str.empty()) { |
202 *error = "action attribute is missing"; | 302 *error = "action attribute is missing"; |
203 return false; | 303 return false; |
204 } | 304 } |
205 if (!NameToValue(kActionTypes, action_str, &action)) { | 305 if (!NameToValue(kActionTypes, action_str, &action)) { |
206 *error = "Unknown action " + action_str; | 306 *error = "Unknown action " + action_str; |
207 return false; | 307 return false; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 } | 383 } |
284 | 384 |
285 return true; | 385 return true; |
286 } | 386 } |
287 | 387 |
288 std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const { | 388 std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const { |
289 std::unique_ptr<XmlElement> root( | 389 std::unique_ptr<XmlElement> root( |
290 new XmlElement(QName("jabber:client", "iq"), true)); | 390 new XmlElement(QName("jabber:client", "iq"), true)); |
291 | 391 |
292 DCHECK(!to.empty()); | 392 DCHECK(!to.empty()); |
293 root->AddAttr(QName(kEmptyNamespace, "to"), to); | 393 SetAddress(root.get(), to, false); |
294 if (!from.empty()) | 394 SetAddress(root.get(), from, true); |
295 root->AddAttr(QName(kEmptyNamespace, "from"), from); | |
296 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); | 395 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); |
297 | 396 |
298 XmlElement* jingle_tag = | 397 XmlElement* jingle_tag = |
299 new XmlElement(QName(kJingleNamespace, "jingle"), true); | 398 new XmlElement(QName(kJingleNamespace, "jingle"), true); |
300 root->AddElement(jingle_tag); | 399 root->AddElement(jingle_tag); |
301 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); | 400 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); |
302 | 401 |
303 const char* action_attr = ValueToName(kActionTypes, action); | 402 const char* action_attr = ValueToName(kActionTypes, action); |
304 if (!action_attr) | 403 if (!action_attr) |
305 LOG(FATAL) << "Invalid action value " << action; | 404 LOG(FATAL) << "Invalid action value " << action; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 error_type(error), | 463 error_type(error), |
365 text(text_value) { | 464 text(text_value) { |
366 } | 465 } |
367 | 466 |
368 JingleMessageReply::~JingleMessageReply() { } | 467 JingleMessageReply::~JingleMessageReply() { } |
369 | 468 |
370 std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml( | 469 std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml( |
371 const buzz::XmlElement* request_stanza) const { | 470 const buzz::XmlElement* request_stanza) const { |
372 std::unique_ptr<XmlElement> iq( | 471 std::unique_ptr<XmlElement> iq( |
373 new XmlElement(QName(kJabberNamespace, "iq"), true)); | 472 new XmlElement(QName(kJabberNamespace, "iq"), true)); |
374 iq->SetAttr(QName(kEmptyNamespace, "to"), | 473 |
375 request_stanza->Attr(QName(kEmptyNamespace, "from"))); | 474 SignalingAddress original_from; |
| 475 std::string error_message; |
| 476 original_from = ParseAddress(request_stanza, true, &error_message); |
| 477 DCHECK(error_message.empty()); |
| 478 SetAddress(iq.get(), original_from, false); |
| 479 |
376 iq->SetAttr(QName(kEmptyNamespace, "id"), | 480 iq->SetAttr(QName(kEmptyNamespace, "id"), |
377 request_stanza->Attr(QName(kEmptyNamespace, "id"))); | 481 request_stanza->Attr(QName(kEmptyNamespace, "id"))); |
378 | 482 |
379 if (type == REPLY_RESULT) { | 483 if (type == REPLY_RESULT) { |
380 iq->SetAttr(QName(kEmptyNamespace, "type"), "result"); | 484 iq->SetAttr(QName(kEmptyNamespace, "type"), "result"); |
381 return iq; | 485 return iq; |
382 } | 486 } |
383 | 487 |
384 DCHECK_EQ(type, REPLY_ERROR); | 488 DCHECK_EQ(type, REPLY_ERROR); |
385 | 489 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 result->AddElement(FormatIceCredentials(credentials)); | 593 result->AddElement(FormatIceCredentials(credentials)); |
490 } | 594 } |
491 for (const NamedCandidate& candidate : candidates) { | 595 for (const NamedCandidate& candidate : candidates) { |
492 result->AddElement(FormatIceCandidate(candidate)); | 596 result->AddElement(FormatIceCandidate(candidate)); |
493 } | 597 } |
494 return result; | 598 return result; |
495 } | 599 } |
496 | 600 |
497 } // namespace protocol | 601 } // namespace protocol |
498 } // namespace remoting | 602 } // namespace remoting |
OLD | NEW |