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