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