| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include <string.h> | |
| 12 | |
| 13 #include <deque> | |
| 14 #include <map> | |
| 15 #include <sstream> | |
| 16 | |
| 17 #include "webrtc/base/base64.h" | |
| 18 #include "webrtc/base/common.h" | |
| 19 #include "webrtc/base/gunit.h" | |
| 20 #include "webrtc/base/helpers.h" | |
| 21 #include "webrtc/base/logging.h" | |
| 22 #include "webrtc/base/natserver.h" | |
| 23 #include "webrtc/base/natsocketfactory.h" | |
| 24 #include "webrtc/base/stringencode.h" | |
| 25 #include "webrtc/libjingle/session/parsing.h" | |
| 26 #include "webrtc/libjingle/session/sessionclient.h" | |
| 27 #include "webrtc/libjingle/session/sessionmanager.h" | |
| 28 #include "webrtc/libjingle/xmpp/constants.h" | |
| 29 #include "webrtc/p2p/base/basicpacketsocketfactory.h" | |
| 30 #include "webrtc/p2p/base/constants.h" | |
| 31 #include "webrtc/p2p/base/p2ptransport.h" | |
| 32 #include "webrtc/p2p/base/portallocator.h" | |
| 33 #include "webrtc/p2p/base/relayport.h" | |
| 34 #include "webrtc/p2p/base/relayserver.h" | |
| 35 #include "webrtc/p2p/base/stunport.h" | |
| 36 #include "webrtc/p2p/base/stunserver.h" | |
| 37 #include "webrtc/p2p/base/transportchannel.h" | |
| 38 #include "webrtc/p2p/base/transportchannelproxy.h" | |
| 39 #include "webrtc/p2p/base/udpport.h" | |
| 40 | |
| 41 using cricket::SignalingProtocol; | |
| 42 using cricket::PROTOCOL_HYBRID; | |
| 43 using cricket::PROTOCOL_JINGLE; | |
| 44 using cricket::PROTOCOL_GINGLE; | |
| 45 | |
| 46 static const std::string kInitiator = "init@init.com"; | |
| 47 static const std::string kResponder = "resp@resp.com"; | |
| 48 // Expected from test random number generator. | |
| 49 static const std::string kSessionId = "9254631414740579489"; | |
| 50 // TODO: When we need to test more than one transport type, | |
| 51 // allow this to be injected like the content types are. | |
| 52 static const std::string kTransportType = "http://www.google.com/transport/p2p"; | |
| 53 | |
| 54 // Controls how long we wait for a session to send messages that we | |
| 55 // expect, in milliseconds. We put it high to avoid flaky tests. | |
| 56 static const int kEventTimeout = 5000; | |
| 57 | |
| 58 static const int kNumPorts = 2; | |
| 59 static const int kPort0 = 28653; | |
| 60 static const int kPortStep = 5; | |
| 61 | |
| 62 int GetPort(int port_index) { | |
| 63 return kPort0 + (port_index * kPortStep); | |
| 64 } | |
| 65 | |
| 66 std::string GetPortString(int port_index) { | |
| 67 return rtc::ToString(GetPort(port_index)); | |
| 68 } | |
| 69 | |
| 70 // Only works for port_index < 10, which is fine for our purposes. | |
| 71 std::string GetUsername(int port_index) { | |
| 72 return "username" + std::string(8, rtc::ToString(port_index)[0]); | |
| 73 } | |
| 74 | |
| 75 // Only works for port_index < 10, which is fine for our purposes. | |
| 76 std::string GetPassword(int port_index) { | |
| 77 return "password" + std::string(8, rtc::ToString(port_index)[0]); | |
| 78 } | |
| 79 | |
| 80 std::string IqAck(const std::string& id, | |
| 81 const std::string& from, | |
| 82 const std::string& to) { | |
| 83 return "<cli:iq" | |
| 84 " to=\"" + to + "\"" | |
| 85 " id=\"" + id + "\"" | |
| 86 " type=\"result\"" | |
| 87 " from=\"" + from + "\"" | |
| 88 " xmlns:cli=\"jabber:client\"" | |
| 89 "/>"; | |
| 90 } | |
| 91 | |
| 92 std::string IqSet(const std::string& id, | |
| 93 const std::string& from, | |
| 94 const std::string& to, | |
| 95 const std::string& content) { | |
| 96 return "<cli:iq" | |
| 97 " to=\"" + to + "\"" | |
| 98 " type=\"set\"" | |
| 99 " from=\"" + from + "\"" | |
| 100 " id=\"" + id + "\"" | |
| 101 " xmlns:cli=\"jabber:client\"" | |
| 102 ">" | |
| 103 + content + | |
| 104 "</cli:iq>"; | |
| 105 } | |
| 106 | |
| 107 std::string IqError(const std::string& id, | |
| 108 const std::string& from, | |
| 109 const std::string& to, | |
| 110 const std::string& content) { | |
| 111 return "<cli:error" | |
| 112 " to=\"" + to + "\"" | |
| 113 " type=\"error\"" | |
| 114 " from=\"" + from + "\"" | |
| 115 " id=\"" + id + "\"" | |
| 116 " xmlns:cli=\"jabber:client\"" | |
| 117 ">" | |
| 118 + content + | |
| 119 "</cli:error>"; | |
| 120 } | |
| 121 | |
| 122 std::string GingleSessionXml(const std::string& type, | |
| 123 const std::string& content) { | |
| 124 return "<session" | |
| 125 " xmlns=\"http://www.google.com/session\"" | |
| 126 " type=\"" + type + "\"" | |
| 127 " id=\"" + kSessionId + "\"" | |
| 128 " initiator=\"" + kInitiator + "\"" | |
| 129 ">" | |
| 130 + content + | |
| 131 "</session>"; | |
| 132 } | |
| 133 | |
| 134 std::string GingleDescriptionXml(const std::string& content_type) { | |
| 135 return "<description" | |
| 136 " xmlns=\"" + content_type + "\"" | |
| 137 "/>"; | |
| 138 } | |
| 139 | |
| 140 std::string P2pCandidateXml(const std::string& name, int port_index) { | |
| 141 // Port will update the rtcp username by +1 on the last character. So we need | |
| 142 // to compensate here. See Port::username_fragment() for detail. | |
| 143 std::string username = GetUsername(port_index); | |
| 144 // TODO: Use the component id instead of the channel name to | |
| 145 // determinte if we need to covert the username here. | |
| 146 if (name == "rtcp" || name == "video_rtcp" || name == "chanb") { | |
| 147 char next_ch = username[username.size() - 1]; | |
| 148 ASSERT(username.size() > 0); | |
| 149 rtc::Base64::GetNextBase64Char(next_ch, &next_ch); | |
| 150 username[username.size() - 1] = next_ch; | |
| 151 } | |
| 152 return "<candidate" | |
| 153 " name=\"" + name + "\"" | |
| 154 " address=\"127.0.0.1\"" | |
| 155 " port=\"" + GetPortString(port_index) + "\"" | |
| 156 " preference=\"0.99\"" | |
| 157 " username=\"" + username + "\"" | |
| 158 " protocol=\"udp\"" | |
| 159 " generation=\"0\"" | |
| 160 " password=\"" + GetPassword(port_index) + "\"" | |
| 161 " type=\"local\"" | |
| 162 " network=\"network\"" | |
| 163 "/>"; | |
| 164 } | |
| 165 | |
| 166 std::string JingleActionXml(const std::string& action, | |
| 167 const std::string& content) { | |
| 168 return "<jingle" | |
| 169 " xmlns=\"urn:xmpp:jingle:1\"" | |
| 170 " action=\"" + action + "\"" | |
| 171 " sid=\"" + kSessionId + "\"" | |
| 172 ">" | |
| 173 + content + | |
| 174 "</jingle>"; | |
| 175 } | |
| 176 | |
| 177 std::string JingleInitiateActionXml(const std::string& content) { | |
| 178 return "<jingle" | |
| 179 " xmlns=\"urn:xmpp:jingle:1\"" | |
| 180 " action=\"session-initiate\"" | |
| 181 " sid=\"" + kSessionId + "\"" | |
| 182 " initiator=\"" + kInitiator + "\"" | |
| 183 ">" | |
| 184 + content + | |
| 185 "</jingle>"; | |
| 186 } | |
| 187 | |
| 188 std::string JingleGroupInfoXml(const std::string& content_name_a, | |
| 189 const std::string& content_name_b) { | |
| 190 std::string group_info = "<jin:group" | |
| 191 " type=\"BUNDLE\"" | |
| 192 " xmlns:jin=\"google:jingle\"" | |
| 193 ">"; | |
| 194 if (!content_name_a.empty()) | |
| 195 group_info += "<content name=\"" + content_name_a + "\"" | |
| 196 "/>"; | |
| 197 if (!content_name_b.empty()) | |
| 198 group_info += "<content name=\"" + content_name_b + "\"" | |
| 199 "/>"; | |
| 200 group_info += "</jin:group>"; | |
| 201 return group_info; | |
| 202 } | |
| 203 | |
| 204 | |
| 205 std::string JingleEmptyContentXml(const std::string& content_name, | |
| 206 const std::string& content_type, | |
| 207 const std::string& transport_type) { | |
| 208 return "<content" | |
| 209 " name=\"" + content_name + "\"" | |
| 210 " creator=\"initiator\"" | |
| 211 ">" | |
| 212 "<description" | |
| 213 " xmlns=\"" + content_type + "\"" | |
| 214 "/>" | |
| 215 "<transport" | |
| 216 " xmlns=\"" + transport_type + "\"" | |
| 217 "/>" | |
| 218 "</content>"; | |
| 219 } | |
| 220 | |
| 221 std::string JingleContentXml(const std::string& content_name, | |
| 222 const std::string& content_type, | |
| 223 const std::string& transport_type, | |
| 224 const std::string& transport_main) { | |
| 225 std::string transport = transport_type.empty() ? "" : | |
| 226 "<transport" | |
| 227 " xmlns=\"" + transport_type + "\"" | |
| 228 ">" | |
| 229 + transport_main + | |
| 230 "</transport>"; | |
| 231 | |
| 232 return"<content" | |
| 233 " name=\"" + content_name + "\"" | |
| 234 " creator=\"initiator\"" | |
| 235 ">" | |
| 236 "<description" | |
| 237 " xmlns=\"" + content_type + "\"" | |
| 238 "/>" | |
| 239 + transport + | |
| 240 "</content>"; | |
| 241 } | |
| 242 | |
| 243 std::string JingleTransportContentXml(const std::string& content_name, | |
| 244 const std::string& transport_type, | |
| 245 const std::string& content) { | |
| 246 return "<content" | |
| 247 " name=\"" + content_name + "\"" | |
| 248 " creator=\"initiator\"" | |
| 249 ">" | |
| 250 "<transport" | |
| 251 " xmlns=\"" + transport_type + "\"" | |
| 252 ">" | |
| 253 + content + | |
| 254 "</transport>" | |
| 255 "</content>"; | |
| 256 } | |
| 257 | |
| 258 std::string GingleInitiateXml(const std::string& content_type) { | |
| 259 return GingleSessionXml( | |
| 260 "initiate", | |
| 261 GingleDescriptionXml(content_type)); | |
| 262 } | |
| 263 | |
| 264 std::string JingleInitiateXml(const std::string& content_name_a, | |
| 265 const std::string& content_type_a, | |
| 266 const std::string& content_name_b, | |
| 267 const std::string& content_type_b, | |
| 268 bool bundle = false) { | |
| 269 std::string content_xml; | |
| 270 if (content_name_b.empty()) { | |
| 271 content_xml = JingleEmptyContentXml( | |
| 272 content_name_a, content_type_a, kTransportType); | |
| 273 } else { | |
| 274 content_xml = JingleEmptyContentXml( | |
| 275 content_name_a, content_type_a, kTransportType) + | |
| 276 JingleEmptyContentXml( | |
| 277 content_name_b, content_type_b, kTransportType); | |
| 278 if (bundle) { | |
| 279 content_xml += JingleGroupInfoXml(content_name_a, content_name_b); | |
| 280 } | |
| 281 } | |
| 282 return JingleInitiateActionXml(content_xml); | |
| 283 } | |
| 284 | |
| 285 std::string GingleAcceptXml(const std::string& content_type) { | |
| 286 return GingleSessionXml( | |
| 287 "accept", | |
| 288 GingleDescriptionXml(content_type)); | |
| 289 } | |
| 290 | |
| 291 std::string JingleAcceptXml(const std::string& content_name_a, | |
| 292 const std::string& content_type_a, | |
| 293 const std::string& content_name_b, | |
| 294 const std::string& content_type_b, | |
| 295 bool bundle = false) { | |
| 296 std::string content_xml; | |
| 297 if (content_name_b.empty()) { | |
| 298 content_xml = JingleEmptyContentXml( | |
| 299 content_name_a, content_type_a, kTransportType); | |
| 300 } else { | |
| 301 content_xml = JingleEmptyContentXml( | |
| 302 content_name_a, content_type_a, kTransportType) + | |
| 303 JingleEmptyContentXml( | |
| 304 content_name_b, content_type_b, kTransportType); | |
| 305 } | |
| 306 if (bundle) { | |
| 307 content_xml += JingleGroupInfoXml(content_name_a, content_name_b); | |
| 308 } | |
| 309 | |
| 310 return JingleActionXml("session-accept", content_xml); | |
| 311 } | |
| 312 | |
| 313 std::string Gingle2CandidatesXml(const std::string& channel_name, | |
| 314 int port_index0, | |
| 315 int port_index1) { | |
| 316 return GingleSessionXml( | |
| 317 "candidates", | |
| 318 P2pCandidateXml(channel_name, port_index0) + | |
| 319 P2pCandidateXml(channel_name, port_index1)); | |
| 320 } | |
| 321 | |
| 322 std::string Gingle4CandidatesXml(const std::string& channel_name_a, | |
| 323 int port_index0, | |
| 324 int port_index1, | |
| 325 const std::string& channel_name_b, | |
| 326 int port_index2, | |
| 327 int port_index3) { | |
| 328 return GingleSessionXml( | |
| 329 "candidates", | |
| 330 P2pCandidateXml(channel_name_a, port_index0) + | |
| 331 P2pCandidateXml(channel_name_a, port_index1) + | |
| 332 P2pCandidateXml(channel_name_b, port_index2) + | |
| 333 P2pCandidateXml(channel_name_b, port_index3)); | |
| 334 } | |
| 335 | |
| 336 std::string Jingle2TransportInfoXml(const std::string& content_name, | |
| 337 const std::string& channel_name, | |
| 338 int port_index0, | |
| 339 int port_index1) { | |
| 340 return JingleActionXml( | |
| 341 "transport-info", | |
| 342 JingleTransportContentXml( | |
| 343 content_name, kTransportType, | |
| 344 P2pCandidateXml(channel_name, port_index0) + | |
| 345 P2pCandidateXml(channel_name, port_index1))); | |
| 346 } | |
| 347 | |
| 348 std::string Jingle4TransportInfoXml(const std::string& content_name, | |
| 349 const std::string& channel_name_a, | |
| 350 int port_index0, | |
| 351 int port_index1, | |
| 352 const std::string& channel_name_b, | |
| 353 int port_index2, | |
| 354 int port_index3) { | |
| 355 return JingleActionXml( | |
| 356 "transport-info", | |
| 357 JingleTransportContentXml( | |
| 358 content_name, kTransportType, | |
| 359 P2pCandidateXml(channel_name_a, port_index0) + | |
| 360 P2pCandidateXml(channel_name_a, port_index1) + | |
| 361 P2pCandidateXml(channel_name_b, port_index2) + | |
| 362 P2pCandidateXml(channel_name_b, port_index3))); | |
| 363 } | |
| 364 | |
| 365 std::string JingleDescriptionInfoXml(const std::string& content_name, | |
| 366 const std::string& content_type) { | |
| 367 return JingleActionXml( | |
| 368 "description-info", | |
| 369 JingleContentXml(content_name, content_type, "", "")); | |
| 370 } | |
| 371 | |
| 372 std::string GingleRejectXml(const std::string& reason) { | |
| 373 return GingleSessionXml( | |
| 374 "reject", | |
| 375 "<" + reason + "/>"); | |
| 376 } | |
| 377 | |
| 378 std::string JingleTerminateXml(const std::string& reason) { | |
| 379 return JingleActionXml( | |
| 380 "session-terminate", | |
| 381 "<reason><" + reason + "/></reason>"); | |
| 382 } | |
| 383 | |
| 384 std::string GingleTerminateXml(const std::string& reason) { | |
| 385 return GingleSessionXml( | |
| 386 "terminate", | |
| 387 "<" + reason + "/>"); | |
| 388 } | |
| 389 | |
| 390 std::string GingleRedirectXml(const std::string& intitiate, | |
| 391 const std::string& target) { | |
| 392 return intitiate + | |
| 393 "<error code=\"302\" type=\"modify\">" | |
| 394 "<redirect xmlns=\"http://www.google.com/session\">" | |
| 395 "xmpp:" + target + | |
| 396 "</redirect>" | |
| 397 "</error>"; | |
| 398 } | |
| 399 | |
| 400 std::string JingleRedirectXml(const std::string& intitiate, | |
| 401 const std::string& target) { | |
| 402 return intitiate + | |
| 403 "<error code=\"302\" type=\"modify\">" | |
| 404 "<redirect xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">" | |
| 405 "xmpp:" + target + | |
| 406 "</redirect>" | |
| 407 "</error>"; | |
| 408 } | |
| 409 | |
| 410 std::string InitiateXml(SignalingProtocol protocol, | |
| 411 const std::string& gingle_content_type, | |
| 412 const std::string& content_name_a, | |
| 413 const std::string& content_type_a, | |
| 414 const std::string& content_name_b, | |
| 415 const std::string& content_type_b, | |
| 416 bool bundle = false) { | |
| 417 switch (protocol) { | |
| 418 case PROTOCOL_JINGLE: | |
| 419 return JingleInitiateXml(content_name_a, content_type_a, | |
| 420 content_name_b, content_type_b, | |
| 421 bundle); | |
| 422 case PROTOCOL_GINGLE: | |
| 423 return GingleInitiateXml(gingle_content_type); | |
| 424 case PROTOCOL_HYBRID: | |
| 425 return JingleInitiateXml(content_name_a, content_type_a, | |
| 426 content_name_b, content_type_b) + | |
| 427 GingleInitiateXml(gingle_content_type); | |
| 428 } | |
| 429 return ""; | |
| 430 } | |
| 431 | |
| 432 std::string InitiateXml(SignalingProtocol protocol, | |
| 433 const std::string& content_name, | |
| 434 const std::string& content_type) { | |
| 435 return InitiateXml(protocol, | |
| 436 content_type, | |
| 437 content_name, content_type, | |
| 438 "", ""); | |
| 439 } | |
| 440 | |
| 441 std::string AcceptXml(SignalingProtocol protocol, | |
| 442 const std::string& gingle_content_type, | |
| 443 const std::string& content_name_a, | |
| 444 const std::string& content_type_a, | |
| 445 const std::string& content_name_b, | |
| 446 const std::string& content_type_b, | |
| 447 bool bundle = false) { | |
| 448 switch (protocol) { | |
| 449 case PROTOCOL_JINGLE: | |
| 450 return JingleAcceptXml(content_name_a, content_type_a, | |
| 451 content_name_b, content_type_b, bundle); | |
| 452 case PROTOCOL_GINGLE: | |
| 453 return GingleAcceptXml(gingle_content_type); | |
| 454 case PROTOCOL_HYBRID: | |
| 455 return | |
| 456 JingleAcceptXml(content_name_a, content_type_a, | |
| 457 content_name_b, content_type_b) + | |
| 458 GingleAcceptXml(gingle_content_type); | |
| 459 } | |
| 460 return ""; | |
| 461 } | |
| 462 | |
| 463 | |
| 464 std::string AcceptXml(SignalingProtocol protocol, | |
| 465 const std::string& content_name, | |
| 466 const std::string& content_type, | |
| 467 bool bundle = false) { | |
| 468 return AcceptXml(protocol, | |
| 469 content_type, | |
| 470 content_name, content_type, | |
| 471 "", ""); | |
| 472 } | |
| 473 | |
| 474 std::string TransportInfo2Xml(SignalingProtocol protocol, | |
| 475 const std::string& content_name, | |
| 476 const std::string& channel_name, | |
| 477 int port_index0, | |
| 478 int port_index1) { | |
| 479 switch (protocol) { | |
| 480 case PROTOCOL_JINGLE: | |
| 481 return Jingle2TransportInfoXml( | |
| 482 content_name, | |
| 483 channel_name, port_index0, port_index1); | |
| 484 case PROTOCOL_GINGLE: | |
| 485 return Gingle2CandidatesXml( | |
| 486 channel_name, port_index0, port_index1); | |
| 487 case PROTOCOL_HYBRID: | |
| 488 return | |
| 489 Jingle2TransportInfoXml( | |
| 490 content_name, | |
| 491 channel_name, port_index0, port_index1) + | |
| 492 Gingle2CandidatesXml( | |
| 493 channel_name, port_index0, port_index1); | |
| 494 } | |
| 495 return ""; | |
| 496 } | |
| 497 | |
| 498 std::string TransportInfo4Xml(SignalingProtocol protocol, | |
| 499 const std::string& content_name, | |
| 500 const std::string& channel_name_a, | |
| 501 int port_index0, | |
| 502 int port_index1, | |
| 503 const std::string& channel_name_b, | |
| 504 int port_index2, | |
| 505 int port_index3) { | |
| 506 switch (protocol) { | |
| 507 case PROTOCOL_JINGLE: | |
| 508 return Jingle4TransportInfoXml( | |
| 509 content_name, | |
| 510 channel_name_a, port_index0, port_index1, | |
| 511 channel_name_b, port_index2, port_index3); | |
| 512 case PROTOCOL_GINGLE: | |
| 513 return Gingle4CandidatesXml( | |
| 514 channel_name_a, port_index0, port_index1, | |
| 515 channel_name_b, port_index2, port_index3); | |
| 516 case PROTOCOL_HYBRID: | |
| 517 return | |
| 518 Jingle4TransportInfoXml( | |
| 519 content_name, | |
| 520 channel_name_a, port_index0, port_index1, | |
| 521 channel_name_b, port_index2, port_index3) + | |
| 522 Gingle4CandidatesXml( | |
| 523 channel_name_a, port_index0, port_index1, | |
| 524 channel_name_b, port_index2, port_index3); | |
| 525 } | |
| 526 return ""; | |
| 527 } | |
| 528 | |
| 529 std::string RejectXml(SignalingProtocol protocol, | |
| 530 const std::string& reason) { | |
| 531 switch (protocol) { | |
| 532 case PROTOCOL_JINGLE: | |
| 533 return JingleTerminateXml(reason); | |
| 534 case PROTOCOL_GINGLE: | |
| 535 return GingleRejectXml(reason); | |
| 536 case PROTOCOL_HYBRID: | |
| 537 return JingleTerminateXml(reason) + | |
| 538 GingleRejectXml(reason); | |
| 539 } | |
| 540 return ""; | |
| 541 } | |
| 542 | |
| 543 std::string TerminateXml(SignalingProtocol protocol, | |
| 544 const std::string& reason) { | |
| 545 switch (protocol) { | |
| 546 case PROTOCOL_JINGLE: | |
| 547 return JingleTerminateXml(reason); | |
| 548 case PROTOCOL_GINGLE: | |
| 549 return GingleTerminateXml(reason); | |
| 550 case PROTOCOL_HYBRID: | |
| 551 return JingleTerminateXml(reason) + | |
| 552 GingleTerminateXml(reason); | |
| 553 } | |
| 554 return ""; | |
| 555 } | |
| 556 | |
| 557 std::string RedirectXml(SignalingProtocol protocol, | |
| 558 const std::string& initiate, | |
| 559 const std::string& target) { | |
| 560 switch (protocol) { | |
| 561 case PROTOCOL_JINGLE: | |
| 562 return JingleRedirectXml(initiate, target); | |
| 563 case PROTOCOL_GINGLE: | |
| 564 return GingleRedirectXml(initiate, target); | |
| 565 default: | |
| 566 break; | |
| 567 } | |
| 568 return ""; | |
| 569 } | |
| 570 | |
| 571 // TODO: Break out and join with fakeportallocator.h | |
| 572 class TestPortAllocatorSession : public cricket::PortAllocatorSession { | |
| 573 public: | |
| 574 TestPortAllocatorSession(const std::string& content_name, | |
| 575 int component, | |
| 576 const std::string& ice_ufrag, | |
| 577 const std::string& ice_pwd, | |
| 578 const int port_offset) | |
| 579 : PortAllocatorSession(content_name, component, ice_ufrag, ice_pwd, 0), | |
| 580 port_offset_(port_offset), | |
| 581 ports_(kNumPorts), | |
| 582 address_("127.0.0.1", 0), | |
| 583 network_("network", "unittest", | |
| 584 rtc::IPAddress(INADDR_LOOPBACK), 8), | |
| 585 socket_factory_(rtc::Thread::Current()), | |
| 586 running_(false) { | |
| 587 network_.AddIP(address_.ipaddr()); | |
| 588 } | |
| 589 | |
| 590 ~TestPortAllocatorSession() { | |
| 591 for (size_t i = 0; i < ports_.size(); i++) | |
| 592 delete ports_[i]; | |
| 593 } | |
| 594 | |
| 595 virtual void StartGettingPorts() { | |
| 596 for (int i = 0; i < kNumPorts; i++) { | |
| 597 int index = port_offset_ + i; | |
| 598 ports_[i] = cricket::UDPPort::Create( | |
| 599 rtc::Thread::Current(), &socket_factory_, | |
| 600 &network_, address_.ipaddr(), GetPort(index), GetPort(index), | |
| 601 GetUsername(index), GetPassword(index), | |
| 602 std::string()); | |
| 603 AddPort(ports_[i]); | |
| 604 } | |
| 605 running_ = true; | |
| 606 } | |
| 607 | |
| 608 virtual void StopGettingPorts() { running_ = false; } | |
| 609 virtual bool IsGettingPorts() { return running_; } | |
| 610 | |
| 611 void AddPort(cricket::Port* port) { | |
| 612 port->set_component(component_); | |
| 613 port->set_generation(0); | |
| 614 port->SignalDestroyed.connect( | |
| 615 this, &TestPortAllocatorSession::OnPortDestroyed); | |
| 616 port->SignalPortComplete.connect( | |
| 617 this, &TestPortAllocatorSession::OnPortComplete); | |
| 618 port->PrepareAddress(); | |
| 619 SignalPortReady(this, port); | |
| 620 } | |
| 621 | |
| 622 void OnPortDestroyed(cricket::PortInterface* port) { | |
| 623 for (size_t i = 0; i < ports_.size(); i++) { | |
| 624 if (ports_[i] == port) | |
| 625 ports_[i] = NULL; | |
| 626 } | |
| 627 } | |
| 628 | |
| 629 void OnPortComplete(cricket::Port* port) { | |
| 630 SignalCandidatesReady(this, port->Candidates()); | |
| 631 } | |
| 632 | |
| 633 private: | |
| 634 int port_offset_; | |
| 635 std::vector<cricket::Port*> ports_; | |
| 636 rtc::SocketAddress address_; | |
| 637 rtc::Network network_; | |
| 638 rtc::BasicPacketSocketFactory socket_factory_; | |
| 639 bool running_; | |
| 640 }; | |
| 641 | |
| 642 class TestPortAllocator : public cricket::PortAllocator { | |
| 643 public: | |
| 644 TestPortAllocator() : port_offset_(0) {} | |
| 645 | |
| 646 virtual cricket::PortAllocatorSession* | |
| 647 CreateSessionInternal( | |
| 648 const std::string& content_name, | |
| 649 int component, | |
| 650 const std::string& ice_ufrag, | |
| 651 const std::string& ice_pwd) { | |
| 652 port_offset_ += 2; | |
| 653 return new TestPortAllocatorSession(content_name, component, | |
| 654 ice_ufrag, ice_pwd, port_offset_ - 2); | |
| 655 } | |
| 656 | |
| 657 int port_offset_; | |
| 658 }; | |
| 659 | |
| 660 class TestContentDescription : public cricket::ContentDescription { | |
| 661 public: | |
| 662 explicit TestContentDescription(const std::string& gingle_content_type, | |
| 663 const std::string& content_type) | |
| 664 : gingle_content_type(gingle_content_type), | |
| 665 content_type(content_type) { | |
| 666 } | |
| 667 virtual ContentDescription* Copy() const { | |
| 668 return new TestContentDescription(*this); | |
| 669 } | |
| 670 | |
| 671 std::string gingle_content_type; | |
| 672 std::string content_type; | |
| 673 }; | |
| 674 | |
| 675 cricket::SessionDescription* NewTestSessionDescription( | |
| 676 const std::string gingle_content_type, | |
| 677 const std::string& content_name_a, const std::string& content_type_a, | |
| 678 const std::string& content_name_b, const std::string& content_type_b) { | |
| 679 | |
| 680 cricket::SessionDescription* offer = new cricket::SessionDescription(); | |
| 681 offer->AddContent(content_name_a, content_type_a, | |
| 682 new TestContentDescription(gingle_content_type, | |
| 683 content_type_a)); | |
| 684 cricket::TransportDescription desc(cricket::NS_GINGLE_P2P, | |
| 685 std::string(), std::string()); | |
| 686 offer->AddTransportInfo(cricket::TransportInfo(content_name_a, desc)); | |
| 687 | |
| 688 if (content_name_a != content_name_b) { | |
| 689 offer->AddContent(content_name_b, content_type_b, | |
| 690 new TestContentDescription(gingle_content_type, | |
| 691 content_type_b)); | |
| 692 offer->AddTransportInfo(cricket::TransportInfo(content_name_b, desc)); | |
| 693 } | |
| 694 return offer; | |
| 695 } | |
| 696 | |
| 697 cricket::SessionDescription* NewTestSessionDescription( | |
| 698 const std::string& content_name, const std::string& content_type) { | |
| 699 | |
| 700 cricket::SessionDescription* offer = new cricket::SessionDescription(); | |
| 701 offer->AddContent(content_name, content_type, | |
| 702 new TestContentDescription(content_type, | |
| 703 content_type)); | |
| 704 offer->AddTransportInfo(cricket::TransportInfo | |
| 705 (content_name, cricket::TransportDescription( | |
| 706 cricket::NS_GINGLE_P2P, | |
| 707 std::string(), std::string()))); | |
| 708 return offer; | |
| 709 } | |
| 710 | |
| 711 struct TestSessionClient: public cricket::SessionClient, | |
| 712 public sigslot::has_slots<> { | |
| 713 public: | |
| 714 TestSessionClient() { | |
| 715 } | |
| 716 | |
| 717 ~TestSessionClient() { | |
| 718 } | |
| 719 | |
| 720 virtual bool ParseContent(SignalingProtocol protocol, | |
| 721 const buzz::XmlElement* elem, | |
| 722 cricket::ContentDescription** content, | |
| 723 cricket::ParseError* error) { | |
| 724 std::string content_type; | |
| 725 std::string gingle_content_type; | |
| 726 if (protocol == PROTOCOL_GINGLE) { | |
| 727 gingle_content_type = elem->Name().Namespace(); | |
| 728 } else { | |
| 729 content_type = elem->Name().Namespace(); | |
| 730 } | |
| 731 | |
| 732 *content = new TestContentDescription(gingle_content_type, content_type); | |
| 733 return true; | |
| 734 } | |
| 735 | |
| 736 virtual bool WriteContent(SignalingProtocol protocol, | |
| 737 const cricket::ContentDescription* untyped_content, | |
| 738 buzz::XmlElement** elem, | |
| 739 cricket::WriteError* error) { | |
| 740 const TestContentDescription* content = | |
| 741 static_cast<const TestContentDescription*>(untyped_content); | |
| 742 std::string content_type = (protocol == PROTOCOL_GINGLE ? | |
| 743 content->gingle_content_type : | |
| 744 content->content_type); | |
| 745 *elem = new buzz::XmlElement( | |
| 746 buzz::QName(content_type, "description"), true); | |
| 747 return true; | |
| 748 } | |
| 749 | |
| 750 void OnSessionCreate(cricket::Session* session, bool initiate) { | |
| 751 } | |
| 752 | |
| 753 void OnSessionDestroy(cricket::Session* session) { | |
| 754 } | |
| 755 }; | |
| 756 | |
| 757 struct ChannelHandler : sigslot::has_slots<> { | |
| 758 explicit ChannelHandler(cricket::TransportChannel* p, const std::string& name) | |
| 759 : channel(p), last_readable(false), last_writable(false), data_count(0), | |
| 760 last_size(0), name(name) { | |
| 761 p->SignalReadableState.connect(this, &ChannelHandler::OnReadableState); | |
| 762 p->SignalWritableState.connect(this, &ChannelHandler::OnWritableState); | |
| 763 p->SignalReadPacket.connect(this, &ChannelHandler::OnReadPacket); | |
| 764 } | |
| 765 | |
| 766 bool writable() const { | |
| 767 return last_writable && channel->writable(); | |
| 768 } | |
| 769 | |
| 770 bool readable() const { | |
| 771 return last_readable && channel->readable(); | |
| 772 } | |
| 773 | |
| 774 void OnReadableState(cricket::TransportChannel* p) { | |
| 775 EXPECT_EQ(channel, p); | |
| 776 last_readable = channel->readable(); | |
| 777 } | |
| 778 | |
| 779 void OnWritableState(cricket::TransportChannel* p) { | |
| 780 EXPECT_EQ(channel, p); | |
| 781 last_writable = channel->writable(); | |
| 782 } | |
| 783 | |
| 784 void OnReadPacket(cricket::TransportChannel* p, const char* buf, | |
| 785 size_t size, const rtc::PacketTime& time, int flags) { | |
| 786 if (memcmp(buf, name.c_str(), name.size()) != 0) | |
| 787 return; // drop packet if packet doesn't belong to this channel. This | |
| 788 // can happen when transport channels are muxed together. | |
| 789 buf += name.size(); // Remove channel name from the message. | |
| 790 size -= name.size(); // Decrement size by channel name string size. | |
| 791 EXPECT_EQ(channel, p); | |
| 792 EXPECT_LE(size, sizeof(last_data)); | |
| 793 data_count += 1; | |
| 794 last_size = size; | |
| 795 memcpy(last_data, buf, size); | |
| 796 } | |
| 797 | |
| 798 void Send(const char* data, size_t size) { | |
| 799 rtc::PacketOptions options; | |
| 800 std::string data_with_id(name); | |
| 801 data_with_id += data; | |
| 802 int result = channel->SendPacket(data_with_id.c_str(), data_with_id.size(), | |
| 803 options, 0); | |
| 804 EXPECT_EQ(static_cast<int>(data_with_id.size()), result); | |
| 805 } | |
| 806 | |
| 807 cricket::TransportChannel* channel; | |
| 808 bool last_readable, last_writable; | |
| 809 int data_count; | |
| 810 char last_data[4096]; | |
| 811 size_t last_size; | |
| 812 std::string name; | |
| 813 }; | |
| 814 | |
| 815 void PrintStanza(const std::string& message, | |
| 816 const buzz::XmlElement* stanza) { | |
| 817 printf("%s: %s\n", message.c_str(), stanza->Str().c_str()); | |
| 818 } | |
| 819 | |
| 820 class TestClient : public sigslot::has_slots<> { | |
| 821 public: | |
| 822 // TODO: Add channel_component_a/b as inputs to the ctor. | |
| 823 TestClient(cricket::PortAllocator* port_allocator, | |
| 824 int* next_message_id, | |
| 825 const std::string& local_name, | |
| 826 SignalingProtocol start_protocol, | |
| 827 const std::string& content_type, | |
| 828 const std::string& content_name_a, | |
| 829 const std::string& channel_name_a, | |
| 830 const std::string& content_name_b, | |
| 831 const std::string& channel_name_b) { | |
| 832 Construct(port_allocator, next_message_id, local_name, start_protocol, | |
| 833 content_type, content_name_a, channel_name_a, | |
| 834 content_name_b, channel_name_b); | |
| 835 } | |
| 836 | |
| 837 ~TestClient() { | |
| 838 if (session) { | |
| 839 session_manager->DestroySession(session); | |
| 840 EXPECT_EQ(1U, session_destroyed_count); | |
| 841 } | |
| 842 delete session_manager; | |
| 843 delete client; | |
| 844 for (std::deque<buzz::XmlElement*>::iterator it = sent_stanzas.begin(); | |
| 845 it != sent_stanzas.end(); ++it) { | |
| 846 delete *it; | |
| 847 } | |
| 848 } | |
| 849 | |
| 850 void Construct(cricket::PortAllocator* pa, | |
| 851 int* message_id, | |
| 852 const std::string& lname, | |
| 853 SignalingProtocol protocol, | |
| 854 const std::string& cont_type, | |
| 855 const std::string& cont_name_a, | |
| 856 const std::string& chan_name_a, | |
| 857 const std::string& cont_name_b, | |
| 858 const std::string& chan_name_b) { | |
| 859 port_allocator_ = pa; | |
| 860 next_message_id = message_id; | |
| 861 local_name = lname; | |
| 862 start_protocol = protocol; | |
| 863 content_type = cont_type; | |
| 864 content_name_a = cont_name_a; | |
| 865 channel_name_a = chan_name_a; | |
| 866 content_name_b = cont_name_b; | |
| 867 channel_name_b = chan_name_b; | |
| 868 session_created_count = 0; | |
| 869 session_destroyed_count = 0; | |
| 870 session_remote_description_update_count = 0; | |
| 871 new_local_description = false; | |
| 872 new_remote_description = false; | |
| 873 last_content_action = cricket::CA_OFFER; | |
| 874 last_content_source = cricket::CS_LOCAL; | |
| 875 session = NULL; | |
| 876 last_session_state = cricket::BaseSession::STATE_INIT; | |
| 877 blow_up_on_error = true; | |
| 878 error_count = 0; | |
| 879 | |
| 880 session_manager = new cricket::SessionManager(port_allocator_); | |
| 881 session_manager->SignalSessionCreate.connect( | |
| 882 this, &TestClient::OnSessionCreate); | |
| 883 session_manager->SignalSessionDestroy.connect( | |
| 884 this, &TestClient::OnSessionDestroy); | |
| 885 session_manager->SignalOutgoingMessage.connect( | |
| 886 this, &TestClient::OnOutgoingMessage); | |
| 887 | |
| 888 client = new TestSessionClient(); | |
| 889 session_manager->AddClient(content_type, client); | |
| 890 EXPECT_EQ(client, session_manager->GetClient(content_type)); | |
| 891 } | |
| 892 | |
| 893 uint32 sent_stanza_count() const { | |
| 894 return static_cast<uint32>(sent_stanzas.size()); | |
| 895 } | |
| 896 | |
| 897 const buzz::XmlElement* stanza() const { | |
| 898 return last_expected_sent_stanza.get(); | |
| 899 } | |
| 900 | |
| 901 cricket::BaseSession::State session_state() const { | |
| 902 EXPECT_EQ(last_session_state, session->state()); | |
| 903 return session->state(); | |
| 904 } | |
| 905 | |
| 906 void SetSessionState(cricket::BaseSession::State state) { | |
| 907 session->SetState(state); | |
| 908 EXPECT_EQ_WAIT(last_session_state, session->state(), kEventTimeout); | |
| 909 } | |
| 910 | |
| 911 void CreateSession() { | |
| 912 session_manager->CreateSession(local_name, content_type); | |
| 913 } | |
| 914 | |
| 915 void DeliverStanza(const buzz::XmlElement* stanza) { | |
| 916 session_manager->OnIncomingMessage(stanza); | |
| 917 } | |
| 918 | |
| 919 void DeliverStanza(const std::string& str) { | |
| 920 buzz::XmlElement* stanza = buzz::XmlElement::ForStr(str); | |
| 921 session_manager->OnIncomingMessage(stanza); | |
| 922 delete stanza; | |
| 923 } | |
| 924 | |
| 925 void DeliverAckToLastStanza() { | |
| 926 const buzz::XmlElement* orig_stanza = stanza(); | |
| 927 const buzz::XmlElement* response_stanza = | |
| 928 buzz::XmlElement::ForStr(IqAck(orig_stanza->Attr(buzz::QN_IQ), "", "")); | |
| 929 session_manager->OnIncomingResponse(orig_stanza, response_stanza); | |
| 930 delete response_stanza; | |
| 931 } | |
| 932 | |
| 933 void ExpectSentStanza(const std::string& expected) { | |
| 934 EXPECT_TRUE(!sent_stanzas.empty()) << | |
| 935 "Found no stanza when expected " << expected; | |
| 936 | |
| 937 last_expected_sent_stanza.reset(sent_stanzas.front()); | |
| 938 sent_stanzas.pop_front(); | |
| 939 | |
| 940 std::string actual = last_expected_sent_stanza->Str(); | |
| 941 EXPECT_EQ(expected, actual); | |
| 942 } | |
| 943 | |
| 944 void SkipUnsentStanza() { | |
| 945 GetNextOutgoingMessageID(); | |
| 946 } | |
| 947 | |
| 948 bool HasTransport(const std::string& content_name) const { | |
| 949 ASSERT(session != NULL); | |
| 950 const cricket::Transport* transport = session->GetTransport(content_name); | |
| 951 return transport != NULL && (kTransportType == transport->type()); | |
| 952 } | |
| 953 | |
| 954 bool HasChannel(const std::string& content_name, | |
| 955 int component) const { | |
| 956 ASSERT(session != NULL); | |
| 957 const cricket::TransportChannel* channel = | |
| 958 session->GetChannel(content_name, component); | |
| 959 return channel != NULL && (component == channel->component()); | |
| 960 } | |
| 961 | |
| 962 cricket::TransportChannel* GetChannel(const std::string& content_name, | |
| 963 int component) const { | |
| 964 ASSERT(session != NULL); | |
| 965 return session->GetChannel(content_name, component); | |
| 966 } | |
| 967 | |
| 968 void OnSessionCreate(cricket::Session* created_session, bool initiate) { | |
| 969 session_created_count += 1; | |
| 970 | |
| 971 session = created_session; | |
| 972 session->set_current_protocol(start_protocol); | |
| 973 session->SignalState.connect(this, &TestClient::OnSessionState); | |
| 974 session->SignalError.connect(this, &TestClient::OnSessionError); | |
| 975 session->SignalRemoteDescriptionUpdate.connect( | |
| 976 this, &TestClient::OnSessionRemoteDescriptionUpdate); | |
| 977 session->SignalNewLocalDescription.connect( | |
| 978 this, &TestClient::OnNewLocalDescription); | |
| 979 session->SignalNewRemoteDescription.connect( | |
| 980 this, &TestClient::OnNewRemoteDescription); | |
| 981 | |
| 982 CreateChannels(); | |
| 983 } | |
| 984 | |
| 985 void OnSessionDestroy(cricket::Session *session) { | |
| 986 session_destroyed_count += 1; | |
| 987 } | |
| 988 | |
| 989 void OnSessionState(cricket::BaseSession* session, | |
| 990 cricket::BaseSession::State state) { | |
| 991 // EXPECT_EQ does not allow use of this, hence the tmp variable. | |
| 992 cricket::BaseSession* tmp = this->session; | |
| 993 EXPECT_EQ(tmp, session); | |
| 994 last_session_state = state; | |
| 995 } | |
| 996 | |
| 997 void OnSessionError(cricket::BaseSession* session, | |
| 998 cricket::BaseSession::Error error) { | |
| 999 // EXPECT_EQ does not allow use of this, hence the tmp variable. | |
| 1000 cricket::BaseSession* tmp = this->session; | |
| 1001 EXPECT_EQ(tmp, session); | |
| 1002 if (blow_up_on_error) { | |
| 1003 EXPECT_TRUE(false); | |
| 1004 } else { | |
| 1005 error_count++; | |
| 1006 } | |
| 1007 } | |
| 1008 | |
| 1009 void OnSessionRemoteDescriptionUpdate(cricket::BaseSession* session, | |
| 1010 const cricket::ContentInfos& contents) { | |
| 1011 session_remote_description_update_count++; | |
| 1012 } | |
| 1013 | |
| 1014 void OnNewLocalDescription(cricket::BaseSession* session, | |
| 1015 cricket::ContentAction action) { | |
| 1016 new_local_description = true; | |
| 1017 last_content_action = action; | |
| 1018 last_content_source = cricket::CS_LOCAL; | |
| 1019 } | |
| 1020 | |
| 1021 void OnNewRemoteDescription(cricket::BaseSession* session, | |
| 1022 cricket::ContentAction action) { | |
| 1023 new_remote_description = true; | |
| 1024 last_content_action = action; | |
| 1025 last_content_source = cricket::CS_REMOTE; | |
| 1026 } | |
| 1027 | |
| 1028 void PrepareCandidates() { | |
| 1029 session_manager->OnSignalingReady(); | |
| 1030 } | |
| 1031 | |
| 1032 void OnOutgoingMessage(cricket::SessionManager* manager, | |
| 1033 const buzz::XmlElement* stanza) { | |
| 1034 buzz::XmlElement* elem = new buzz::XmlElement(*stanza); | |
| 1035 EXPECT_TRUE(elem->Name() == buzz::QN_IQ); | |
| 1036 EXPECT_TRUE(elem->HasAttr(buzz::QN_TO)); | |
| 1037 EXPECT_FALSE(elem->HasAttr(buzz::QN_FROM)); | |
| 1038 EXPECT_TRUE(elem->HasAttr(buzz::QN_TYPE)); | |
| 1039 EXPECT_TRUE((elem->Attr(buzz::QN_TYPE) == "set") || | |
| 1040 (elem->Attr(buzz::QN_TYPE) == "result") || | |
| 1041 (elem->Attr(buzz::QN_TYPE) == "error")); | |
| 1042 | |
| 1043 elem->SetAttr(buzz::QN_FROM, local_name); | |
| 1044 if (elem->Attr(buzz::QN_TYPE) == "set") { | |
| 1045 EXPECT_FALSE(elem->HasAttr(buzz::QN_ID)); | |
| 1046 elem->SetAttr(buzz::QN_ID, GetNextOutgoingMessageID()); | |
| 1047 } | |
| 1048 | |
| 1049 // Uncommenting this is useful for debugging. | |
| 1050 // PrintStanza("OutgoingMessage", elem); | |
| 1051 sent_stanzas.push_back(elem); | |
| 1052 } | |
| 1053 | |
| 1054 std::string GetNextOutgoingMessageID() { | |
| 1055 int message_id = (*next_message_id)++; | |
| 1056 std::ostringstream ost; | |
| 1057 ost << message_id; | |
| 1058 return ost.str(); | |
| 1059 } | |
| 1060 | |
| 1061 void CreateChannels() { | |
| 1062 ASSERT(session != NULL); | |
| 1063 // We either have a single content with multiple components (RTP/RTCP), or | |
| 1064 // multiple contents with single components, but not both. | |
| 1065 int component_a = 1; | |
| 1066 int component_b = (content_name_a == content_name_b) ? 2 : 1; | |
| 1067 chan_a.reset(new ChannelHandler( | |
| 1068 session->CreateChannel(content_name_a, channel_name_a, component_a), | |
| 1069 channel_name_a)); | |
| 1070 chan_b.reset(new ChannelHandler( | |
| 1071 session->CreateChannel(content_name_b, channel_name_b, component_b), | |
| 1072 channel_name_b)); | |
| 1073 } | |
| 1074 | |
| 1075 int* next_message_id; | |
| 1076 std::string local_name; | |
| 1077 SignalingProtocol start_protocol; | |
| 1078 std::string content_type; | |
| 1079 std::string content_name_a; | |
| 1080 std::string channel_name_a; | |
| 1081 std::string content_name_b; | |
| 1082 std::string channel_name_b; | |
| 1083 | |
| 1084 uint32 session_created_count; | |
| 1085 uint32 session_destroyed_count; | |
| 1086 uint32 session_remote_description_update_count; | |
| 1087 bool new_local_description; | |
| 1088 bool new_remote_description; | |
| 1089 cricket::ContentAction last_content_action; | |
| 1090 cricket::ContentSource last_content_source; | |
| 1091 std::deque<buzz::XmlElement*> sent_stanzas; | |
| 1092 rtc::scoped_ptr<buzz::XmlElement> last_expected_sent_stanza; | |
| 1093 | |
| 1094 cricket::SessionManager* session_manager; | |
| 1095 TestSessionClient* client; | |
| 1096 cricket::PortAllocator* port_allocator_; | |
| 1097 cricket::Session* session; | |
| 1098 cricket::BaseSession::State last_session_state; | |
| 1099 rtc::scoped_ptr<ChannelHandler> chan_a; | |
| 1100 rtc::scoped_ptr<ChannelHandler> chan_b; | |
| 1101 bool blow_up_on_error; | |
| 1102 int error_count; | |
| 1103 }; | |
| 1104 | |
| 1105 class SessionTest : public testing::Test { | |
| 1106 protected: | |
| 1107 virtual void SetUp() { | |
| 1108 // Seed needed for each test to satisfy expectations. | |
| 1109 rtc::SetRandomTestMode(true); | |
| 1110 } | |
| 1111 | |
| 1112 virtual void TearDown() { | |
| 1113 rtc::SetRandomTestMode(false); | |
| 1114 } | |
| 1115 | |
| 1116 // Tests sending data between two clients, over two channels. | |
| 1117 void TestSendRecv(ChannelHandler* chan1a, | |
| 1118 ChannelHandler* chan1b, | |
| 1119 ChannelHandler* chan2a, | |
| 1120 ChannelHandler* chan2b) { | |
| 1121 const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam"; | |
| 1122 const char* dat2a = "mapssnaebdekabmapsmapsmapsmapsmapsmapsmaps"; | |
| 1123 const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce..."; | |
| 1124 const char* dat2b = "...ecuas yanrom a htiw etteverC a rodimrehT retsboL"; | |
| 1125 | |
| 1126 for (int i = 0; i < 20; i++) { | |
| 1127 chan1a->Send(dat1a, strlen(dat1a)); | |
| 1128 chan1b->Send(dat1b, strlen(dat1b)); | |
| 1129 chan2a->Send(dat2a, strlen(dat2a)); | |
| 1130 chan2b->Send(dat2b, strlen(dat2b)); | |
| 1131 | |
| 1132 EXPECT_EQ_WAIT(i + 1, chan1a->data_count, kEventTimeout); | |
| 1133 EXPECT_EQ_WAIT(i + 1, chan1b->data_count, kEventTimeout); | |
| 1134 EXPECT_EQ_WAIT(i + 1, chan2a->data_count, kEventTimeout); | |
| 1135 EXPECT_EQ_WAIT(i + 1, chan2b->data_count, kEventTimeout); | |
| 1136 | |
| 1137 EXPECT_EQ(strlen(dat2a), chan1a->last_size); | |
| 1138 EXPECT_EQ(strlen(dat2b), chan1b->last_size); | |
| 1139 EXPECT_EQ(strlen(dat1a), chan2a->last_size); | |
| 1140 EXPECT_EQ(strlen(dat1b), chan2b->last_size); | |
| 1141 | |
| 1142 EXPECT_EQ(0, memcmp(chan1a->last_data, dat2a, strlen(dat2a))); | |
| 1143 EXPECT_EQ(0, memcmp(chan1b->last_data, dat2b, strlen(dat2b))); | |
| 1144 EXPECT_EQ(0, memcmp(chan2a->last_data, dat1a, strlen(dat1a))); | |
| 1145 EXPECT_EQ(0, memcmp(chan2b->last_data, dat1b, strlen(dat1b))); | |
| 1146 } | |
| 1147 } | |
| 1148 | |
| 1149 // Test an initiate from one client to another, each with | |
| 1150 // independent initial protocols. Checks for the correct initiates, | |
| 1151 // candidates, and accept messages, and tests that working network | |
| 1152 // channels are established. | |
| 1153 void TestSession(SignalingProtocol initiator_protocol, | |
| 1154 SignalingProtocol responder_protocol, | |
| 1155 SignalingProtocol resulting_protocol, | |
| 1156 const std::string& gingle_content_type, | |
| 1157 const std::string& content_type, | |
| 1158 const std::string& content_name_a, | |
| 1159 const std::string& channel_name_a, | |
| 1160 const std::string& content_name_b, | |
| 1161 const std::string& channel_name_b, | |
| 1162 const std::string& initiate_xml, | |
| 1163 const std::string& transport_info_a_xml, | |
| 1164 const std::string& transport_info_b_xml, | |
| 1165 const std::string& transport_info_reply_a_xml, | |
| 1166 const std::string& transport_info_reply_b_xml, | |
| 1167 const std::string& accept_xml, | |
| 1168 bool bundle = false) { | |
| 1169 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 1170 new TestPortAllocator()); | |
| 1171 int next_message_id = 0; | |
| 1172 | |
| 1173 rtc::scoped_ptr<TestClient> initiator( | |
| 1174 new TestClient(allocator.get(), &next_message_id, | |
| 1175 kInitiator, initiator_protocol, | |
| 1176 content_type, | |
| 1177 content_name_a, channel_name_a, | |
| 1178 content_name_b, channel_name_b)); | |
| 1179 rtc::scoped_ptr<TestClient> responder( | |
| 1180 new TestClient(allocator.get(), &next_message_id, | |
| 1181 kResponder, responder_protocol, | |
| 1182 content_type, | |
| 1183 content_name_a, channel_name_a, | |
| 1184 content_name_b, channel_name_b)); | |
| 1185 | |
| 1186 // Create Session and check channels and state. | |
| 1187 initiator->CreateSession(); | |
| 1188 EXPECT_EQ(1U, initiator->session_created_count); | |
| 1189 EXPECT_EQ(kSessionId, initiator->session->id()); | |
| 1190 EXPECT_EQ(initiator->session->local_name(), kInitiator); | |
| 1191 EXPECT_EQ(cricket::BaseSession::STATE_INIT, | |
| 1192 initiator->session_state()); | |
| 1193 | |
| 1194 // See comment in CreateChannels about how we choose component IDs. | |
| 1195 int component_a = 1; | |
| 1196 int component_b = (content_name_a == content_name_b) ? 2 : 1; | |
| 1197 EXPECT_TRUE(initiator->HasTransport(content_name_a)); | |
| 1198 EXPECT_TRUE(initiator->HasChannel(content_name_a, component_a)); | |
| 1199 EXPECT_TRUE(initiator->HasTransport(content_name_b)); | |
| 1200 EXPECT_TRUE(initiator->HasChannel(content_name_b, component_b)); | |
| 1201 | |
| 1202 // Initiate and expect initiate message sent. | |
| 1203 cricket::SessionDescription* offer = NewTestSessionDescription( | |
| 1204 gingle_content_type, | |
| 1205 content_name_a, content_type, | |
| 1206 content_name_b, content_type); | |
| 1207 if (bundle) { | |
| 1208 cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE); | |
| 1209 group.AddContentName(content_name_a); | |
| 1210 group.AddContentName(content_name_b); | |
| 1211 EXPECT_TRUE(group.HasContentName(content_name_a)); | |
| 1212 EXPECT_TRUE(group.HasContentName(content_name_b)); | |
| 1213 offer->AddGroup(group); | |
| 1214 } | |
| 1215 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer)); | |
| 1216 EXPECT_EQ(initiator->session->remote_name(), kResponder); | |
| 1217 EXPECT_EQ(initiator->session->local_description(), offer); | |
| 1218 | |
| 1219 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1220 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE, | |
| 1221 initiator->session_state()); | |
| 1222 | |
| 1223 initiator->ExpectSentStanza( | |
| 1224 IqSet("0", kInitiator, kResponder, initiate_xml)); | |
| 1225 | |
| 1226 // Deliver the initiate. Expect ack and session created with | |
| 1227 // transports. | |
| 1228 responder->DeliverStanza(initiator->stanza()); | |
| 1229 responder->ExpectSentStanza( | |
| 1230 IqAck("0", kResponder, kInitiator)); | |
| 1231 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1232 | |
| 1233 EXPECT_EQ(1U, responder->session_created_count); | |
| 1234 EXPECT_EQ(kSessionId, responder->session->id()); | |
| 1235 EXPECT_EQ(responder->session->local_name(), kResponder); | |
| 1236 EXPECT_EQ(responder->session->remote_name(), kInitiator); | |
| 1237 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE, | |
| 1238 responder->session_state()); | |
| 1239 | |
| 1240 EXPECT_TRUE(responder->HasTransport(content_name_a)); | |
| 1241 EXPECT_TRUE(responder->HasChannel(content_name_a, component_a)); | |
| 1242 EXPECT_TRUE(responder->HasTransport(content_name_b)); | |
| 1243 EXPECT_TRUE(responder->HasChannel(content_name_b, component_b)); | |
| 1244 | |
| 1245 // Expect transport-info message from initiator. | |
| 1246 // But don't send candidates until initiate ack is received. | |
| 1247 initiator->PrepareCandidates(); | |
| 1248 WAIT(initiator->sent_stanza_count() > 0, 100); | |
| 1249 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1250 initiator->DeliverAckToLastStanza(); | |
| 1251 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1252 initiator->ExpectSentStanza( | |
| 1253 IqSet("1", kInitiator, kResponder, transport_info_a_xml)); | |
| 1254 | |
| 1255 // Deliver transport-info and expect ack. | |
| 1256 responder->DeliverStanza(initiator->stanza()); | |
| 1257 responder->ExpectSentStanza( | |
| 1258 IqAck("1", kResponder, kInitiator)); | |
| 1259 | |
| 1260 if (!transport_info_b_xml.empty()) { | |
| 1261 // Expect second transport-info message from initiator. | |
| 1262 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1263 initiator->ExpectSentStanza( | |
| 1264 IqSet("2", kInitiator, kResponder, transport_info_b_xml)); | |
| 1265 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1266 | |
| 1267 // Deliver second transport-info message and expect ack. | |
| 1268 responder->DeliverStanza(initiator->stanza()); | |
| 1269 responder->ExpectSentStanza( | |
| 1270 IqAck("2", kResponder, kInitiator)); | |
| 1271 } else { | |
| 1272 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1273 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1274 initiator->SkipUnsentStanza(); | |
| 1275 } | |
| 1276 | |
| 1277 // Expect reply transport-info message from responder. | |
| 1278 responder->PrepareCandidates(); | |
| 1279 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout); | |
| 1280 responder->ExpectSentStanza( | |
| 1281 IqSet("3", kResponder, kInitiator, transport_info_reply_a_xml)); | |
| 1282 | |
| 1283 // Deliver reply transport-info and expect ack. | |
| 1284 initiator->DeliverStanza(responder->stanza()); | |
| 1285 initiator->ExpectSentStanza( | |
| 1286 IqAck("3", kInitiator, kResponder)); | |
| 1287 | |
| 1288 if (!transport_info_reply_b_xml.empty()) { | |
| 1289 // Expect second reply transport-info message from responder. | |
| 1290 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout); | |
| 1291 responder->ExpectSentStanza( | |
| 1292 IqSet("4", kResponder, kInitiator, transport_info_reply_b_xml)); | |
| 1293 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1294 | |
| 1295 // Deliver second reply transport-info message and expect ack. | |
| 1296 initiator->DeliverStanza(responder->stanza()); | |
| 1297 initiator->ExpectSentStanza( | |
| 1298 IqAck("4", kInitiator, kResponder)); | |
| 1299 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1300 } else { | |
| 1301 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1302 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1303 responder->SkipUnsentStanza(); | |
| 1304 } | |
| 1305 | |
| 1306 // The channels should be able to become writable at this point. This | |
| 1307 // requires pinging, so it may take a little while. | |
| 1308 EXPECT_TRUE_WAIT(initiator->chan_a->writable() && | |
| 1309 initiator->chan_a->readable(), kEventTimeout); | |
| 1310 EXPECT_TRUE_WAIT(initiator->chan_b->writable() && | |
| 1311 initiator->chan_b->readable(), kEventTimeout); | |
| 1312 EXPECT_TRUE_WAIT(responder->chan_a->writable() && | |
| 1313 responder->chan_a->readable(), kEventTimeout); | |
| 1314 EXPECT_TRUE_WAIT(responder->chan_b->writable() && | |
| 1315 responder->chan_b->readable(), kEventTimeout); | |
| 1316 | |
| 1317 // Accept the session and expect accept stanza. | |
| 1318 cricket::SessionDescription* answer = NewTestSessionDescription( | |
| 1319 gingle_content_type, | |
| 1320 content_name_a, content_type, | |
| 1321 content_name_b, content_type); | |
| 1322 if (bundle) { | |
| 1323 cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE); | |
| 1324 group.AddContentName(content_name_a); | |
| 1325 group.AddContentName(content_name_b); | |
| 1326 EXPECT_TRUE(group.HasContentName(content_name_a)); | |
| 1327 EXPECT_TRUE(group.HasContentName(content_name_b)); | |
| 1328 answer->AddGroup(group); | |
| 1329 } | |
| 1330 EXPECT_TRUE(responder->session->Accept(answer)); | |
| 1331 EXPECT_EQ(responder->session->local_description(), answer); | |
| 1332 | |
| 1333 responder->ExpectSentStanza( | |
| 1334 IqSet("5", kResponder, kInitiator, accept_xml)); | |
| 1335 | |
| 1336 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1337 | |
| 1338 // Deliver the accept message and expect an ack. | |
| 1339 initiator->DeliverStanza(responder->stanza()); | |
| 1340 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1341 initiator->ExpectSentStanza( | |
| 1342 IqAck("5", kInitiator, kResponder)); | |
| 1343 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1344 | |
| 1345 // Both sessions should be in progress and have functioning | |
| 1346 // channels. | |
| 1347 EXPECT_EQ(resulting_protocol, initiator->session->current_protocol()); | |
| 1348 EXPECT_EQ(resulting_protocol, responder->session->current_protocol()); | |
| 1349 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS, | |
| 1350 initiator->session_state(), kEventTimeout); | |
| 1351 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS, | |
| 1352 responder->session_state(), kEventTimeout); | |
| 1353 if (bundle) { | |
| 1354 cricket::TransportChannel* initiator_chan_a = initiator->chan_a->channel; | |
| 1355 cricket::TransportChannel* initiator_chan_b = initiator->chan_b->channel; | |
| 1356 | |
| 1357 // Since we know these are TransportChannelProxy, type cast it. | |
| 1358 cricket::TransportChannelProxy* initiator_proxy_chan_a = | |
| 1359 static_cast<cricket::TransportChannelProxy*>(initiator_chan_a); | |
| 1360 cricket::TransportChannelProxy* initiator_proxy_chan_b = | |
| 1361 static_cast<cricket::TransportChannelProxy*>(initiator_chan_b); | |
| 1362 EXPECT_TRUE(initiator_proxy_chan_a->impl() != NULL); | |
| 1363 EXPECT_TRUE(initiator_proxy_chan_b->impl() != NULL); | |
| 1364 EXPECT_EQ(initiator_proxy_chan_a->impl(), initiator_proxy_chan_b->impl()); | |
| 1365 | |
| 1366 cricket::TransportChannel* responder_chan_a = responder->chan_a->channel; | |
| 1367 cricket::TransportChannel* responder_chan_b = responder->chan_b->channel; | |
| 1368 | |
| 1369 // Since we know these are TransportChannelProxy, type cast it. | |
| 1370 cricket::TransportChannelProxy* responder_proxy_chan_a = | |
| 1371 static_cast<cricket::TransportChannelProxy*>(responder_chan_a); | |
| 1372 cricket::TransportChannelProxy* responder_proxy_chan_b = | |
| 1373 static_cast<cricket::TransportChannelProxy*>(responder_chan_b); | |
| 1374 EXPECT_TRUE(responder_proxy_chan_a->impl() != NULL); | |
| 1375 EXPECT_TRUE(responder_proxy_chan_b->impl() != NULL); | |
| 1376 EXPECT_EQ(responder_proxy_chan_a->impl(), responder_proxy_chan_b->impl()); | |
| 1377 } | |
| 1378 TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(), | |
| 1379 responder->chan_a.get(), responder->chan_b.get()); | |
| 1380 | |
| 1381 if (resulting_protocol == PROTOCOL_JINGLE) { | |
| 1382 // Deliver a description-info message to the initiator and check if the | |
| 1383 // content description changes. | |
| 1384 EXPECT_EQ(0U, initiator->session_remote_description_update_count); | |
| 1385 | |
| 1386 const cricket::SessionDescription* old_session_desc = | |
| 1387 initiator->session->remote_description(); | |
| 1388 const cricket::ContentInfo* old_content_a = | |
| 1389 old_session_desc->GetContentByName(content_name_a); | |
| 1390 const cricket::ContentDescription* old_content_desc_a = | |
| 1391 old_content_a->description; | |
| 1392 const cricket::ContentInfo* old_content_b = | |
| 1393 old_session_desc->GetContentByName(content_name_b); | |
| 1394 const cricket::ContentDescription* old_content_desc_b = | |
| 1395 old_content_b->description; | |
| 1396 EXPECT_TRUE(old_content_desc_a != NULL); | |
| 1397 EXPECT_TRUE(old_content_desc_b != NULL); | |
| 1398 | |
| 1399 LOG(LS_INFO) << "A " << old_content_a->name; | |
| 1400 LOG(LS_INFO) << "B " << old_content_b->name; | |
| 1401 | |
| 1402 std::string description_info_xml = | |
| 1403 JingleDescriptionInfoXml(content_name_a, content_type); | |
| 1404 initiator->DeliverStanza( | |
| 1405 IqSet("6", kResponder, kInitiator, description_info_xml)); | |
| 1406 responder->SkipUnsentStanza(); | |
| 1407 EXPECT_EQ(1U, initiator->session_remote_description_update_count); | |
| 1408 | |
| 1409 const cricket::SessionDescription* new_session_desc = | |
| 1410 initiator->session->remote_description(); | |
| 1411 const cricket::ContentInfo* new_content_a = | |
| 1412 new_session_desc->GetContentByName(content_name_a); | |
| 1413 const cricket::ContentDescription* new_content_desc_a = | |
| 1414 new_content_a->description; | |
| 1415 const cricket::ContentInfo* new_content_b = | |
| 1416 new_session_desc->GetContentByName(content_name_b); | |
| 1417 const cricket::ContentDescription* new_content_desc_b = | |
| 1418 new_content_b->description; | |
| 1419 EXPECT_TRUE(new_content_desc_a != NULL); | |
| 1420 EXPECT_TRUE(new_content_desc_b != NULL); | |
| 1421 | |
| 1422 // TODO: We used to replace contents from an update, but | |
| 1423 // that no longer works with partial updates. We need to figure out | |
| 1424 // a way to merge patial updates into contents. For now, users of | |
| 1425 // Session should listen to SignalRemoteDescriptionUpdate and handle | |
| 1426 // updates. They should not expect remote_description to be the | |
| 1427 // latest value. | |
| 1428 // See session.cc OnDescriptionInfoMessage. | |
| 1429 | |
| 1430 // EXPECT_NE(old_content_desc_a, new_content_desc_a); | |
| 1431 | |
| 1432 // if (content_name_a != content_name_b) { | |
| 1433 // // If content_name_a != content_name_b, then b's content description | |
| 1434 // // should not have changed since the description-info message only | |
| 1435 // // contained an update for content_name_a. | |
| 1436 // EXPECT_EQ(old_content_desc_b, new_content_desc_b); | |
| 1437 // } | |
| 1438 | |
| 1439 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1440 initiator->ExpectSentStanza( | |
| 1441 IqAck("6", kInitiator, kResponder)); | |
| 1442 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1443 } else { | |
| 1444 responder->SkipUnsentStanza(); | |
| 1445 } | |
| 1446 | |
| 1447 initiator->session->Terminate(); | |
| 1448 initiator->ExpectSentStanza( | |
| 1449 IqSet("7", kInitiator, kResponder, | |
| 1450 TerminateXml(resulting_protocol, | |
| 1451 cricket::STR_TERMINATE_SUCCESS))); | |
| 1452 | |
| 1453 responder->DeliverStanza(initiator->stanza()); | |
| 1454 responder->ExpectSentStanza( | |
| 1455 IqAck("7", kResponder, kInitiator)); | |
| 1456 EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE, | |
| 1457 initiator->session_state()); | |
| 1458 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE, | |
| 1459 responder->session_state()); | |
| 1460 } | |
| 1461 | |
| 1462 // Test an initiate with other content, called "main". | |
| 1463 void TestOtherContent(SignalingProtocol initiator_protocol, | |
| 1464 SignalingProtocol responder_protocol, | |
| 1465 SignalingProtocol resulting_protocol) { | |
| 1466 std::string content_name = "main"; | |
| 1467 std::string content_type = "http://oink.splat/session"; | |
| 1468 std::string content_name_a = content_name; | |
| 1469 std::string channel_name_a = "rtp"; | |
| 1470 std::string content_name_b = content_name; | |
| 1471 std::string channel_name_b = "rtcp"; | |
| 1472 std::string initiate_xml = InitiateXml( | |
| 1473 initiator_protocol, | |
| 1474 content_name_a, content_type); | |
| 1475 std::string transport_info_a_xml = TransportInfo4Xml( | |
| 1476 initiator_protocol, content_name, | |
| 1477 channel_name_a, 0, 1, | |
| 1478 channel_name_b, 2, 3); | |
| 1479 std::string transport_info_b_xml = ""; | |
| 1480 std::string transport_info_reply_a_xml = TransportInfo4Xml( | |
| 1481 resulting_protocol, content_name, | |
| 1482 channel_name_a, 4, 5, | |
| 1483 channel_name_b, 6, 7); | |
| 1484 std::string transport_info_reply_b_xml = ""; | |
| 1485 std::string accept_xml = AcceptXml( | |
| 1486 resulting_protocol, | |
| 1487 content_name_a, content_type); | |
| 1488 | |
| 1489 | |
| 1490 TestSession(initiator_protocol, responder_protocol, resulting_protocol, | |
| 1491 content_type, | |
| 1492 content_type, | |
| 1493 content_name_a, channel_name_a, | |
| 1494 content_name_b, channel_name_b, | |
| 1495 initiate_xml, | |
| 1496 transport_info_a_xml, transport_info_b_xml, | |
| 1497 transport_info_reply_a_xml, transport_info_reply_b_xml, | |
| 1498 accept_xml); | |
| 1499 } | |
| 1500 | |
| 1501 // Test an initiate with audio content. | |
| 1502 void TestAudioContent(SignalingProtocol initiator_protocol, | |
| 1503 SignalingProtocol responder_protocol, | |
| 1504 SignalingProtocol resulting_protocol) { | |
| 1505 std::string gingle_content_type = cricket::NS_GINGLE_AUDIO; | |
| 1506 std::string content_name = cricket::CN_AUDIO; | |
| 1507 std::string content_type = cricket::NS_JINGLE_RTP; | |
| 1508 std::string channel_name_a = "rtp"; | |
| 1509 std::string channel_name_b = "rtcp"; | |
| 1510 std::string initiate_xml = InitiateXml( | |
| 1511 initiator_protocol, | |
| 1512 gingle_content_type, | |
| 1513 content_name, content_type, | |
| 1514 "", ""); | |
| 1515 std::string transport_info_a_xml = TransportInfo4Xml( | |
| 1516 initiator_protocol, content_name, | |
| 1517 channel_name_a, 0, 1, | |
| 1518 channel_name_b, 2, 3); | |
| 1519 std::string transport_info_b_xml = ""; | |
| 1520 std::string transport_info_reply_a_xml = TransportInfo4Xml( | |
| 1521 resulting_protocol, content_name, | |
| 1522 channel_name_a, 4, 5, | |
| 1523 channel_name_b, 6, 7); | |
| 1524 std::string transport_info_reply_b_xml = ""; | |
| 1525 std::string accept_xml = AcceptXml( | |
| 1526 resulting_protocol, | |
| 1527 gingle_content_type, | |
| 1528 content_name, content_type, | |
| 1529 "", ""); | |
| 1530 | |
| 1531 | |
| 1532 TestSession(initiator_protocol, responder_protocol, resulting_protocol, | |
| 1533 gingle_content_type, | |
| 1534 content_type, | |
| 1535 content_name, channel_name_a, | |
| 1536 content_name, channel_name_b, | |
| 1537 initiate_xml, | |
| 1538 transport_info_a_xml, transport_info_b_xml, | |
| 1539 transport_info_reply_a_xml, transport_info_reply_b_xml, | |
| 1540 accept_xml); | |
| 1541 } | |
| 1542 | |
| 1543 // Since media content is "split" into two contents (audio and | |
| 1544 // video), we need to treat it special. | |
| 1545 void TestVideoContents(SignalingProtocol initiator_protocol, | |
| 1546 SignalingProtocol responder_protocol, | |
| 1547 SignalingProtocol resulting_protocol) { | |
| 1548 std::string content_type = cricket::NS_JINGLE_RTP; | |
| 1549 std::string gingle_content_type = cricket::NS_GINGLE_VIDEO; | |
| 1550 std::string content_name_a = cricket::CN_AUDIO; | |
| 1551 std::string channel_name_a = "rtp"; | |
| 1552 std::string content_name_b = cricket::CN_VIDEO; | |
| 1553 std::string channel_name_b = "video_rtp"; | |
| 1554 | |
| 1555 std::string initiate_xml = InitiateXml( | |
| 1556 initiator_protocol, | |
| 1557 gingle_content_type, | |
| 1558 content_name_a, content_type, | |
| 1559 content_name_b, content_type); | |
| 1560 std::string transport_info_a_xml = TransportInfo2Xml( | |
| 1561 initiator_protocol, content_name_a, | |
| 1562 channel_name_a, 0, 1); | |
| 1563 std::string transport_info_b_xml = TransportInfo2Xml( | |
| 1564 initiator_protocol, content_name_b, | |
| 1565 channel_name_b, 2, 3); | |
| 1566 std::string transport_info_reply_a_xml = TransportInfo2Xml( | |
| 1567 resulting_protocol, content_name_a, | |
| 1568 channel_name_a, 4, 5); | |
| 1569 std::string transport_info_reply_b_xml = TransportInfo2Xml( | |
| 1570 resulting_protocol, content_name_b, | |
| 1571 channel_name_b, 6, 7); | |
| 1572 std::string accept_xml = AcceptXml( | |
| 1573 resulting_protocol, | |
| 1574 gingle_content_type, | |
| 1575 content_name_a, content_type, | |
| 1576 content_name_b, content_type); | |
| 1577 | |
| 1578 TestSession(initiator_protocol, responder_protocol, resulting_protocol, | |
| 1579 gingle_content_type, | |
| 1580 content_type, | |
| 1581 content_name_a, channel_name_a, | |
| 1582 content_name_b, channel_name_b, | |
| 1583 initiate_xml, | |
| 1584 transport_info_a_xml, transport_info_b_xml, | |
| 1585 transport_info_reply_a_xml, transport_info_reply_b_xml, | |
| 1586 accept_xml); | |
| 1587 } | |
| 1588 | |
| 1589 void TestBadRedirect(SignalingProtocol protocol) { | |
| 1590 std::string content_name = "main"; | |
| 1591 std::string content_type = "http://oink.splat/session"; | |
| 1592 std::string channel_name_a = "chana"; | |
| 1593 std::string channel_name_b = "chanb"; | |
| 1594 std::string initiate_xml = InitiateXml( | |
| 1595 protocol, content_name, content_type); | |
| 1596 std::string transport_info_xml = TransportInfo4Xml( | |
| 1597 protocol, content_name, | |
| 1598 channel_name_a, 0, 1, | |
| 1599 channel_name_b, 2, 3); | |
| 1600 std::string transport_info_reply_xml = TransportInfo4Xml( | |
| 1601 protocol, content_name, | |
| 1602 channel_name_a, 4, 5, | |
| 1603 channel_name_b, 6, 7); | |
| 1604 std::string accept_xml = AcceptXml( | |
| 1605 protocol, content_name, content_type); | |
| 1606 std::string responder_full = kResponder + "/full"; | |
| 1607 | |
| 1608 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 1609 new TestPortAllocator()); | |
| 1610 int next_message_id = 0; | |
| 1611 | |
| 1612 rtc::scoped_ptr<TestClient> initiator( | |
| 1613 new TestClient(allocator.get(), &next_message_id, | |
| 1614 kInitiator, protocol, | |
| 1615 content_type, | |
| 1616 content_name, channel_name_a, | |
| 1617 content_name, channel_name_b)); | |
| 1618 | |
| 1619 rtc::scoped_ptr<TestClient> responder( | |
| 1620 new TestClient(allocator.get(), &next_message_id, | |
| 1621 responder_full, protocol, | |
| 1622 content_type, | |
| 1623 content_name, channel_name_a, | |
| 1624 content_name, channel_name_b)); | |
| 1625 | |
| 1626 // Create Session and check channels and state. | |
| 1627 initiator->CreateSession(); | |
| 1628 EXPECT_EQ(1U, initiator->session_created_count); | |
| 1629 EXPECT_EQ(kSessionId, initiator->session->id()); | |
| 1630 EXPECT_EQ(initiator->session->local_name(), kInitiator); | |
| 1631 EXPECT_EQ(cricket::BaseSession::STATE_INIT, | |
| 1632 initiator->session_state()); | |
| 1633 | |
| 1634 EXPECT_TRUE(initiator->HasChannel(content_name, 1)); | |
| 1635 EXPECT_TRUE(initiator->HasChannel(content_name, 2)); | |
| 1636 | |
| 1637 // Initiate and expect initiate message sent. | |
| 1638 cricket::SessionDescription* offer = NewTestSessionDescription( | |
| 1639 content_name, content_type); | |
| 1640 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer)); | |
| 1641 EXPECT_EQ(initiator->session->remote_name(), kResponder); | |
| 1642 EXPECT_EQ(initiator->session->local_description(), offer); | |
| 1643 | |
| 1644 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1645 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE, | |
| 1646 initiator->session_state()); | |
| 1647 initiator->ExpectSentStanza( | |
| 1648 IqSet("0", kInitiator, kResponder, initiate_xml)); | |
| 1649 | |
| 1650 // Expect transport-info message from initiator. | |
| 1651 initiator->DeliverAckToLastStanza(); | |
| 1652 initiator->PrepareCandidates(); | |
| 1653 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1654 initiator->ExpectSentStanza( | |
| 1655 IqSet("1", kInitiator, kResponder, transport_info_xml)); | |
| 1656 | |
| 1657 // Send an unauthorized redirect to the initiator and expect it be ignored. | |
| 1658 initiator->blow_up_on_error = false; | |
| 1659 const buzz::XmlElement* initiate_stanza = initiator->stanza(); | |
| 1660 rtc::scoped_ptr<buzz::XmlElement> redirect_stanza( | |
| 1661 buzz::XmlElement::ForStr( | |
| 1662 IqError("ER", kResponder, kInitiator, | |
| 1663 RedirectXml(protocol, initiate_xml, "not@allowed.com")))); | |
| 1664 initiator->session_manager->OnFailedSend( | |
| 1665 initiate_stanza, redirect_stanza.get()); | |
| 1666 EXPECT_EQ(initiator->session->remote_name(), kResponder); | |
| 1667 initiator->blow_up_on_error = true; | |
| 1668 EXPECT_EQ(initiator->error_count, 1); | |
| 1669 } | |
| 1670 | |
| 1671 void TestGoodRedirect(SignalingProtocol protocol) { | |
| 1672 std::string content_name = "main"; | |
| 1673 std::string content_type = "http://oink.splat/session"; | |
| 1674 std::string channel_name_a = "chana"; | |
| 1675 std::string channel_name_b = "chanb"; | |
| 1676 std::string initiate_xml = InitiateXml( | |
| 1677 protocol, content_name, content_type); | |
| 1678 std::string transport_info_xml = TransportInfo4Xml( | |
| 1679 protocol, content_name, | |
| 1680 channel_name_a, 0, 1, | |
| 1681 channel_name_b, 2, 3); | |
| 1682 std::string transport_info_reply_xml = TransportInfo4Xml( | |
| 1683 protocol, content_name, | |
| 1684 channel_name_a, 4, 5, | |
| 1685 channel_name_b, 6, 7); | |
| 1686 std::string accept_xml = AcceptXml( | |
| 1687 protocol, content_name, content_type); | |
| 1688 std::string responder_full = kResponder + "/full"; | |
| 1689 | |
| 1690 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 1691 new TestPortAllocator()); | |
| 1692 int next_message_id = 0; | |
| 1693 | |
| 1694 rtc::scoped_ptr<TestClient> initiator( | |
| 1695 new TestClient(allocator.get(), &next_message_id, | |
| 1696 kInitiator, protocol, | |
| 1697 content_type, | |
| 1698 content_name, channel_name_a, | |
| 1699 content_name, channel_name_b)); | |
| 1700 | |
| 1701 rtc::scoped_ptr<TestClient> responder( | |
| 1702 new TestClient(allocator.get(), &next_message_id, | |
| 1703 responder_full, protocol, | |
| 1704 content_type, | |
| 1705 content_name, channel_name_a, | |
| 1706 content_name, channel_name_b)); | |
| 1707 | |
| 1708 // Create Session and check channels and state. | |
| 1709 initiator->CreateSession(); | |
| 1710 EXPECT_EQ(1U, initiator->session_created_count); | |
| 1711 EXPECT_EQ(kSessionId, initiator->session->id()); | |
| 1712 EXPECT_EQ(initiator->session->local_name(), kInitiator); | |
| 1713 EXPECT_EQ(cricket::BaseSession::STATE_INIT, | |
| 1714 initiator->session_state()); | |
| 1715 | |
| 1716 EXPECT_TRUE(initiator->HasChannel(content_name, 1)); | |
| 1717 EXPECT_TRUE(initiator->HasChannel(content_name, 2)); | |
| 1718 | |
| 1719 // Initiate and expect initiate message sent. | |
| 1720 cricket::SessionDescription* offer = NewTestSessionDescription( | |
| 1721 content_name, content_type); | |
| 1722 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer)); | |
| 1723 EXPECT_EQ(initiator->session->remote_name(), kResponder); | |
| 1724 EXPECT_EQ(initiator->session->local_description(), offer); | |
| 1725 | |
| 1726 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1727 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE, | |
| 1728 initiator->session_state()); | |
| 1729 initiator->ExpectSentStanza( | |
| 1730 IqSet("0", kInitiator, kResponder, initiate_xml)); | |
| 1731 | |
| 1732 // Expect transport-info message from initiator. | |
| 1733 initiator->DeliverAckToLastStanza(); | |
| 1734 initiator->PrepareCandidates(); | |
| 1735 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1736 initiator->ExpectSentStanza( | |
| 1737 IqSet("1", kInitiator, kResponder, transport_info_xml)); | |
| 1738 | |
| 1739 // Send a redirect to the initiator and expect all of the message | |
| 1740 // to be resent. | |
| 1741 const buzz::XmlElement* initiate_stanza = initiator->stanza(); | |
| 1742 rtc::scoped_ptr<buzz::XmlElement> redirect_stanza( | |
| 1743 buzz::XmlElement::ForStr( | |
| 1744 IqError("ER2", kResponder, kInitiator, | |
| 1745 RedirectXml(protocol, initiate_xml, responder_full)))); | |
| 1746 initiator->session_manager->OnFailedSend( | |
| 1747 initiate_stanza, redirect_stanza.get()); | |
| 1748 EXPECT_EQ(initiator->session->remote_name(), responder_full); | |
| 1749 | |
| 1750 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1751 initiator->ExpectSentStanza( | |
| 1752 IqSet("2", kInitiator, responder_full, initiate_xml)); | |
| 1753 initiator->ExpectSentStanza( | |
| 1754 IqSet("3", kInitiator, responder_full, transport_info_xml)); | |
| 1755 | |
| 1756 // Deliver the initiate. Expect ack and session created with | |
| 1757 // transports. | |
| 1758 responder->DeliverStanza( | |
| 1759 IqSet("2", kInitiator, responder_full, initiate_xml)); | |
| 1760 responder->ExpectSentStanza( | |
| 1761 IqAck("2", responder_full, kInitiator)); | |
| 1762 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1763 | |
| 1764 EXPECT_EQ(1U, responder->session_created_count); | |
| 1765 EXPECT_EQ(kSessionId, responder->session->id()); | |
| 1766 EXPECT_EQ(responder->session->local_name(), responder_full); | |
| 1767 EXPECT_EQ(responder->session->remote_name(), kInitiator); | |
| 1768 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE, | |
| 1769 responder->session_state()); | |
| 1770 | |
| 1771 EXPECT_TRUE(responder->HasChannel(content_name, 1)); | |
| 1772 EXPECT_TRUE(responder->HasChannel(content_name, 2)); | |
| 1773 | |
| 1774 // Deliver transport-info and expect ack. | |
| 1775 responder->DeliverStanza( | |
| 1776 IqSet("3", kInitiator, responder_full, transport_info_xml)); | |
| 1777 responder->ExpectSentStanza( | |
| 1778 IqAck("3", responder_full, kInitiator)); | |
| 1779 | |
| 1780 // Expect reply transport-infos sent to new remote JID | |
| 1781 responder->PrepareCandidates(); | |
| 1782 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout); | |
| 1783 responder->ExpectSentStanza( | |
| 1784 IqSet("4", responder_full, kInitiator, transport_info_reply_xml)); | |
| 1785 | |
| 1786 initiator->DeliverStanza(responder->stanza()); | |
| 1787 initiator->ExpectSentStanza( | |
| 1788 IqAck("4", kInitiator, responder_full)); | |
| 1789 | |
| 1790 // The channels should be able to become writable at this point. This | |
| 1791 // requires pinging, so it may take a little while. | |
| 1792 EXPECT_TRUE_WAIT(initiator->chan_a->writable() && | |
| 1793 initiator->chan_a->readable(), kEventTimeout); | |
| 1794 EXPECT_TRUE_WAIT(initiator->chan_b->writable() && | |
| 1795 initiator->chan_b->readable(), kEventTimeout); | |
| 1796 EXPECT_TRUE_WAIT(responder->chan_a->writable() && | |
| 1797 responder->chan_a->readable(), kEventTimeout); | |
| 1798 EXPECT_TRUE_WAIT(responder->chan_b->writable() && | |
| 1799 responder->chan_b->readable(), kEventTimeout); | |
| 1800 | |
| 1801 // Accept the session and expect accept stanza. | |
| 1802 cricket::SessionDescription* answer = NewTestSessionDescription( | |
| 1803 content_name, content_type); | |
| 1804 EXPECT_TRUE(responder->session->Accept(answer)); | |
| 1805 EXPECT_EQ(responder->session->local_description(), answer); | |
| 1806 | |
| 1807 responder->ExpectSentStanza( | |
| 1808 IqSet("5", responder_full, kInitiator, accept_xml)); | |
| 1809 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1810 | |
| 1811 // Deliver the accept message and expect an ack. | |
| 1812 initiator->DeliverStanza(responder->stanza()); | |
| 1813 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1814 initiator->ExpectSentStanza( | |
| 1815 IqAck("5", kInitiator, responder_full)); | |
| 1816 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1817 | |
| 1818 // Both sessions should be in progress and have functioning | |
| 1819 // channels. | |
| 1820 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS, | |
| 1821 initiator->session_state(), kEventTimeout); | |
| 1822 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS, | |
| 1823 responder->session_state(), kEventTimeout); | |
| 1824 TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(), | |
| 1825 responder->chan_a.get(), responder->chan_b.get()); | |
| 1826 } | |
| 1827 | |
| 1828 void TestCandidatesInInitiateAndAccept(const std::string& test_name) { | |
| 1829 std::string content_name = "main"; | |
| 1830 std::string content_type = "http://oink.splat/session"; | |
| 1831 std::string channel_name_a = "rtp"; | |
| 1832 std::string channel_name_b = "rtcp"; | |
| 1833 cricket::SignalingProtocol protocol = PROTOCOL_JINGLE; | |
| 1834 | |
| 1835 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 1836 new TestPortAllocator()); | |
| 1837 int next_message_id = 0; | |
| 1838 | |
| 1839 rtc::scoped_ptr<TestClient> initiator( | |
| 1840 new TestClient(allocator.get(), &next_message_id, | |
| 1841 kInitiator, protocol, | |
| 1842 content_type, | |
| 1843 content_name, channel_name_a, | |
| 1844 content_name, channel_name_b)); | |
| 1845 | |
| 1846 rtc::scoped_ptr<TestClient> responder( | |
| 1847 new TestClient(allocator.get(), &next_message_id, | |
| 1848 kResponder, protocol, | |
| 1849 content_type, | |
| 1850 content_name, channel_name_a, | |
| 1851 content_name, channel_name_b)); | |
| 1852 | |
| 1853 // Create Session and check channels and state. | |
| 1854 initiator->CreateSession(); | |
| 1855 EXPECT_TRUE(initiator->HasTransport(content_name)); | |
| 1856 EXPECT_TRUE(initiator->HasChannel(content_name, 1)); | |
| 1857 EXPECT_TRUE(initiator->HasTransport(content_name)); | |
| 1858 EXPECT_TRUE(initiator->HasChannel(content_name, 2)); | |
| 1859 | |
| 1860 // Initiate and expect initiate message sent. | |
| 1861 cricket::SessionDescription* offer = NewTestSessionDescription( | |
| 1862 content_name, content_type); | |
| 1863 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer)); | |
| 1864 | |
| 1865 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1866 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE, | |
| 1867 initiator->session_state()); | |
| 1868 initiator->ExpectSentStanza( | |
| 1869 IqSet("0", kInitiator, kResponder, | |
| 1870 InitiateXml(protocol, content_name, content_type))); | |
| 1871 | |
| 1872 // Fake the delivery the initiate and candidates together. | |
| 1873 responder->DeliverStanza( | |
| 1874 IqSet("A", kInitiator, kResponder, | |
| 1875 JingleInitiateActionXml( | |
| 1876 JingleContentXml( | |
| 1877 content_name, content_type, kTransportType, | |
| 1878 P2pCandidateXml(channel_name_a, 0) + | |
| 1879 P2pCandidateXml(channel_name_a, 1) + | |
| 1880 P2pCandidateXml(channel_name_b, 2) + | |
| 1881 P2pCandidateXml(channel_name_b, 3))))); | |
| 1882 responder->ExpectSentStanza( | |
| 1883 IqAck("A", kResponder, kInitiator)); | |
| 1884 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1885 | |
| 1886 EXPECT_EQ(1U, responder->session_created_count); | |
| 1887 EXPECT_EQ(kSessionId, responder->session->id()); | |
| 1888 EXPECT_EQ(responder->session->local_name(), kResponder); | |
| 1889 EXPECT_EQ(responder->session->remote_name(), kInitiator); | |
| 1890 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE, | |
| 1891 responder->session_state()); | |
| 1892 | |
| 1893 EXPECT_TRUE(responder->HasTransport(content_name)); | |
| 1894 EXPECT_TRUE(responder->HasChannel(content_name, 1)); | |
| 1895 EXPECT_TRUE(responder->HasTransport(content_name)); | |
| 1896 EXPECT_TRUE(responder->HasChannel(content_name, 2)); | |
| 1897 | |
| 1898 // Expect transport-info message from initiator. | |
| 1899 // But don't send candidates until initiate ack is received. | |
| 1900 initiator->DeliverAckToLastStanza(); | |
| 1901 initiator->PrepareCandidates(); | |
| 1902 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1903 initiator->ExpectSentStanza( | |
| 1904 IqSet("1", kInitiator, kResponder, | |
| 1905 TransportInfo4Xml(protocol, content_name, | |
| 1906 channel_name_a, 0, 1, | |
| 1907 channel_name_b, 2, 3))); | |
| 1908 | |
| 1909 responder->PrepareCandidates(); | |
| 1910 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout); | |
| 1911 responder->ExpectSentStanza( | |
| 1912 IqSet("2", kResponder, kInitiator, | |
| 1913 TransportInfo4Xml(protocol, content_name, | |
| 1914 channel_name_a, 4, 5, | |
| 1915 channel_name_b, 6, 7))); | |
| 1916 | |
| 1917 // Accept the session and expect accept stanza. | |
| 1918 cricket::SessionDescription* answer = NewTestSessionDescription( | |
| 1919 content_name, content_type); | |
| 1920 EXPECT_TRUE(responder->session->Accept(answer)); | |
| 1921 | |
| 1922 responder->ExpectSentStanza( | |
| 1923 IqSet("3", kResponder, kInitiator, | |
| 1924 AcceptXml(protocol, content_name, content_type))); | |
| 1925 EXPECT_EQ(0U, responder->sent_stanza_count()); | |
| 1926 | |
| 1927 // Fake the delivery the accept and candidates together. | |
| 1928 initiator->DeliverStanza( | |
| 1929 IqSet("B", kResponder, kInitiator, | |
| 1930 JingleActionXml("session-accept", | |
| 1931 JingleContentXml( | |
| 1932 content_name, content_type, kTransportType, | |
| 1933 P2pCandidateXml(channel_name_a, 4) + | |
| 1934 P2pCandidateXml(channel_name_a, 5) + | |
| 1935 P2pCandidateXml(channel_name_b, 6) + | |
| 1936 P2pCandidateXml(channel_name_b, 7))))); | |
| 1937 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout); | |
| 1938 initiator->ExpectSentStanza( | |
| 1939 IqAck("B", kInitiator, kResponder)); | |
| 1940 EXPECT_EQ(0U, initiator->sent_stanza_count()); | |
| 1941 | |
| 1942 // The channels should be able to become writable at this point. This | |
| 1943 // requires pinging, so it may take a little while. | |
| 1944 EXPECT_TRUE_WAIT(initiator->chan_a->writable() && | |
| 1945 initiator->chan_a->readable(), kEventTimeout); | |
| 1946 EXPECT_TRUE_WAIT(initiator->chan_b->writable() && | |
| 1947 initiator->chan_b->readable(), kEventTimeout); | |
| 1948 EXPECT_TRUE_WAIT(responder->chan_a->writable() && | |
| 1949 responder->chan_a->readable(), kEventTimeout); | |
| 1950 EXPECT_TRUE_WAIT(responder->chan_b->writable() && | |
| 1951 responder->chan_b->readable(), kEventTimeout); | |
| 1952 | |
| 1953 | |
| 1954 // Both sessions should be in progress and have functioning | |
| 1955 // channels. | |
| 1956 EXPECT_EQ(protocol, initiator->session->current_protocol()); | |
| 1957 EXPECT_EQ(protocol, responder->session->current_protocol()); | |
| 1958 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS, | |
| 1959 initiator->session_state(), kEventTimeout); | |
| 1960 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS, | |
| 1961 responder->session_state(), kEventTimeout); | |
| 1962 TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(), | |
| 1963 responder->chan_a.get(), responder->chan_b.get()); | |
| 1964 } | |
| 1965 | |
| 1966 // Tests that when an initiator terminates right after initiate, | |
| 1967 // everything behaves correctly. | |
| 1968 void TestEarlyTerminationFromInitiator(SignalingProtocol protocol) { | |
| 1969 std::string content_name = "main"; | |
| 1970 std::string content_type = "http://oink.splat/session"; | |
| 1971 | |
| 1972 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 1973 new TestPortAllocator()); | |
| 1974 int next_message_id = 0; | |
| 1975 | |
| 1976 rtc::scoped_ptr<TestClient> initiator( | |
| 1977 new TestClient(allocator.get(), &next_message_id, | |
| 1978 kInitiator, protocol, | |
| 1979 content_type, | |
| 1980 content_name, "a", | |
| 1981 content_name, "b")); | |
| 1982 | |
| 1983 rtc::scoped_ptr<TestClient> responder( | |
| 1984 new TestClient(allocator.get(), &next_message_id, | |
| 1985 kResponder, protocol, | |
| 1986 content_type, | |
| 1987 content_name, "a", | |
| 1988 content_name, "b")); | |
| 1989 | |
| 1990 // Send initiate | |
| 1991 initiator->CreateSession(); | |
| 1992 EXPECT_TRUE(initiator->session->Initiate( | |
| 1993 kResponder, NewTestSessionDescription(content_name, content_type))); | |
| 1994 initiator->ExpectSentStanza( | |
| 1995 IqSet("0", kInitiator, kResponder, | |
| 1996 InitiateXml(protocol, content_name, content_type))); | |
| 1997 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE, | |
| 1998 initiator->session_state()); | |
| 1999 | |
| 2000 responder->DeliverStanza(initiator->stanza()); | |
| 2001 responder->ExpectSentStanza( | |
| 2002 IqAck("0", kResponder, kInitiator)); | |
| 2003 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE, | |
| 2004 responder->session_state()); | |
| 2005 | |
| 2006 initiator->session->TerminateWithReason(cricket::STR_TERMINATE_ERROR); | |
| 2007 initiator->ExpectSentStanza( | |
| 2008 IqSet("1", kInitiator, kResponder, | |
| 2009 TerminateXml(protocol, cricket::STR_TERMINATE_ERROR))); | |
| 2010 EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE, | |
| 2011 initiator->session_state()); | |
| 2012 | |
| 2013 responder->DeliverStanza(initiator->stanza()); | |
| 2014 responder->ExpectSentStanza( | |
| 2015 IqAck("1", kResponder, kInitiator)); | |
| 2016 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE, | |
| 2017 responder->session_state()); | |
| 2018 } | |
| 2019 | |
| 2020 // Tests that when the responder rejects, everything behaves | |
| 2021 // correctly. | |
| 2022 void TestRejection(SignalingProtocol protocol) { | |
| 2023 std::string content_name = "main"; | |
| 2024 std::string content_type = "http://oink.splat/session"; | |
| 2025 | |
| 2026 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 2027 new TestPortAllocator()); | |
| 2028 int next_message_id = 0; | |
| 2029 | |
| 2030 rtc::scoped_ptr<TestClient> initiator( | |
| 2031 new TestClient(allocator.get(), &next_message_id, | |
| 2032 kInitiator, protocol, | |
| 2033 content_type, | |
| 2034 content_name, "a", | |
| 2035 content_name, "b")); | |
| 2036 | |
| 2037 // Send initiate | |
| 2038 initiator->CreateSession(); | |
| 2039 EXPECT_TRUE(initiator->session->Initiate( | |
| 2040 kResponder, NewTestSessionDescription(content_name, content_type))); | |
| 2041 initiator->ExpectSentStanza( | |
| 2042 IqSet("0", kInitiator, kResponder, | |
| 2043 InitiateXml(protocol, content_name, content_type))); | |
| 2044 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE, | |
| 2045 initiator->session_state()); | |
| 2046 | |
| 2047 initiator->DeliverStanza( | |
| 2048 IqSet("1", kResponder, kInitiator, | |
| 2049 RejectXml(protocol, cricket::STR_TERMINATE_ERROR))); | |
| 2050 initiator->ExpectSentStanza( | |
| 2051 IqAck("1", kInitiator, kResponder)); | |
| 2052 if (protocol == PROTOCOL_JINGLE) { | |
| 2053 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE, | |
| 2054 initiator->session_state()); | |
| 2055 } else { | |
| 2056 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDREJECT, | |
| 2057 initiator->session_state()); | |
| 2058 } | |
| 2059 } | |
| 2060 | |
| 2061 void TestTransportMux() { | |
| 2062 SignalingProtocol initiator_protocol = PROTOCOL_JINGLE; | |
| 2063 SignalingProtocol responder_protocol = PROTOCOL_JINGLE; | |
| 2064 SignalingProtocol resulting_protocol = PROTOCOL_JINGLE; | |
| 2065 std::string content_type = cricket::NS_JINGLE_RTP; | |
| 2066 std::string gingle_content_type = cricket::NS_GINGLE_VIDEO; | |
| 2067 std::string content_name_a = cricket::CN_AUDIO; | |
| 2068 std::string channel_name_a = "rtp"; | |
| 2069 std::string content_name_b = cricket::CN_VIDEO; | |
| 2070 std::string channel_name_b = "video_rtp"; | |
| 2071 | |
| 2072 std::string initiate_xml = InitiateXml( | |
| 2073 initiator_protocol, | |
| 2074 gingle_content_type, | |
| 2075 content_name_a, content_type, | |
| 2076 content_name_b, content_type, true); | |
| 2077 std::string transport_info_a_xml = TransportInfo2Xml( | |
| 2078 initiator_protocol, content_name_a, | |
| 2079 channel_name_a, 0, 1); | |
| 2080 std::string transport_info_b_xml = TransportInfo2Xml( | |
| 2081 initiator_protocol, content_name_b, | |
| 2082 channel_name_b, 2, 3); | |
| 2083 std::string transport_info_reply_a_xml = TransportInfo2Xml( | |
| 2084 resulting_protocol, content_name_a, | |
| 2085 channel_name_a, 4, 5); | |
| 2086 std::string transport_info_reply_b_xml = TransportInfo2Xml( | |
| 2087 resulting_protocol, content_name_b, | |
| 2088 channel_name_b, 6, 7); | |
| 2089 std::string accept_xml = AcceptXml( | |
| 2090 resulting_protocol, | |
| 2091 gingle_content_type, | |
| 2092 content_name_a, content_type, | |
| 2093 content_name_b, content_type, true); | |
| 2094 | |
| 2095 TestSession(initiator_protocol, responder_protocol, resulting_protocol, | |
| 2096 gingle_content_type, | |
| 2097 content_type, | |
| 2098 content_name_a, channel_name_a, | |
| 2099 content_name_b, channel_name_b, | |
| 2100 initiate_xml, | |
| 2101 transport_info_a_xml, transport_info_b_xml, | |
| 2102 transport_info_reply_a_xml, transport_info_reply_b_xml, | |
| 2103 accept_xml, | |
| 2104 true); | |
| 2105 } | |
| 2106 | |
| 2107 void TestSendDescriptionInfo() { | |
| 2108 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 2109 new TestPortAllocator()); | |
| 2110 int next_message_id = 0; | |
| 2111 | |
| 2112 std::string content_name = "content-name"; | |
| 2113 std::string content_type = "content-type"; | |
| 2114 rtc::scoped_ptr<TestClient> initiator( | |
| 2115 new TestClient(allocator.get(), &next_message_id, | |
| 2116 kInitiator, PROTOCOL_JINGLE, | |
| 2117 content_type, | |
| 2118 content_name, "", | |
| 2119 "", "")); | |
| 2120 | |
| 2121 initiator->CreateSession(); | |
| 2122 cricket::SessionDescription* offer = NewTestSessionDescription( | |
| 2123 content_name, content_type); | |
| 2124 std::string initiate_xml = InitiateXml( | |
| 2125 PROTOCOL_JINGLE, content_name, content_type); | |
| 2126 | |
| 2127 cricket::ContentInfos contents; | |
| 2128 TestContentDescription content(content_type, content_type); | |
| 2129 contents.push_back( | |
| 2130 cricket::ContentInfo(content_name, content_type, &content)); | |
| 2131 std::string description_info_xml = JingleDescriptionInfoXml( | |
| 2132 content_name, content_type); | |
| 2133 | |
| 2134 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer)); | |
| 2135 initiator->ExpectSentStanza( | |
| 2136 IqSet("0", kInitiator, kResponder, initiate_xml)); | |
| 2137 | |
| 2138 EXPECT_TRUE(initiator->session->SendDescriptionInfoMessage(contents)); | |
| 2139 initiator->ExpectSentStanza( | |
| 2140 IqSet("1", kInitiator, kResponder, description_info_xml)); | |
| 2141 } | |
| 2142 | |
| 2143 void DoTestSignalNewDescription( | |
| 2144 TestClient* client, | |
| 2145 cricket::BaseSession::State state, | |
| 2146 cricket::ContentAction expected_content_action, | |
| 2147 cricket::ContentSource expected_content_source) { | |
| 2148 // Clean up before the new test. | |
| 2149 client->new_local_description = false; | |
| 2150 client->new_remote_description = false; | |
| 2151 | |
| 2152 client->SetSessionState(state); | |
| 2153 EXPECT_EQ((expected_content_source == cricket::CS_LOCAL), | |
| 2154 client->new_local_description); | |
| 2155 EXPECT_EQ((expected_content_source == cricket::CS_REMOTE), | |
| 2156 client->new_remote_description); | |
| 2157 EXPECT_EQ(expected_content_action, client->last_content_action); | |
| 2158 EXPECT_EQ(expected_content_source, client->last_content_source); | |
| 2159 } | |
| 2160 | |
| 2161 void TestCallerSignalNewDescription() { | |
| 2162 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 2163 new TestPortAllocator()); | |
| 2164 int next_message_id = 0; | |
| 2165 | |
| 2166 std::string content_name = "content-name"; | |
| 2167 std::string content_type = "content-type"; | |
| 2168 rtc::scoped_ptr<TestClient> initiator( | |
| 2169 new TestClient(allocator.get(), &next_message_id, | |
| 2170 kInitiator, PROTOCOL_JINGLE, | |
| 2171 content_type, | |
| 2172 content_name, "", | |
| 2173 "", "")); | |
| 2174 | |
| 2175 initiator->CreateSession(); | |
| 2176 | |
| 2177 // send offer -> send update offer -> | |
| 2178 // receive pr answer -> receive update pr answer -> | |
| 2179 // receive answer | |
| 2180 DoTestSignalNewDescription( | |
| 2181 initiator.get(), cricket::BaseSession::STATE_SENTINITIATE, | |
| 2182 cricket::CA_OFFER, cricket::CS_LOCAL); | |
| 2183 | |
| 2184 DoTestSignalNewDescription( | |
| 2185 initiator.get(), cricket::BaseSession::STATE_SENTINITIATE, | |
| 2186 cricket::CA_OFFER, cricket::CS_LOCAL); | |
| 2187 | |
| 2188 DoTestSignalNewDescription( | |
| 2189 initiator.get(), cricket::BaseSession::STATE_RECEIVEDPRACCEPT, | |
| 2190 cricket::CA_PRANSWER, cricket::CS_REMOTE); | |
| 2191 | |
| 2192 DoTestSignalNewDescription( | |
| 2193 initiator.get(), cricket::BaseSession::STATE_RECEIVEDPRACCEPT, | |
| 2194 cricket::CA_PRANSWER, cricket::CS_REMOTE); | |
| 2195 | |
| 2196 DoTestSignalNewDescription( | |
| 2197 initiator.get(), cricket::BaseSession::STATE_RECEIVEDACCEPT, | |
| 2198 cricket::CA_ANSWER, cricket::CS_REMOTE); | |
| 2199 } | |
| 2200 | |
| 2201 void TestCalleeSignalNewDescription() { | |
| 2202 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 2203 new TestPortAllocator()); | |
| 2204 int next_message_id = 0; | |
| 2205 | |
| 2206 std::string content_name = "content-name"; | |
| 2207 std::string content_type = "content-type"; | |
| 2208 rtc::scoped_ptr<TestClient> initiator( | |
| 2209 new TestClient(allocator.get(), &next_message_id, | |
| 2210 kInitiator, PROTOCOL_JINGLE, | |
| 2211 content_type, | |
| 2212 content_name, "", | |
| 2213 "", "")); | |
| 2214 | |
| 2215 initiator->CreateSession(); | |
| 2216 | |
| 2217 // receive offer -> receive update offer -> | |
| 2218 // send pr answer -> send update pr answer -> | |
| 2219 // send answer | |
| 2220 DoTestSignalNewDescription( | |
| 2221 initiator.get(), cricket::BaseSession::STATE_RECEIVEDINITIATE, | |
| 2222 cricket::CA_OFFER, cricket::CS_REMOTE); | |
| 2223 | |
| 2224 DoTestSignalNewDescription( | |
| 2225 initiator.get(), cricket::BaseSession::STATE_RECEIVEDINITIATE, | |
| 2226 cricket::CA_OFFER, cricket::CS_REMOTE); | |
| 2227 | |
| 2228 DoTestSignalNewDescription( | |
| 2229 initiator.get(), cricket::BaseSession::STATE_SENTPRACCEPT, | |
| 2230 cricket::CA_PRANSWER, cricket::CS_LOCAL); | |
| 2231 | |
| 2232 DoTestSignalNewDescription( | |
| 2233 initiator.get(), cricket::BaseSession::STATE_SENTPRACCEPT, | |
| 2234 cricket::CA_PRANSWER, cricket::CS_LOCAL); | |
| 2235 | |
| 2236 DoTestSignalNewDescription( | |
| 2237 initiator.get(), cricket::BaseSession::STATE_SENTACCEPT, | |
| 2238 cricket::CA_ANSWER, cricket::CS_LOCAL); | |
| 2239 } | |
| 2240 | |
| 2241 void TestGetTransportStats() { | |
| 2242 rtc::scoped_ptr<cricket::PortAllocator> allocator( | |
| 2243 new TestPortAllocator()); | |
| 2244 int next_message_id = 0; | |
| 2245 | |
| 2246 std::string content_name = "content-name"; | |
| 2247 std::string content_type = "content-type"; | |
| 2248 rtc::scoped_ptr<TestClient> initiator( | |
| 2249 new TestClient(allocator.get(), &next_message_id, | |
| 2250 kInitiator, PROTOCOL_JINGLE, | |
| 2251 content_type, | |
| 2252 content_name, "", | |
| 2253 "", "")); | |
| 2254 initiator->CreateSession(); | |
| 2255 | |
| 2256 cricket::SessionStats stats; | |
| 2257 EXPECT_TRUE(initiator->session->GetStats(&stats)); | |
| 2258 // At initiation, there are 2 transports. | |
| 2259 EXPECT_EQ(2ul, stats.proxy_to_transport.size()); | |
| 2260 EXPECT_EQ(2ul, stats.transport_stats.size()); | |
| 2261 } | |
| 2262 }; | |
| 2263 | |
| 2264 // For each of these, "X => Y = Z" means "if a client with protocol X | |
| 2265 // initiates to a client with protocol Y, they end up speaking protocol Z. | |
| 2266 | |
| 2267 // Gingle => Gingle = Gingle (with other content) | |
| 2268 TEST_F(SessionTest, GingleToGingleOtherContent) { | |
| 2269 TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE); | |
| 2270 } | |
| 2271 | |
| 2272 // Gingle => Gingle = Gingle (with audio content) | |
| 2273 TEST_F(SessionTest, GingleToGingleAudioContent) { | |
| 2274 TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE); | |
| 2275 } | |
| 2276 | |
| 2277 // Gingle => Gingle = Gingle (with video contents) | |
| 2278 TEST_F(SessionTest, GingleToGingleVideoContents) { | |
| 2279 TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE); | |
| 2280 } | |
| 2281 | |
| 2282 // Jingle => Jingle = Jingle (with other content) | |
| 2283 TEST_F(SessionTest, JingleToJingleOtherContent) { | |
| 2284 TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE); | |
| 2285 } | |
| 2286 | |
| 2287 // Jingle => Jingle = Jingle (with audio content) | |
| 2288 TEST_F(SessionTest, JingleToJingleAudioContent) { | |
| 2289 TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE); | |
| 2290 } | |
| 2291 | |
| 2292 // Jingle => Jingle = Jingle (with video contents) | |
| 2293 TEST_F(SessionTest, JingleToJingleVideoContents) { | |
| 2294 TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE); | |
| 2295 } | |
| 2296 | |
| 2297 // Hybrid => Hybrid = Jingle (with other content) | |
| 2298 TEST_F(SessionTest, HybridToHybridOtherContent) { | |
| 2299 TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE); | |
| 2300 } | |
| 2301 | |
| 2302 // Hybrid => Hybrid = Jingle (with audio content) | |
| 2303 TEST_F(SessionTest, HybridToHybridAudioContent) { | |
| 2304 TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE); | |
| 2305 } | |
| 2306 | |
| 2307 // Hybrid => Hybrid = Jingle (with video contents) | |
| 2308 TEST_F(SessionTest, HybridToHybridVideoContents) { | |
| 2309 TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE); | |
| 2310 } | |
| 2311 | |
| 2312 // Gingle => Hybrid = Gingle (with other content) | |
| 2313 TEST_F(SessionTest, GingleToHybridOtherContent) { | |
| 2314 TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE); | |
| 2315 } | |
| 2316 | |
| 2317 // Gingle => Hybrid = Gingle (with audio content) | |
| 2318 TEST_F(SessionTest, GingleToHybridAudioContent) { | |
| 2319 TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE); | |
| 2320 } | |
| 2321 | |
| 2322 // Gingle => Hybrid = Gingle (with video contents) | |
| 2323 TEST_F(SessionTest, GingleToHybridVideoContents) { | |
| 2324 TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE); | |
| 2325 } | |
| 2326 | |
| 2327 // Jingle => Hybrid = Jingle (with other content) | |
| 2328 TEST_F(SessionTest, JingleToHybridOtherContent) { | |
| 2329 TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE); | |
| 2330 } | |
| 2331 | |
| 2332 // Jingle => Hybrid = Jingle (with audio content) | |
| 2333 TEST_F(SessionTest, JingleToHybridAudioContent) { | |
| 2334 TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE); | |
| 2335 } | |
| 2336 | |
| 2337 // Jingle => Hybrid = Jingle (with video contents) | |
| 2338 TEST_F(SessionTest, JingleToHybridVideoContents) { | |
| 2339 TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE); | |
| 2340 } | |
| 2341 | |
| 2342 // Hybrid => Gingle = Gingle (with other content) | |
| 2343 TEST_F(SessionTest, HybridToGingleOtherContent) { | |
| 2344 TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE); | |
| 2345 } | |
| 2346 | |
| 2347 // Hybrid => Gingle = Gingle (with audio content) | |
| 2348 TEST_F(SessionTest, HybridToGingleAudioContent) { | |
| 2349 TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE); | |
| 2350 } | |
| 2351 | |
| 2352 // Hybrid => Gingle = Gingle (with video contents) | |
| 2353 TEST_F(SessionTest, HybridToGingleVideoContents) { | |
| 2354 TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE); | |
| 2355 } | |
| 2356 | |
| 2357 // Hybrid => Jingle = Jingle (with other content) | |
| 2358 TEST_F(SessionTest, HybridToJingleOtherContent) { | |
| 2359 TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE); | |
| 2360 } | |
| 2361 | |
| 2362 // Hybrid => Jingle = Jingle (with audio content) | |
| 2363 TEST_F(SessionTest, HybridToJingleAudioContent) { | |
| 2364 TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE); | |
| 2365 } | |
| 2366 | |
| 2367 // Hybrid => Jingle = Jingle (with video contents) | |
| 2368 TEST_F(SessionTest, HybridToJingleVideoContents) { | |
| 2369 TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE); | |
| 2370 } | |
| 2371 | |
| 2372 TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) { | |
| 2373 TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE); | |
| 2374 } | |
| 2375 | |
| 2376 TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) { | |
| 2377 TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE); | |
| 2378 } | |
| 2379 | |
| 2380 TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) { | |
| 2381 TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID); | |
| 2382 } | |
| 2383 | |
| 2384 TEST_F(SessionTest, GingleRejection) { | |
| 2385 TestRejection(PROTOCOL_GINGLE); | |
| 2386 } | |
| 2387 | |
| 2388 TEST_F(SessionTest, JingleRejection) { | |
| 2389 TestRejection(PROTOCOL_JINGLE); | |
| 2390 } | |
| 2391 | |
| 2392 TEST_F(SessionTest, GingleGoodRedirect) { | |
| 2393 TestGoodRedirect(PROTOCOL_GINGLE); | |
| 2394 } | |
| 2395 | |
| 2396 TEST_F(SessionTest, JingleGoodRedirect) { | |
| 2397 TestGoodRedirect(PROTOCOL_JINGLE); | |
| 2398 } | |
| 2399 | |
| 2400 TEST_F(SessionTest, GingleBadRedirect) { | |
| 2401 TestBadRedirect(PROTOCOL_GINGLE); | |
| 2402 } | |
| 2403 | |
| 2404 TEST_F(SessionTest, JingleBadRedirect) { | |
| 2405 TestBadRedirect(PROTOCOL_JINGLE); | |
| 2406 } | |
| 2407 | |
| 2408 TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) { | |
| 2409 TestCandidatesInInitiateAndAccept("Candidates in initiate/accept"); | |
| 2410 } | |
| 2411 | |
| 2412 TEST_F(SessionTest, TestTransportMux) { | |
| 2413 TestTransportMux(); | |
| 2414 } | |
| 2415 | |
| 2416 TEST_F(SessionTest, TestSendDescriptionInfo) { | |
| 2417 TestSendDescriptionInfo(); | |
| 2418 } | |
| 2419 | |
| 2420 TEST_F(SessionTest, TestCallerSignalNewDescription) { | |
| 2421 TestCallerSignalNewDescription(); | |
| 2422 } | |
| 2423 | |
| 2424 TEST_F(SessionTest, TestCalleeSignalNewDescription) { | |
| 2425 TestCalleeSignalNewDescription(); | |
| 2426 } | |
| 2427 | |
| 2428 TEST_F(SessionTest, TestGetTransportStats) { | |
| 2429 TestGetTransportStats(); | |
| 2430 } | |
| OLD | NEW |