Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: remoting/protocol/jingle_messages.cc

Issue 1085703003: Use standard ICE in Chromoting. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix crash on memory bots Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/protocol/jingle_messages.h ('k') | remoting/protocol/jingle_messages_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "remoting/protocol/name_value_map.h" 11 #include "remoting/protocol/name_value_map.h"
12 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" 12 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
13 13
14 using buzz::QName; 14 using buzz::QName;
15 using buzz::XmlElement; 15 using buzz::XmlElement;
16 16
17 namespace remoting { 17 namespace remoting {
18 namespace protocol { 18 namespace protocol {
19 19
20 namespace {
21
20 const char kJabberNamespace[] = "jabber:client"; 22 const char kJabberNamespace[] = "jabber:client";
21 const char kJingleNamespace[] = "urn:xmpp:jingle:1"; 23 const char kJingleNamespace[] = "urn:xmpp:jingle:1";
22 const char kP2PTransportNamespace[] = "http://www.google.com/transport/p2p";
23 24
24 namespace { 25 // Namespace for transport messages for legacy GICE.
26 const char kGiceTransportNamespace[] = "http://www.google.com/transport/p2p";
27
28 // Namespace for transport messages when using standard ICE.
29 const char kIceTransportNamespace[] = "google:remoting:ice";
25 30
26 const char kEmptyNamespace[] = ""; 31 const char kEmptyNamespace[] = "";
27 const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace"; 32 const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace";
28 33
29 const int kPortMin = 1000; 34 const int kPortMin = 1000;
30 const int kPortMax = 65535; 35 const int kPortMax = 65535;
31 36
32 const NameMapElement<JingleMessage::ActionType> kActionTypes[] = { 37 const NameMapElement<JingleMessage::ActionType> kActionTypes[] = {
33 { JingleMessage::SESSION_INITIATE, "session-initiate" }, 38 { JingleMessage::SESSION_INITIATE, "session-initiate" },
34 { JingleMessage::SESSION_ACCEPT, "session-accept" }, 39 { JingleMessage::SESSION_ACCEPT, "session-accept" },
35 { JingleMessage::SESSION_TERMINATE, "session-terminate" }, 40 { JingleMessage::SESSION_TERMINATE, "session-terminate" },
36 { JingleMessage::SESSION_INFO, "session-info" }, 41 { JingleMessage::SESSION_INFO, "session-info" },
37 { JingleMessage::TRANSPORT_INFO, "transport-info" }, 42 { JingleMessage::TRANSPORT_INFO, "transport-info" },
38 }; 43 };
39 44
40 const NameMapElement<JingleMessage::Reason> kReasons[] = { 45 const NameMapElement<JingleMessage::Reason> kReasons[] = {
41 { JingleMessage::SUCCESS, "success" }, 46 { JingleMessage::SUCCESS, "success" },
42 { JingleMessage::DECLINE, "decline" }, 47 { JingleMessage::DECLINE, "decline" },
43 { JingleMessage::CANCEL, "cancel" }, 48 { JingleMessage::CANCEL, "cancel" },
44 { JingleMessage::GENERAL_ERROR, "general-error" }, 49 { JingleMessage::GENERAL_ERROR, "general-error" },
45 { JingleMessage::INCOMPATIBLE_PARAMETERS, "incompatible-parameters" }, 50 { JingleMessage::INCOMPATIBLE_PARAMETERS, "incompatible-parameters" },
46 }; 51 };
47 52
48 bool ParseCandidate(const buzz::XmlElement* element, 53 bool ParseIceCredentials(const buzz::XmlElement* element,
49 JingleMessage::NamedCandidate* candidate) { 54 JingleMessage::IceCredentials* credentials) {
50 DCHECK(element->Name() == QName(kP2PTransportNamespace, "candidate")); 55 DCHECK(element->Name() == QName(kIceTransportNamespace, "credentials"));
56
57 const std::string& channel = element->Attr(QName(kEmptyNamespace, "channel"));
58 const std::string& ufrag =
59 element->Attr(QName(kEmptyNamespace, "ufrag"));
60 const std::string& password =
61 element->Attr(QName(kEmptyNamespace, "password"));
62
63 if (channel.empty() || ufrag.empty() || password.empty()) {
64 return false;
65 }
66
67 credentials->channel = channel;
68 credentials->ufrag = ufrag;
69 credentials->password = password;
70
71 return true;
72 }
73
74 bool ParseIceCandidate(const buzz::XmlElement* element,
75 JingleMessage::NamedCandidate* candidate) {
76 DCHECK(element->Name() == QName(kIceTransportNamespace, "candidate"));
77
78 const std::string& name = element->Attr(QName(kEmptyNamespace, "name"));
79 const std::string& foundation =
80 element->Attr(QName(kEmptyNamespace, "foundation"));
81 const std::string& address = element->Attr(QName(kEmptyNamespace, "address"));
82 const std::string& port_str = element->Attr(QName(kEmptyNamespace, "port"));
83 const std::string& type = element->Attr(QName(kEmptyNamespace, "type"));
84 const std::string& protocol =
85 element->Attr(QName(kEmptyNamespace, "protocol"));
86 const std::string& priority_str =
87 element->Attr(QName(kEmptyNamespace, "priority"));
88 const std::string& generation_str =
89 element->Attr(QName(kEmptyNamespace, "generation"));
90
91 int port;
92 unsigned priority;
93 int generation;
94 if (name.empty() || foundation.empty() || address.empty() ||
95 !base::StringToInt(port_str, &port) || port < kPortMin ||
96 port > kPortMax || type.empty() || protocol.empty() ||
97 !base::StringToUint(priority_str, &priority) ||
98 !base::StringToInt(generation_str, &generation)) {
99 return false;
100 }
101
102 candidate->name = name;
103
104 candidate->candidate.set_foundation(foundation);
105 candidate->candidate.set_address(rtc::SocketAddress(address, port));
106 candidate->candidate.set_type(type);
107 candidate->candidate.set_protocol(protocol);
108 candidate->candidate.set_priority(priority);
109 candidate->candidate.set_generation(generation);
110
111 return true;
112 }
113
114 bool ParseIceTransportInfo(
115 const buzz::XmlElement* element,
116 std::list<JingleMessage::IceCredentials>* ice_credentials,
117 std::list<JingleMessage::NamedCandidate>* candidates) {
118 DCHECK(element->Name() == QName(kIceTransportNamespace, "transport"));
119
120 ice_credentials->clear();
121 candidates->clear();
122
123 QName qn_credentials(kIceTransportNamespace, "credentials");
124 for (const XmlElement* credentials_tag = element->FirstNamed(qn_credentials);
125 credentials_tag;
126 credentials_tag = credentials_tag->NextNamed(qn_credentials)) {
127 JingleMessage::IceCredentials credentials;
128 if (!ParseIceCredentials(credentials_tag, &credentials))
129 return false;
130 ice_credentials->push_back(credentials);
131 }
132
133 QName qn_candidate(kIceTransportNamespace, "candidate");
134 for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate);
135 candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) {
136 JingleMessage::NamedCandidate candidate;
137 if (!ParseIceCandidate(candidate_tag, &candidate))
138 return false;
139 candidates->push_back(candidate);
140 }
141
142 return true;
143 }
144
145 bool ParseGiceCandidate(const buzz::XmlElement* element,
146 JingleMessage::NamedCandidate* candidate) {
147 DCHECK(element->Name() == QName(kGiceTransportNamespace, "candidate"));
51 148
52 const std::string& name = element->Attr(QName(kEmptyNamespace, "name")); 149 const std::string& name = element->Attr(QName(kEmptyNamespace, "name"));
53 const std::string& address = element->Attr(QName(kEmptyNamespace, "address")); 150 const std::string& address = element->Attr(QName(kEmptyNamespace, "address"));
54 const std::string& port_str = element->Attr(QName(kEmptyNamespace, "port")); 151 const std::string& port_str = element->Attr(QName(kEmptyNamespace, "port"));
55 const std::string& type = element->Attr(QName(kEmptyNamespace, "type")); 152 const std::string& type = element->Attr(QName(kEmptyNamespace, "type"));
56 const std::string& protocol = 153 const std::string& protocol =
57 element->Attr(QName(kEmptyNamespace, "protocol")); 154 element->Attr(QName(kEmptyNamespace, "protocol"));
58 const std::string& username = 155 const std::string& username =
59 element->Attr(QName(kEmptyNamespace, "username")); 156 element->Attr(QName(kEmptyNamespace, "username"));
60 const std::string& password = 157 const std::string& password =
(...skipping 20 matching lines...) Expand all
81 candidate->candidate.set_type(type); 178 candidate->candidate.set_type(type);
82 candidate->candidate.set_protocol(protocol); 179 candidate->candidate.set_protocol(protocol);
83 candidate->candidate.set_username(username); 180 candidate->candidate.set_username(username);
84 candidate->candidate.set_password(password); 181 candidate->candidate.set_password(password);
85 candidate->candidate.set_preference(static_cast<float>(preference)); 182 candidate->candidate.set_preference(static_cast<float>(preference));
86 candidate->candidate.set_generation(generation); 183 candidate->candidate.set_generation(generation);
87 184
88 return true; 185 return true;
89 } 186 }
90 187
91 XmlElement* FormatCandidate(const JingleMessage::NamedCandidate& candidate) { 188 bool ParseGiceTransportInfo(
189 const buzz::XmlElement* element,
190 std::list<JingleMessage::NamedCandidate>* candidates) {
191 DCHECK(element->Name() == QName(kGiceTransportNamespace, "transport"));
192
193 candidates->clear();
194
195 QName qn_candidate(kGiceTransportNamespace, "candidate");
196 for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate);
197 candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) {
198 JingleMessage::NamedCandidate candidate;
199 if (!ParseGiceCandidate(candidate_tag, &candidate))
200 return false;
201 candidates->push_back(candidate);
202 }
203
204 return true;
205 }
206
207 XmlElement* FormatIceCredentials(
208 const JingleMessage::IceCredentials& credentials) {
92 XmlElement* result = 209 XmlElement* result =
93 new XmlElement(QName(kP2PTransportNamespace, "candidate")); 210 new XmlElement(QName(kIceTransportNamespace, "credentials"));
211 result->SetAttr(QName(kEmptyNamespace, "channel"), credentials.channel);
212 result->SetAttr(QName(kEmptyNamespace, "ufrag"), credentials.ufrag);
213 result->SetAttr(QName(kEmptyNamespace, "password"), credentials.password);
214 return result;
215 }
216
217 XmlElement* FormatIceCandidate(const JingleMessage::NamedCandidate& candidate) {
218 XmlElement* result =
219 new XmlElement(QName(kIceTransportNamespace, "candidate"));
220 result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name);
221 result->SetAttr(QName(kEmptyNamespace, "foundation"),
222 candidate.candidate.foundation());
223 result->SetAttr(QName(kEmptyNamespace, "address"),
224 candidate.candidate.address().ipaddr().ToString());
225 result->SetAttr(QName(kEmptyNamespace, "port"),
226 base::IntToString(candidate.candidate.address().port()));
227 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type());
228 result->SetAttr(QName(kEmptyNamespace, "protocol"),
229 candidate.candidate.protocol());
230 result->SetAttr(QName(kEmptyNamespace, "priority"),
231 base::DoubleToString(candidate.candidate.priority()));
232 result->SetAttr(QName(kEmptyNamespace, "generation"),
233 base::IntToString(candidate.candidate.generation()));
234 return result;
235 }
236
237 XmlElement* FormatGiceCandidate(
238 const JingleMessage::NamedCandidate& candidate) {
239 XmlElement* result =
240 new XmlElement(QName(kGiceTransportNamespace, "candidate"));
94 result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name); 241 result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name);
95 result->SetAttr(QName(kEmptyNamespace, "address"), 242 result->SetAttr(QName(kEmptyNamespace, "address"),
96 candidate.candidate.address().ipaddr().ToString()); 243 candidate.candidate.address().ipaddr().ToString());
97 result->SetAttr(QName(kEmptyNamespace, "port"), 244 result->SetAttr(QName(kEmptyNamespace, "port"),
98 base::IntToString(candidate.candidate.address().port())); 245 base::IntToString(candidate.candidate.address().port()));
99 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); 246 result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type());
100 result->SetAttr(QName(kEmptyNamespace, "protocol"), 247 result->SetAttr(QName(kEmptyNamespace, "protocol"),
101 candidate.candidate.protocol()); 248 candidate.candidate.protocol());
102 result->SetAttr(QName(kEmptyNamespace, "username"), 249 result->SetAttr(QName(kEmptyNamespace, "username"),
103 candidate.candidate.username()); 250 candidate.candidate.username());
104 result->SetAttr(QName(kEmptyNamespace, "password"), 251 result->SetAttr(QName(kEmptyNamespace, "password"),
105 candidate.candidate.password()); 252 candidate.candidate.password());
106 result->SetAttr(QName(kEmptyNamespace, "preference"), 253 result->SetAttr(QName(kEmptyNamespace, "preference"),
107 base::DoubleToString(candidate.candidate.preference())); 254 base::DoubleToString(candidate.candidate.preference()));
108 result->SetAttr(QName(kEmptyNamespace, "generation"), 255 result->SetAttr(QName(kEmptyNamespace, "generation"),
109 base::IntToString(candidate.candidate.generation())); 256 base::IntToString(candidate.candidate.generation()));
110 return result; 257 return result;
111 } 258 }
112 259
113 } // namespace 260 } // namespace
114 261
115 JingleMessage::NamedCandidate::NamedCandidate() {
116 }
117
118 JingleMessage::NamedCandidate::NamedCandidate( 262 JingleMessage::NamedCandidate::NamedCandidate(
119 const std::string& name, 263 const std::string& name,
120 const cricket::Candidate& candidate) 264 const cricket::Candidate& candidate)
121 : name(name), 265 : name(name),
122 candidate(candidate) { 266 candidate(candidate) {
123 } 267 }
124 268
269 JingleMessage::IceCredentials::IceCredentials(std::string channel,
270 std::string ufrag,
271 std::string password)
272 : channel(channel), ufrag(ufrag), password(password) {
273 }
274
125 // static 275 // static
126 bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) { 276 bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) {
127 return stanza->Name() == QName(kJabberNamespace, "iq") && 277 return stanza->Name() == QName(kJabberNamespace, "iq") &&
128 stanza->Attr(QName(std::string(), "type")) == "set" && 278 stanza->Attr(QName(std::string(), "type")) == "set" &&
129 stanza->FirstNamed(QName(kJingleNamespace, "jingle")) != nullptr; 279 stanza->FirstNamed(QName(kJingleNamespace, "jingle")) != nullptr;
130 } 280 }
131 281
132 // static 282 // static
133 std::string JingleMessage::GetActionName(ActionType action) { 283 std::string JingleMessage::GetActionName(ActionType action) {
134 return ValueToName(kActionTypes, action); 284 return ValueToName(kActionTypes, action);
135 } 285 }
136 286
137 JingleMessage::JingleMessage() 287 JingleMessage::JingleMessage() {
138 : action(UNKNOWN_ACTION),
139 reason(UNKNOWN_REASON) {
140 } 288 }
141 289
142 JingleMessage::JingleMessage( 290 JingleMessage::JingleMessage(const std::string& to,
143 const std::string& to_value, 291 ActionType action,
144 ActionType action_value, 292 const std::string& sid)
145 const std::string& sid_value) 293 : to(to), action(action), sid(sid) {
146 : to(to_value),
147 action(action_value),
148 sid(sid_value),
149 reason(UNKNOWN_REASON) {
150 } 294 }
151 295
152 JingleMessage::~JingleMessage() { 296 JingleMessage::~JingleMessage() {
153 } 297 }
154 298
155 bool JingleMessage::ParseXml(const buzz::XmlElement* stanza, 299 bool JingleMessage::ParseXml(const buzz::XmlElement* stanza,
156 std::string* error) { 300 std::string* error) {
157 if (!IsJingleMessage(stanza)) { 301 if (!IsJingleMessage(stanza)) {
158 *error = "Not a jingle message"; 302 *error = "Not a jingle message";
159 return false; 303 return false;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 return false; 377 return false;
234 } 378 }
235 379
236 description = ContentDescription::ParseXml(description_tag); 380 description = ContentDescription::ParseXml(description_tag);
237 if (!description.get()) { 381 if (!description.get()) {
238 *error = "Failed to parse content description"; 382 *error = "Failed to parse content description";
239 return false; 383 return false;
240 } 384 }
241 } 385 }
242 386
243 candidates.clear(); 387 const XmlElement* ice_transport_tag = content_tag->FirstNamed(
244 const XmlElement* transport_tag = content_tag->FirstNamed( 388 QName(kIceTransportNamespace, "transport"));
245 QName(kP2PTransportNamespace, "transport")); 389 const XmlElement* gice_transport_tag = content_tag->FirstNamed(
246 if (transport_tag) { 390 QName(kGiceTransportNamespace, "transport"));
247 QName qn_candidate(kP2PTransportNamespace, "candidate"); 391 if (ice_transport_tag && gice_transport_tag) {
248 for (const XmlElement* candidate_tag = 392 *error = "ICE and GICE transport information is found in the same message";
249 transport_tag->FirstNamed(qn_candidate); 393 return false;
250 candidate_tag != nullptr; 394 } else if (ice_transport_tag) {
251 candidate_tag = candidate_tag->NextNamed(qn_candidate)) { 395 standard_ice = true;
252 NamedCandidate candidate; 396 if (!ParseIceTransportInfo(ice_transport_tag, &ice_credentials,
253 if (!ParseCandidate(candidate_tag, &candidate)) { 397 &candidates)) {
254 *error = "Failed to parse candidates"; 398 *error = "Failed to parse transport info";
255 return false; 399 return false;
256 } 400 }
257 candidates.push_back(candidate); 401 } else if (gice_transport_tag) {
402 standard_ice = false;
403 ice_credentials.clear();
404 if (!ParseGiceTransportInfo(gice_transport_tag, &candidates)) {
405 *error = "Failed to parse transport info";
406 return false;
258 } 407 }
259 } 408 }
260 409
261 return true; 410 return true;
262 } 411 }
263 412
264 scoped_ptr<buzz::XmlElement> JingleMessage::ToXml() const { 413 scoped_ptr<buzz::XmlElement> JingleMessage::ToXml() const {
265 scoped_ptr<XmlElement> root( 414 scoped_ptr<XmlElement> root(
266 new XmlElement(QName("jabber:client", "iq"), true)); 415 new XmlElement(QName("jabber:client", "iq"), true));
267 416
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 new XmlElement(QName(kJingleNamespace, "content")); 455 new XmlElement(QName(kJingleNamespace, "content"));
307 jingle_tag->AddElement(content_tag); 456 jingle_tag->AddElement(content_tag);
308 457
309 content_tag->AddAttr(QName(kEmptyNamespace, "name"), 458 content_tag->AddAttr(QName(kEmptyNamespace, "name"),
310 ContentDescription::kChromotingContentName); 459 ContentDescription::kChromotingContentName);
311 content_tag->AddAttr(QName(kEmptyNamespace, "creator"), "initiator"); 460 content_tag->AddAttr(QName(kEmptyNamespace, "creator"), "initiator");
312 461
313 if (description.get()) 462 if (description.get())
314 content_tag->AddElement(description->ToXml()); 463 content_tag->AddElement(description->ToXml());
315 464
316 XmlElement* transport_tag = 465 if (standard_ice) {
317 new XmlElement(QName(kP2PTransportNamespace, "transport"), true); 466 XmlElement* transport_tag =
318 content_tag->AddElement(transport_tag); 467 new XmlElement(QName(kIceTransportNamespace, "transport"), true);
319 for (std::list<NamedCandidate>::const_iterator it = candidates.begin(); 468 content_tag->AddElement(transport_tag);
320 it != candidates.end(); ++it) { 469 for (std::list<IceCredentials>::const_iterator it =
321 transport_tag->AddElement(FormatCandidate(*it)); 470 ice_credentials.begin();
471 it != ice_credentials.end(); ++it) {
472 transport_tag->AddElement(FormatIceCredentials(*it));
473 }
474 for (std::list<NamedCandidate>::const_iterator it = candidates.begin();
475 it != candidates.end(); ++it) {
476 transport_tag->AddElement(FormatIceCandidate(*it));
477 }
478 } else {
479 XmlElement* transport_tag =
480 new XmlElement(QName(kGiceTransportNamespace, "transport"), true);
481 content_tag->AddElement(transport_tag);
482 for (std::list<NamedCandidate>::const_iterator it = candidates.begin();
483 it != candidates.end(); ++it) {
484 transport_tag->AddElement(FormatGiceCandidate(*it));
485 }
322 } 486 }
323 } 487 }
324 488
325 return root.Pass(); 489 return root.Pass();
326 } 490 }
327 491
328 JingleMessageReply::JingleMessageReply() 492 JingleMessageReply::JingleMessageReply()
329 : type(REPLY_RESULT), 493 : type(REPLY_RESULT),
330 error_type(NONE) { 494 error_type(NONE) {
331 } 495 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 text_elem->SetAttr(QName(kXmlNamespace, "lang"), "en"); 585 text_elem->SetAttr(QName(kXmlNamespace, "lang"), "en");
422 text_elem->SetBodyText(error_text); 586 text_elem->SetBodyText(error_text);
423 error->AddElement(text_elem); 587 error->AddElement(text_elem);
424 } 588 }
425 589
426 return iq.Pass(); 590 return iq.Pass();
427 } 591 }
428 592
429 } // namespace protocol 593 } // namespace protocol
430 } // namespace remoting 594 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/jingle_messages.h ('k') | remoting/protocol/jingle_messages_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698