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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); | 142 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); |
143 result->SetAttr(QName(kEmptyNamespace, "protocol"), | 143 result->SetAttr(QName(kEmptyNamespace, "protocol"), |
144 candidate.candidate.protocol()); | 144 candidate.candidate.protocol()); |
145 result->SetAttr(QName(kEmptyNamespace, "priority"), | 145 result->SetAttr(QName(kEmptyNamespace, "priority"), |
146 base::UintToString(candidate.candidate.priority())); | 146 base::UintToString(candidate.candidate.priority())); |
147 result->SetAttr(QName(kEmptyNamespace, "generation"), | 147 result->SetAttr(QName(kEmptyNamespace, "generation"), |
148 base::UintToString(candidate.candidate.generation())); | 148 base::UintToString(candidate.candidate.generation())); |
149 return result; | 149 return result; |
150 } | 150 } |
151 | 151 |
152 XmlElement* EnsureJingleTag(XmlElement* iq) { | |
153 XmlElement* jingle = iq->FirstNamed(QName(kJingleNamespace, "jingle")); | |
154 if (!jingle) { | |
155 jingle = new XmlElement(QName(kJingleNamespace, "jingle"), true); | |
156 iq->AddElement(jingle); | |
157 } | |
158 return jingle; | |
159 } | |
160 | |
152 // Represents the XML attrbute names for the various address fields in the | 161 // Represents the XML attrbute names for the various address fields in the |
153 // iq stanza. | 162 // iq stanza. |
154 enum class Field { JID, CHANNEL, ENDPOINT_ID }; | 163 enum class Field { JID, CHANNEL, ENDPOINT_ID }; |
155 | 164 |
156 buzz::QName GetQNameByField(Field attr, bool from) { | 165 buzz::QName GetQNameByField(Field attr, bool from) { |
157 std::string attribute_name; | 166 std::string attribute_name; |
158 switch (attr) { | 167 switch (attr) { |
159 case Field::JID: | 168 case Field::JID: |
160 attribute_name = (from) ? "from" : "to"; | 169 attribute_name = (from) ? "from" : "to"; |
161 break; | 170 break; |
162 case Field::ENDPOINT_ID: | 171 case Field::ENDPOINT_ID: |
163 attribute_name = (from) ? "from-endpoint-id" : "to-endpoint-id"; | 172 attribute_name = (from) ? "from-endpoint-id" : "to-endpoint-id"; |
164 break; | 173 break; |
165 case Field::CHANNEL: | 174 case Field::CHANNEL: |
166 attribute_name = (from) ? "from-channel" : "to-channel"; | 175 attribute_name = (from) ? "from-channel" : "to-channel"; |
167 break; | 176 break; |
168 default: | 177 default: |
169 NOTREACHED(); | 178 NOTREACHED(); |
170 } | 179 } |
171 return QName(kEmptyNamespace, attribute_name); | 180 return QName(kEmptyNamespace, attribute_name); |
172 } | 181 } |
173 | 182 |
174 SignalingAddress ParseAddress( | 183 SignalingAddress ParseAddress( |
175 const buzz::XmlElement* stanza, bool from, std::string* error) { | 184 const buzz::XmlElement* iq, bool from, std::string* error) { |
176 SignalingAddress empty_instance; | 185 SignalingAddress empty_instance; |
177 | 186 |
178 std::string jid(stanza->Attr(GetQNameByField(Field::JID, from))); | 187 std::string jid(iq->Attr(GetQNameByField(Field::JID, from))); |
188 | |
189 const XmlElement* jingle = iq->FirstNamed(QName(kJingleNamespace, "jingle")); | |
190 | |
191 if (!jingle) { | |
192 return SignalingAddress(jid); | |
193 } | |
194 | |
195 std::string type(iq->Attr(QName(std::string(), "type"))); | |
196 // For error IQs, flips the |from| flag as the jingle node represents the | |
197 // original request. | |
198 if (type == "error") { | |
199 from = !from; | |
200 } | |
201 | |
179 std::string endpoint_id( | 202 std::string endpoint_id( |
180 stanza->Attr(GetQNameByField(Field::ENDPOINT_ID, from))); | 203 jingle->Attr(GetQNameByField(Field::ENDPOINT_ID, from))); |
181 std::string channel_str(stanza->Attr(GetQNameByField(Field::CHANNEL, from))); | 204 std::string channel_str(jingle->Attr(GetQNameByField(Field::CHANNEL, from))); |
182 SignalingAddress::Channel channel; | 205 SignalingAddress::Channel channel; |
183 | 206 |
184 if (channel_str.empty()) { | 207 if (channel_str.empty()) { |
185 channel = SignalingAddress::Channel::XMPP; | 208 channel = SignalingAddress::Channel::XMPP; |
186 } else if (!NameToValue(kChannelTypes, channel_str, &channel)) { | 209 } else if (!NameToValue(kChannelTypes, channel_str, &channel)) { |
187 *error = "Unknown channel: " + channel_str; | 210 *error = "Unknown channel: " + channel_str; |
188 return empty_instance; | 211 return empty_instance; |
189 } | 212 } |
190 | 213 |
191 bool isLcs = (channel == SignalingAddress::Channel::LCS); | 214 bool isLcs = (channel == SignalingAddress::Channel::LCS); |
192 | 215 |
193 if (isLcs == endpoint_id.empty()) { | 216 if (isLcs == endpoint_id.empty()) { |
194 *error = (isLcs ? "Missing |endpoint-id| for LCS channel" | 217 *error = (isLcs ? "Missing |endpoint-id| for LCS channel" |
195 : "|endpoint_id| should be empty for XMPP channel"); | 218 : "|endpoint_id| should be empty for XMPP channel"); |
196 return empty_instance; | 219 return empty_instance; |
197 } | 220 } |
198 | 221 |
199 return SignalingAddress(jid, endpoint_id, channel); | 222 return SignalingAddress(jid, endpoint_id, channel); |
200 } | 223 } |
201 | 224 |
202 void SetAddress(buzz::XmlElement* iqElement, | 225 void SetAddress(buzz::XmlElement* iq, |
203 const SignalingAddress& address, | 226 const SignalingAddress& address, |
204 bool from) { | 227 bool from) { |
205 // Start from a fresh slate regardless of the previous address format. | |
206 iqElement->ClearAttr(GetQNameByField(Field::JID, from)); | |
207 iqElement->ClearAttr(GetQNameByField(Field::CHANNEL, from)); | |
208 iqElement->ClearAttr(GetQNameByField(Field::ENDPOINT_ID, from)); | |
209 | |
210 if (address.empty()) { | 228 if (address.empty()) { |
211 return; | 229 return; |
212 } | 230 } |
213 | 231 |
214 // Always set the JID. | 232 // Always set the JID. |
215 iqElement->AddAttr(GetQNameByField(Field::JID, from), address.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 XmlElement* jingle = EnsureJingleTag(iq); | |
Sergey Ulanov
2016/06/04 17:10:31
I suggest passing a pointer to <jingle> explicitly
kelvinp
2016/06/06 20:43:41
Done.
| |
244 jingle->ClearAttr(GetQNameByField(Field::CHANNEL, from)); | |
Sergey Ulanov
2016/06/04 17:10:31
I this necessary? SetAddress() is always called wi
kelvinp
2016/06/06 20:43:41
This is true. For the sake of future maintenance,
| |
245 jingle->ClearAttr(GetQNameByField(Field::ENDPOINT_ID, from)); | |
216 | 246 |
217 // Only set the channel and endpoint_id in the LCS channel. | 247 // Only set the channel and endpoint_id in the LCS channel. |
218 if (address.channel == SignalingAddress::Channel::LCS) { | 248 if (address.channel == SignalingAddress::Channel::LCS) { |
219 iqElement->AddAttr(GetQNameByField(Field::ENDPOINT_ID, from), | 249 jingle->AddAttr( |
220 address.endpoint_id); | 250 GetQNameByField(Field::ENDPOINT_ID, from), address.endpoint_id); |
221 const char* channel_str = ValueToName(kChannelTypes, address.channel); | 251 jingle->AddAttr( |
222 iqElement->AddAttr(GetQNameByField(Field::CHANNEL, from), channel_str); | 252 GetQNameByField(Field::CHANNEL, from), |
253 ValueToName(kChannelTypes, address.channel)); | |
223 } | 254 } |
224 } | 255 } |
225 | 256 |
226 } // namespace | 257 } // namespace |
227 | 258 |
228 IceTransportInfo::NamedCandidate::NamedCandidate( | 259 IceTransportInfo::NamedCandidate::NamedCandidate( |
229 const std::string& name, | 260 const std::string& name, |
230 const cricket::Candidate& candidate) | 261 const cricket::Candidate& candidate) |
231 : name(name), | 262 : name(name), |
232 candidate(candidate) { | 263 candidate(candidate) { |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 | 426 |
396 std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const { | 427 std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const { |
397 std::unique_ptr<XmlElement> root( | 428 std::unique_ptr<XmlElement> root( |
398 new XmlElement(QName("jabber:client", "iq"), true)); | 429 new XmlElement(QName("jabber:client", "iq"), true)); |
399 | 430 |
400 DCHECK(!to.empty()); | 431 DCHECK(!to.empty()); |
401 SetAddress(root.get(), to, false); | 432 SetAddress(root.get(), to, false); |
402 SetAddress(root.get(), from, true); | 433 SetAddress(root.get(), from, true); |
403 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); | 434 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); |
404 | 435 |
405 XmlElement* jingle_tag = | 436 XmlElement* jingle_tag = EnsureJingleTag(root.get()); |
406 new XmlElement(QName(kJingleNamespace, "jingle"), true); | |
407 root->AddElement(jingle_tag); | |
408 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); | 437 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); |
409 | 438 |
410 const char* action_attr = ValueToName(kActionTypes, action); | 439 const char* action_attr = ValueToName(kActionTypes, action); |
411 if (!action_attr) | 440 if (!action_attr) |
412 LOG(FATAL) << "Invalid action value " << action; | 441 LOG(FATAL) << "Invalid action value " << action; |
413 jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr); | 442 jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr); |
414 | 443 |
415 if (action == SESSION_INFO) { | 444 if (action == SESSION_INFO) { |
416 if (info.get()) | 445 if (info.get()) |
417 jingle_tag->AddElement(new XmlElement(*info.get())); | 446 jingle_tag->AddElement(new XmlElement(*info.get())); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 text(text_value) { | 501 text(text_value) { |
473 } | 502 } |
474 | 503 |
475 JingleMessageReply::~JingleMessageReply() { } | 504 JingleMessageReply::~JingleMessageReply() { } |
476 | 505 |
477 std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml( | 506 std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml( |
478 const buzz::XmlElement* request_stanza) const { | 507 const buzz::XmlElement* request_stanza) const { |
479 std::unique_ptr<XmlElement> iq( | 508 std::unique_ptr<XmlElement> iq( |
480 new XmlElement(QName(kJabberNamespace, "iq"), true)); | 509 new XmlElement(QName(kJabberNamespace, "iq"), true)); |
481 | 510 |
511 iq->SetAttr(QName(kEmptyNamespace, "id"), | |
512 request_stanza->Attr(QName(kEmptyNamespace, "id"))); | |
513 | |
514 std::string type_string(type == REPLY_RESULT ? "result" : "error"); | |
515 iq->SetAttr(QName(kEmptyNamespace, "type"), type_string); | |
516 | |
482 SignalingAddress original_from; | 517 SignalingAddress original_from; |
483 std::string error_message; | 518 std::string error_message; |
484 original_from = ParseAddress(request_stanza, true, &error_message); | 519 original_from = ParseAddress(request_stanza, true, &error_message); |
485 DCHECK(error_message.empty()); | 520 DCHECK(error_message.empty()); |
486 SetAddress(iq.get(), original_from, false); | 521 SetAddress(iq.get(), original_from, false); |
487 | 522 |
488 iq->SetAttr(QName(kEmptyNamespace, "id"), | |
489 request_stanza->Attr(QName(kEmptyNamespace, "id"))); | |
490 | |
491 if (type == REPLY_RESULT) { | 523 if (type == REPLY_RESULT) { |
492 iq->SetAttr(QName(kEmptyNamespace, "type"), "result"); | |
493 return iq; | 524 return iq; |
494 } | 525 } |
495 | 526 |
496 DCHECK_EQ(type, REPLY_ERROR); | 527 DCHECK_EQ(type, REPLY_ERROR); |
497 | 528 |
498 iq->SetAttr(QName(kEmptyNamespace, "type"), "error"); | 529 iq->SetAttr(QName(kEmptyNamespace, "type"), "error"); |
499 | 530 |
500 for (const buzz::XmlElement* child = request_stanza->FirstElement(); | 531 for (const buzz::XmlElement* child = request_stanza->FirstElement(); |
501 child != nullptr; child = child->NextElement()) { | 532 child != nullptr; child = child->NextElement()) { |
502 iq->AddElement(new buzz::XmlElement(*child)); | 533 iq->AddElement(new buzz::XmlElement(*child)); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 result->AddElement(FormatIceCredentials(credentials)); | 632 result->AddElement(FormatIceCredentials(credentials)); |
602 } | 633 } |
603 for (const NamedCandidate& candidate : candidates) { | 634 for (const NamedCandidate& candidate : candidates) { |
604 result->AddElement(FormatIceCandidate(candidate)); | 635 result->AddElement(FormatIceCandidate(candidate)); |
605 } | 636 } |
606 return result; | 637 return result; |
607 } | 638 } |
608 | 639 |
609 } // namespace protocol | 640 } // namespace protocol |
610 } // namespace remoting | 641 } // namespace remoting |
OLD | NEW |