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/base/name_value_map.h" | 10 #include "remoting/base/name_value_map.h" |
11 #include "remoting/base/remoting_bot.h" | 11 #include "remoting/base/remoting_bot.h" |
12 #include "remoting/protocol/content_description.h" | 12 #include "remoting/protocol/content_description.h" |
13 #include "remoting/protocol/session_plugin.h" | 13 #include "remoting/protocol/session_plugin.h" |
14 #include "remoting/signaling/jid_util.h" | |
15 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h" | 14 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h" |
16 | 15 |
17 using buzz::QName; | 16 using buzz::QName; |
18 using buzz::XmlElement; | 17 using buzz::XmlElement; |
19 | 18 |
20 namespace remoting { | 19 namespace remoting { |
21 namespace protocol { | 20 namespace protocol { |
22 | 21 |
23 namespace { | 22 namespace { |
24 | 23 |
25 const char kJabberNamespace[] = "jabber:client"; | 24 const char kJabberNamespace[] = "jabber:client"; |
26 const char kJingleNamespace[] = "urn:xmpp:jingle:1"; | 25 const char kJingleNamespace[] = "urn:xmpp:jingle:1"; |
27 | 26 |
28 // Namespace for transport messages when using standard ICE. | 27 // Namespace for transport messages when using standard ICE. |
29 const char kIceTransportNamespace[] = "google:remoting:ice"; | 28 const char kIceTransportNamespace[] = "google:remoting:ice"; |
30 | 29 |
31 const char kWebrtcTransportNamespace[] = "google:remoting:webrtc"; | 30 const char kWebrtcTransportNamespace[] = "google:remoting:webrtc"; |
32 | 31 |
33 const char kEmptyNamespace[] = ""; | 32 const char kEmptyNamespace[] = ""; |
34 const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace"; | 33 const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace"; |
35 | 34 |
36 const int kPortMin = 1000; | 35 const int kPortMin = 1000; |
37 const int kPortMax = 65535; | 36 const int kPortMax = 65535; |
38 | 37 |
39 const NameMapElement<SignalingAddress::Channel> kChannelTypes[] = { | |
40 {SignalingAddress::Channel::LCS, "lcs"}, | |
41 {SignalingAddress::Channel::XMPP, "xmpp"}, | |
42 }; | |
43 | |
44 const NameMapElement<JingleMessage::ActionType> kActionTypes[] = { | 38 const NameMapElement<JingleMessage::ActionType> kActionTypes[] = { |
45 { JingleMessage::SESSION_INITIATE, "session-initiate" }, | 39 { JingleMessage::SESSION_INITIATE, "session-initiate" }, |
46 { JingleMessage::SESSION_ACCEPT, "session-accept" }, | 40 { JingleMessage::SESSION_ACCEPT, "session-accept" }, |
47 { JingleMessage::SESSION_TERMINATE, "session-terminate" }, | 41 { JingleMessage::SESSION_TERMINATE, "session-terminate" }, |
48 { JingleMessage::SESSION_INFO, "session-info" }, | 42 { JingleMessage::SESSION_INFO, "session-info" }, |
49 { JingleMessage::TRANSPORT_INFO, "transport-info" }, | 43 { JingleMessage::TRANSPORT_INFO, "transport-info" }, |
50 }; | 44 }; |
51 | 45 |
52 const NameMapElement<JingleMessage::Reason> kReasons[] = { | 46 const NameMapElement<JingleMessage::Reason> kReasons[] = { |
53 { JingleMessage::SUCCESS, "success" }, | 47 { JingleMessage::SUCCESS, "success" }, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); | 138 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); |
145 result->SetAttr(QName(kEmptyNamespace, "protocol"), | 139 result->SetAttr(QName(kEmptyNamespace, "protocol"), |
146 candidate.candidate.protocol()); | 140 candidate.candidate.protocol()); |
147 result->SetAttr(QName(kEmptyNamespace, "priority"), | 141 result->SetAttr(QName(kEmptyNamespace, "priority"), |
148 base::UintToString(candidate.candidate.priority())); | 142 base::UintToString(candidate.candidate.priority())); |
149 result->SetAttr(QName(kEmptyNamespace, "generation"), | 143 result->SetAttr(QName(kEmptyNamespace, "generation"), |
150 base::UintToString(candidate.candidate.generation())); | 144 base::UintToString(candidate.candidate.generation())); |
151 return result; | 145 return result; |
152 } | 146 } |
153 | 147 |
154 // Represents the XML attrbute names for the various address fields in the | |
155 // iq stanza. | |
156 enum class Field { JID, CHANNEL, ENDPOINT_ID }; | |
157 | |
158 buzz::QName GetQNameByField(Field attr, bool from) { | |
159 std::string attribute_name; | |
160 switch (attr) { | |
161 case Field::JID: | |
162 attribute_name = (from) ? "from" : "to"; | |
163 break; | |
164 case Field::ENDPOINT_ID: | |
165 attribute_name = (from) ? "from-endpoint-id" : "to-endpoint-id"; | |
166 break; | |
167 case Field::CHANNEL: | |
168 attribute_name = (from) ? "from-channel" : "to-channel"; | |
169 break; | |
170 default: | |
171 NOTREACHED(); | |
172 } | |
173 return QName(kEmptyNamespace, attribute_name); | |
174 } | |
175 | |
176 SignalingAddress ParseAddress( | |
177 const buzz::XmlElement* iq, bool from, std::string* error) { | |
178 std::string jid(iq->Attr(GetQNameByField(Field::JID, from))); | |
179 if (jid.empty()) { | |
180 return SignalingAddress(); | |
181 } | |
182 | |
183 const XmlElement* jingle = iq->FirstNamed(QName(kJingleNamespace, "jingle")); | |
184 | |
185 if (!jingle) { | |
186 return SignalingAddress(jid); | |
187 } | |
188 | |
189 std::string type(iq->Attr(QName(std::string(), "type"))); | |
190 // For error IQs, flips the |from| flag as the jingle node represents the | |
191 // original request. | |
192 if (type == "error") { | |
193 from = !from; | |
194 } | |
195 | |
196 std::string endpoint_id( | |
197 jingle->Attr(GetQNameByField(Field::ENDPOINT_ID, from))); | |
198 std::string channel_str(jingle->Attr(GetQNameByField(Field::CHANNEL, from))); | |
199 SignalingAddress::Channel channel; | |
200 | |
201 if (channel_str.empty()) { | |
202 channel = SignalingAddress::Channel::XMPP; | |
203 } else if (!NameToValue(kChannelTypes, channel_str, &channel)) { | |
204 *error = "Unknown channel: " + channel_str; | |
205 return SignalingAddress(); | |
206 } | |
207 | |
208 bool is_lcs = (channel == SignalingAddress::Channel::LCS); | |
209 | |
210 if (is_lcs == endpoint_id.empty()) { | |
211 *error = (is_lcs ? "Missing |endpoint-id| for LCS channel" | |
212 : "|endpoint_id| should be empty for XMPP channel"); | |
213 return SignalingAddress(); | |
214 } | |
215 | |
216 if (from && is_lcs && !IsValidBotJid(jid)) { | |
217 *error = "Reject LCS message from untrusted sender: " + jid; | |
218 return SignalingAddress(); | |
219 } | |
220 | |
221 return SignalingAddress(jid, endpoint_id, channel); | |
222 } | |
223 | |
224 void SetAddress(buzz::XmlElement* iq, | |
225 buzz::XmlElement* jingle, | |
226 const SignalingAddress& address, | |
227 bool from) { | |
228 if (address.empty()) { | |
229 return; | |
230 } | |
231 | |
232 // Always set the JID. | |
233 iq->SetAttr(GetQNameByField(Field::JID, from), address.jid()); | |
234 | |
235 // Do not tamper the routing-info in the jingle tag for error IQ's, as | |
236 // it corresponds to the original message. | |
237 std::string type(iq->Attr(QName(std::string(), "type"))); | |
238 if (type == "error") { | |
239 return; | |
240 } | |
241 | |
242 // Start from a fresh slate regardless of the previous address format. | |
243 jingle->ClearAttr(GetQNameByField(Field::CHANNEL, from)); | |
244 jingle->ClearAttr(GetQNameByField(Field::ENDPOINT_ID, from)); | |
245 | |
246 // Only set the channel and endpoint_id in the LCS channel. | |
247 if (address.channel() == SignalingAddress::Channel::LCS) { | |
248 jingle->AddAttr(GetQNameByField(Field::ENDPOINT_ID, from), | |
249 address.endpoint_id()); | |
250 jingle->AddAttr(GetQNameByField(Field::CHANNEL, from), | |
251 ValueToName(kChannelTypes, address.channel())); | |
252 } | |
253 } | |
254 | |
255 } // namespace | 148 } // namespace |
256 | 149 |
257 SignalingAddress::SignalingAddress() | |
258 : channel_(SignalingAddress::Channel::XMPP) {} | |
259 | |
260 SignalingAddress::SignalingAddress(const std::string& jid) | |
261 : jid_(NormalizeJid(jid)), channel_(SignalingAddress::Channel::XMPP) { | |
262 DCHECK(!jid.empty()); | |
263 } | |
264 | |
265 SignalingAddress::SignalingAddress(const std::string& jid, | |
266 const std::string& endpoint_id, | |
267 Channel channel) | |
268 : jid_(NormalizeJid(jid)), | |
269 endpoint_id_(NormalizeJid(endpoint_id)), | |
270 channel_(channel) { | |
271 DCHECK(!jid.empty()); | |
272 } | |
273 | |
274 bool SignalingAddress::operator==(const SignalingAddress& other) const { | |
275 return (other.jid_ == jid_) && (other.endpoint_id_ == endpoint_id_) && | |
276 (other.channel_ == channel_); | |
277 } | |
278 | |
279 bool SignalingAddress::operator!=(const SignalingAddress& other) const { | |
280 return !(*this == other); | |
281 } | |
282 | |
283 // static | 150 // static |
284 bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) { | 151 bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) { |
285 return stanza->Name() == QName(kJabberNamespace, "iq") && | 152 return stanza->Name() == QName(kJabberNamespace, "iq") && |
286 stanza->Attr(QName(std::string(), "type")) == "set" && | 153 stanza->Attr(QName(std::string(), "type")) == "set" && |
287 stanza->FirstNamed(QName(kJingleNamespace, "jingle")) != nullptr; | 154 stanza->FirstNamed(QName(kJingleNamespace, "jingle")) != nullptr; |
288 } | 155 } |
289 | 156 |
290 // static | 157 // static |
291 std::string JingleMessage::GetActionName(ActionType action) { | 158 std::string JingleMessage::GetActionName(ActionType action) { |
292 return ValueToName(kActionTypes, action); | 159 return ValueToName(kActionTypes, action); |
(...skipping 15 matching lines...) Expand all Loading... |
308 return false; | 175 return false; |
309 } | 176 } |
310 | 177 |
311 const XmlElement* jingle_tag = | 178 const XmlElement* jingle_tag = |
312 stanza->FirstNamed(QName(kJingleNamespace, "jingle")); | 179 stanza->FirstNamed(QName(kJingleNamespace, "jingle")); |
313 if (!jingle_tag) { | 180 if (!jingle_tag) { |
314 *error = "Not a jingle message"; | 181 *error = "Not a jingle message"; |
315 return false; | 182 return false; |
316 } | 183 } |
317 | 184 |
318 from = ParseAddress(stanza, true, error); | 185 from = SignalingAddress::Parse(stanza, SignalingAddress::FROM, error); |
319 if (!error->empty()) { | 186 to = SignalingAddress::Parse(stanza, SignalingAddress::TO, error); |
| 187 if (from.empty() || to.empty()) { |
320 return false; | 188 return false; |
321 } | 189 } |
322 | 190 |
323 to = ParseAddress(stanza, false, error); | |
324 if (!error->empty()) { | |
325 return false; | |
326 } | |
327 | |
328 initiator = jingle_tag->Attr(QName(kEmptyNamespace, "initiator")); | 191 initiator = jingle_tag->Attr(QName(kEmptyNamespace, "initiator")); |
329 | 192 |
330 std::string action_str = jingle_tag->Attr(QName(kEmptyNamespace, "action")); | 193 std::string action_str = jingle_tag->Attr(QName(kEmptyNamespace, "action")); |
331 if (action_str.empty()) { | 194 if (action_str.empty()) { |
332 *error = "action attribute is missing"; | 195 *error = "action attribute is missing"; |
333 return false; | 196 return false; |
334 } | 197 } |
335 if (!NameToValue(kActionTypes, action_str, &action)) { | 198 if (!NameToValue(kActionTypes, action_str, &action)) { |
336 *error = "Unknown action " + action_str; | 199 *error = "Unknown action " + action_str; |
337 return false; | 200 return false; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 std::unique_ptr<XmlElement> root( | 306 std::unique_ptr<XmlElement> root( |
444 new XmlElement(QName("jabber:client", "iq"), true)); | 307 new XmlElement(QName("jabber:client", "iq"), true)); |
445 | 308 |
446 DCHECK(!to.empty()); | 309 DCHECK(!to.empty()); |
447 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); | 310 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); |
448 | 311 |
449 XmlElement* jingle_tag = | 312 XmlElement* jingle_tag = |
450 new XmlElement(QName(kJingleNamespace, "jingle"), true); | 313 new XmlElement(QName(kJingleNamespace, "jingle"), true); |
451 root->AddElement(jingle_tag); | 314 root->AddElement(jingle_tag); |
452 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); | 315 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); |
453 SetAddress(root.get(), jingle_tag, to, false); | 316 |
454 SetAddress(root.get(), jingle_tag, from, true); | 317 to.SetInMessage(root.get(), SignalingAddress::TO); |
| 318 if (!from.empty()) |
| 319 from.SetInMessage(root.get(), SignalingAddress::FROM); |
455 | 320 |
456 const char* action_attr = ValueToName(kActionTypes, action); | 321 const char* action_attr = ValueToName(kActionTypes, action); |
457 if (!action_attr) { | 322 if (!action_attr) { |
458 LOG(FATAL) << "Invalid action value " << action; | 323 LOG(FATAL) << "Invalid action value " << action; |
459 } | 324 } |
460 jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr); | 325 jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr); |
461 | 326 |
462 if (attachments) { | 327 if (attachments) { |
463 jingle_tag->AddElement(new XmlElement(*attachments)); | 328 jingle_tag->AddElement(new XmlElement(*attachments)); |
464 } | 329 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml( | 408 std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml( |
544 const buzz::XmlElement* request_stanza) const { | 409 const buzz::XmlElement* request_stanza) const { |
545 std::unique_ptr<XmlElement> iq( | 410 std::unique_ptr<XmlElement> iq( |
546 new XmlElement(QName(kJabberNamespace, "iq"), true)); | 411 new XmlElement(QName(kJabberNamespace, "iq"), true)); |
547 | 412 |
548 iq->SetAttr(QName(kEmptyNamespace, "id"), | 413 iq->SetAttr(QName(kEmptyNamespace, "id"), |
549 request_stanza->Attr(QName(kEmptyNamespace, "id"))); | 414 request_stanza->Attr(QName(kEmptyNamespace, "id"))); |
550 | 415 |
551 SignalingAddress original_from; | 416 SignalingAddress original_from; |
552 std::string error_message; | 417 std::string error_message; |
553 original_from = ParseAddress(request_stanza, true, &error_message); | 418 original_from = SignalingAddress::Parse( |
554 DCHECK(error_message.empty()); | 419 request_stanza, SignalingAddress::FROM, &error_message); |
| 420 DCHECK(!original_from.empty()); |
555 | 421 |
556 if (type == REPLY_RESULT) { | 422 if (type == REPLY_RESULT) { |
557 iq->SetAttr(QName(kEmptyNamespace, "type"), "result"); | 423 iq->SetAttr(QName(kEmptyNamespace, "type"), "result"); |
558 XmlElement* jingle = | 424 XmlElement* jingle = |
559 new XmlElement(QName(kJingleNamespace, "jingle"), true); | 425 new XmlElement(QName(kJingleNamespace, "jingle"), true); |
560 iq->AddElement(jingle); | 426 iq->AddElement(jingle); |
561 SetAddress(iq.get(), jingle, original_from, false); | 427 original_from.SetInMessage(iq.get(), SignalingAddress::TO); |
562 return iq; | 428 return iq; |
563 } | 429 } |
564 | 430 |
565 DCHECK_EQ(type, REPLY_ERROR); | 431 DCHECK_EQ(type, REPLY_ERROR); |
566 | 432 |
567 iq->SetAttr(QName(kEmptyNamespace, "type"), "error"); | 433 iq->SetAttr(QName(kEmptyNamespace, "type"), "error"); |
568 SetAddress(iq.get(), nullptr, original_from, false); | 434 original_from.SetInMessage(iq.get(), SignalingAddress::TO); |
569 | 435 |
570 for (const buzz::XmlElement* child = request_stanza->FirstElement(); | 436 for (const buzz::XmlElement* child = request_stanza->FirstElement(); |
571 child != nullptr; child = child->NextElement()) { | 437 child != nullptr; child = child->NextElement()) { |
572 iq->AddElement(new buzz::XmlElement(*child)); | 438 iq->AddElement(new buzz::XmlElement(*child)); |
573 } | 439 } |
574 | 440 |
575 buzz::XmlElement* error = | 441 buzz::XmlElement* error = |
576 new buzz::XmlElement(QName(kJabberNamespace, "error")); | 442 new buzz::XmlElement(QName(kJabberNamespace, "error")); |
577 iq->AddElement(error); | 443 iq->AddElement(error); |
578 | 444 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 result->AddElement(FormatIceCredentials(credentials)); | 551 result->AddElement(FormatIceCredentials(credentials)); |
686 } | 552 } |
687 for (const NamedCandidate& candidate : candidates) { | 553 for (const NamedCandidate& candidate : candidates) { |
688 result->AddElement(FormatIceCandidate(candidate)); | 554 result->AddElement(FormatIceCandidate(candidate)); |
689 } | 555 } |
690 return result; | 556 return result; |
691 } | 557 } |
692 | 558 |
693 } // namespace protocol | 559 } // namespace protocol |
694 } // namespace remoting | 560 } // namespace remoting |
OLD | NEW |