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" |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |