3
* Copyright 2004 Google Inc.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
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.
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.
33
#include "talk/base/basicpacketsocketfactory.h"
34
#include "talk/base/common.h"
35
#include "talk/base/gunit.h"
36
#include "talk/base/helpers.h"
37
#include "talk/base/host.h"
38
#include "talk/base/logging.h"
39
#include "talk/base/natserver.h"
40
#include "talk/base/natsocketfactory.h"
41
#include "talk/base/stringencode.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"
58
using cricket::SignalingProtocol;
59
using cricket::PROTOCOL_HYBRID;
60
using cricket::PROTOCOL_JINGLE;
61
using cricket::PROTOCOL_GINGLE;
63
static const std::string kInitiator = "init@init.com";
64
static const std::string kResponder = "resp@resp.com";
65
// Expected from test random number generator.
66
static const std::string kSessionId = "2154761789";
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";
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;
75
static const int kNumPorts = 2;
76
static const int kPort0 = 28653;
77
static const int kPortStep = 5;
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;
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;
92
int GetPort(int port_index) {
93
return kPort0 + (port_index * kPortStep);
96
std::string GetPortString(int port_index) {
97
return talk_base::ToString(GetPort(port_index));
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]);
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]);
110
std::string IqAck(const std::string& id,
111
const std::string& from,
112
const std::string& to) {
117
" from=\"" + from + "\""
118
" xmlns:cli=\"jabber:client\""
122
std::string IqSet(const std::string& id,
123
const std::string& from,
124
const std::string& to,
125
const std::string& content) {
129
" from=\"" + from + "\""
131
" xmlns:cli=\"jabber:client\""
137
std::string IqError(const std::string& id,
138
const std::string& from,
139
const std::string& to,
140
const std::string& content) {
144
" from=\"" + from + "\""
146
" xmlns:cli=\"jabber:client\""
152
std::string GingleSessionXml(const std::string& type,
153
const std::string& content) {
155
" xmlns=\"http://www.google.com/session\""
156
" type=\"" + type + "\""
157
" id=\"" + kSessionId + "\""
158
" initiator=\"" + kInitiator + "\""
164
std::string GingleDescriptionXml(const std::string& content_type) {
165
return "<description"
166
" xmlns=\"" + content_type + "\""
170
std::string P2pCandidateXml(const std::string& name, int port_index) {
172
" name=\"" + name + "\""
173
" address=\"127.0.0.1\""
174
" port=\"" + GetPortString(port_index) + "\""
176
" username=\"" + GetUsername(port_index) + "\""
179
" password=\"" + GetPassword(port_index) + "\""
181
" network=\"network\""
185
std::string JingleActionXml(const std::string& action,
186
const std::string& content) {
188
" xmlns=\"urn:xmpp:jingle:1\""
189
" action=\"" + action + "\""
190
" sid=\"" + kSessionId + "\""
196
std::string JingleInitiateActionXml(const std::string& content) {
198
" xmlns=\"urn:xmpp:jingle:1\""
199
" action=\"session-initiate\""
200
" sid=\"" + kSessionId + "\""
201
" initiator=\"" + kInitiator + "\""
207
std::string JingleGroupInfoXml(const std::string& content_name_a,
208
const std::string& content_name_b) {
209
std::string group_info = "<jin:group"
211
" xmlns:jin=\"google:jingle\""
213
if (!content_name_a.empty())
214
group_info += "<content name=\"" + content_name_a + "\""
216
if (!content_name_b.empty())
217
group_info += "<content name=\"" + content_name_b + "\""
219
group_info += "</jin:group>";
224
std::string JingleEmptyContentXml(const std::string& content_name,
225
const std::string& content_type,
226
const std::string& transport_type) {
228
" name=\"" + content_name + "\""
229
" creator=\"initiator\""
232
" xmlns=\"" + content_type + "\""
235
" xmlns=\"" + transport_type + "\""
240
std::string JingleContentXml(const std::string& content_name,
241
const std::string& content_type,
242
const std::string& transport_type,
243
const std::string& transport_main) {
244
std::string transport = transport_type.empty() ? "" :
246
" xmlns=\"" + transport_type + "\""
252
" name=\"" + content_name + "\""
253
" creator=\"initiator\""
256
" xmlns=\"" + content_type + "\""
262
std::string JingleTransportContentXml(const std::string& content_name,
263
const std::string& transport_type,
264
const std::string& content) {
266
" name=\"" + content_name + "\""
267
" creator=\"initiator\""
270
" xmlns=\"" + transport_type + "\""
277
std::string GingleInitiateXml(const std::string& content_type) {
278
return GingleSessionXml(
280
GingleDescriptionXml(content_type));
283
std::string JingleInitiateXml(const std::string& content_name_a,
284
const std::string& content_type_a,
285
const std::string& content_name_b,
286
const std::string& content_type_b,
287
bool bundle = false) {
288
std::string content_xml;
289
if (content_name_b.empty()) {
290
content_xml = JingleEmptyContentXml(
291
content_name_a, content_type_a, kTransportType);
293
content_xml = JingleEmptyContentXml(
294
content_name_a, content_type_a, kTransportType) +
295
JingleEmptyContentXml(
296
content_name_b, content_type_b, kTransportType);
298
content_xml += JingleGroupInfoXml(content_name_a, content_name_b);
301
return JingleInitiateActionXml(content_xml);
304
std::string GingleAcceptXml(const std::string& content_type) {
305
return GingleSessionXml(
307
GingleDescriptionXml(content_type));
310
std::string JingleAcceptXml(const std::string& content_name_a,
311
const std::string& content_type_a,
312
const std::string& content_name_b,
313
const std::string& content_type_b,
314
bool bundle = false) {
315
std::string content_xml;
316
if (content_name_b.empty()) {
317
content_xml = JingleEmptyContentXml(
318
content_name_a, content_type_a, kTransportType);
320
content_xml = JingleEmptyContentXml(
321
content_name_a, content_type_a, kTransportType) +
322
JingleEmptyContentXml(
323
content_name_b, content_type_b, kTransportType);
326
content_xml += JingleGroupInfoXml(content_name_a, content_name_b);
329
return JingleActionXml("session-accept", content_xml);
332
std::string Gingle2CandidatesXml(const std::string& channel_name,
335
return GingleSessionXml(
337
P2pCandidateXml(channel_name, port_index0) +
338
P2pCandidateXml(channel_name, port_index1));
341
std::string Gingle4CandidatesXml(const std::string& channel_name_a,
344
const std::string& channel_name_b,
347
return GingleSessionXml(
349
P2pCandidateXml(channel_name_a, port_index0) +
350
P2pCandidateXml(channel_name_a, port_index1) +
351
P2pCandidateXml(channel_name_b, port_index2) +
352
P2pCandidateXml(channel_name_b, port_index3));
355
std::string Jingle2TransportInfoXml(const std::string& content_name,
356
const std::string& channel_name,
359
return JingleActionXml(
361
JingleTransportContentXml(
362
content_name, kTransportType,
363
P2pCandidateXml(channel_name, port_index0) +
364
P2pCandidateXml(channel_name, port_index1)));
367
std::string Jingle4TransportInfoXml(const std::string& content_name,
368
const std::string& channel_name_a,
371
const std::string& channel_name_b,
374
return JingleActionXml(
376
JingleTransportContentXml(
377
content_name, kTransportType,
378
P2pCandidateXml(channel_name_a, port_index0) +
379
P2pCandidateXml(channel_name_a, port_index1) +
380
P2pCandidateXml(channel_name_b, port_index2) +
381
P2pCandidateXml(channel_name_b, port_index3)));
384
std::string JingleDescriptionInfoXml(const std::string& content_name,
385
const std::string& content_type) {
386
return JingleActionXml(
388
JingleContentXml(content_name, content_type, "", ""));
391
std::string GingleRejectXml(const std::string& reason) {
392
return GingleSessionXml(
394
"<" + reason + "/>");
397
std::string JingleTerminateXml(const std::string& reason) {
398
return JingleActionXml(
400
"<reason><" + reason + "/></reason>");
403
std::string GingleTerminateXml(const std::string& reason) {
404
return GingleSessionXml(
406
"<" + reason + "/>");
409
std::string GingleRedirectXml(const std::string& intitiate,
410
const std::string& target) {
412
"<error code=\"302\" type=\"modify\">"
413
"<redirect xmlns=\"http://www.google.com/session\">"
419
std::string JingleRedirectXml(const std::string& intitiate,
420
const std::string& target) {
422
"<error code=\"302\" type=\"modify\">"
423
"<redirect xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">"
429
std::string InitiateXml(SignalingProtocol protocol,
430
const std::string& gingle_content_type,
431
const std::string& content_name_a,
432
const std::string& content_type_a,
433
const std::string& content_name_b,
434
const std::string& content_type_b,
435
bool bundle = false) {
437
case PROTOCOL_JINGLE:
438
return JingleInitiateXml(content_name_a, content_type_a,
439
content_name_b, content_type_b,
441
case PROTOCOL_GINGLE:
442
return GingleInitiateXml(gingle_content_type);
443
case PROTOCOL_HYBRID:
444
return JingleInitiateXml(content_name_a, content_type_a,
445
content_name_b, content_type_b) +
446
GingleInitiateXml(gingle_content_type);
451
std::string InitiateXml(SignalingProtocol protocol,
452
const std::string& content_name,
453
const std::string& content_type) {
454
return InitiateXml(protocol,
456
content_name, content_type,
460
std::string AcceptXml(SignalingProtocol protocol,
461
const std::string& gingle_content_type,
462
const std::string& content_name_a,
463
const std::string& content_type_a,
464
const std::string& content_name_b,
465
const std::string& content_type_b,
466
bool bundle = false) {
468
case PROTOCOL_JINGLE:
469
return JingleAcceptXml(content_name_a, content_type_a,
470
content_name_b, content_type_b, bundle);
471
case PROTOCOL_GINGLE:
472
return GingleAcceptXml(gingle_content_type);
473
case PROTOCOL_HYBRID:
475
JingleAcceptXml(content_name_a, content_type_a,
476
content_name_b, content_type_b) +
477
GingleAcceptXml(gingle_content_type);
483
std::string AcceptXml(SignalingProtocol protocol,
484
const std::string& content_name,
485
const std::string& content_type,
486
bool bundle = false) {
487
return AcceptXml(protocol,
489
content_name, content_type,
493
std::string TransportInfo2Xml(SignalingProtocol protocol,
494
const std::string& content_name,
495
const std::string& channel_name,
499
case PROTOCOL_JINGLE:
500
return Jingle2TransportInfoXml(
502
channel_name, port_index0, port_index1);
503
case PROTOCOL_GINGLE:
504
return Gingle2CandidatesXml(
505
channel_name, port_index0, port_index1);
506
case PROTOCOL_HYBRID:
508
Jingle2TransportInfoXml(
510
channel_name, port_index0, port_index1) +
511
Gingle2CandidatesXml(
512
channel_name, port_index0, port_index1);
517
std::string TransportInfo4Xml(SignalingProtocol protocol,
518
const std::string& content_name,
519
const std::string& channel_name_a,
522
const std::string& channel_name_b,
526
case PROTOCOL_JINGLE:
527
return Jingle4TransportInfoXml(
529
channel_name_a, port_index0, port_index1,
530
channel_name_b, port_index2, port_index3);
531
case PROTOCOL_GINGLE:
532
return Gingle4CandidatesXml(
533
channel_name_a, port_index0, port_index1,
534
channel_name_b, port_index2, port_index3);
535
case PROTOCOL_HYBRID:
537
Jingle4TransportInfoXml(
539
channel_name_a, port_index0, port_index1,
540
channel_name_b, port_index2, port_index3) +
541
Gingle4CandidatesXml(
542
channel_name_a, port_index0, port_index1,
543
channel_name_b, port_index2, port_index3);
548
std::string RejectXml(SignalingProtocol protocol,
549
const std::string& reason) {
551
case PROTOCOL_JINGLE:
552
return JingleTerminateXml(reason);
553
case PROTOCOL_GINGLE:
554
return GingleRejectXml(reason);
555
case PROTOCOL_HYBRID:
556
return JingleTerminateXml(reason) +
557
GingleRejectXml(reason);
562
std::string TerminateXml(SignalingProtocol protocol,
563
const std::string& reason) {
565
case PROTOCOL_JINGLE:
566
return JingleTerminateXml(reason);
567
case PROTOCOL_GINGLE:
568
return GingleTerminateXml(reason);
569
case PROTOCOL_HYBRID:
570
return JingleTerminateXml(reason) +
571
GingleTerminateXml(reason);
576
std::string RedirectXml(SignalingProtocol protocol,
577
const std::string& initiate,
578
const std::string& target) {
580
case PROTOCOL_JINGLE:
581
return JingleRedirectXml(initiate, target);
582
case PROTOCOL_GINGLE:
583
return GingleRedirectXml(initiate, target);
588
// TODO: Break out and join with fakeportallocator.h
589
class TestPortAllocatorSession : public cricket::PortAllocatorSession {
591
TestPortAllocatorSession(const std::string& name,
592
const std::string& session_type,
593
const int port_offset)
594
: PortAllocatorSession(name, session_type, 0),
595
port_offset_(port_offset),
597
address_("127.0.0.1", 0),
598
network_("network", "unittest",
599
talk_base::IPAddress(INADDR_LOOPBACK), 8),
600
socket_factory_(talk_base::Thread::Current()),
603
network_.AddIP(address_.ipaddr());
606
~TestPortAllocatorSession() {
607
for (size_t i = 0; i < ports_.size(); i++)
611
virtual void GetInitialPorts() {
612
for (int i = 0; i < kNumPorts; i++) {
613
int index = port_offset_ + i;
614
ports_[i] = cricket::UDPPort::Create(
615
talk_base::Thread::Current(), &socket_factory_,
616
&network_, address_.ipaddr(), GetPort(index), GetPort(index));
617
ports_[i]->set_username_fragment(GetUsername(index));
618
ports_[i]->set_password(GetPassword(index));
623
virtual void StartGetAllPorts() { running_ = true; }
624
virtual void StopGetAllPorts() { running_ = false; }
625
virtual bool IsGettingAllPorts() { return running_; }
627
void AddPort(cricket::Port* port) {
628
port->set_name(name_);
629
port->set_preference(1.0);
630
port->set_generation(0);
631
port->SignalDestroyed.connect(
632
this, &TestPortAllocatorSession::OnPortDestroyed);
633
port->SignalAddressReady.connect(
634
this, &TestPortAllocatorSession::OnAddressReady);
635
port->PrepareAddress();
636
SignalPortReady(this, port);
639
void OnPortDestroyed(cricket::Port* port) {
640
for (size_t i = 0; i < ports_.size(); i++) {
641
if (ports_[i] == port)
646
void OnAddressReady(cricket::Port* port) {
647
SignalCandidatesReady(this, port->candidates());
652
std::vector<cricket::Port*> ports_;
653
talk_base::SocketAddress address_;
654
talk_base::Network network_;
655
talk_base::BasicPacketSocketFactory socket_factory_;
660
class TestPortAllocator : public cricket::PortAllocator {
662
TestPortAllocator() : port_offset_(0) {}
664
virtual cricket::PortAllocatorSession*
665
CreateSession(const std::string &name,
666
const std::string &content_type) {
668
return new TestPortAllocatorSession(name, content_type, port_offset_ - 2);
674
class TestContentDescription : public cricket::ContentDescription {
676
explicit TestContentDescription(const std::string& gingle_content_type,
677
const std::string& content_type)
678
: gingle_content_type(gingle_content_type),
679
content_type(content_type) {
681
virtual ContentDescription* Copy() const {
682
return new TestContentDescription(*this);
685
std::string gingle_content_type;
686
std::string content_type;
689
cricket::SessionDescription* NewTestSessionDescription(
690
const std::string gingle_content_type,
691
const std::string& content_name_a, const std::string& content_type_a,
692
const std::string& content_name_b, const std::string& content_type_b) {
694
cricket::SessionDescription* offer = new cricket::SessionDescription();
695
offer->AddContent(content_name_a, content_type_a,
696
new TestContentDescription(gingle_content_type,
698
if (content_name_a != content_name_b) {
699
offer->AddContent(content_name_b, content_type_b,
700
new TestContentDescription(gingle_content_type,
706
cricket::SessionDescription* NewTestSessionDescription(
707
const std::string& content_name, const std::string& content_type) {
709
cricket::SessionDescription* offer = new cricket::SessionDescription();
710
offer->AddContent(content_name, content_type,
711
new TestContentDescription(content_type,
716
struct TestSessionClient: public cricket::SessionClient,
717
public sigslot::has_slots<> {
719
TestSessionClient() {
722
~TestSessionClient() {
725
virtual bool ParseContent(SignalingProtocol protocol,
726
const buzz::XmlElement* elem,
727
const cricket::ContentDescription** content,
728
cricket::ParseError* error) {
729
std::string content_type;
730
std::string gingle_content_type;
731
if (protocol == PROTOCOL_GINGLE) {
732
gingle_content_type = elem->Name().Namespace();
734
content_type = elem->Name().Namespace();
737
*content = new TestContentDescription(gingle_content_type, content_type);
741
virtual bool WriteContent(SignalingProtocol protocol,
742
const cricket::ContentDescription* untyped_content,
743
buzz::XmlElement** elem,
744
cricket::WriteError* error) {
745
const TestContentDescription* content =
746
static_cast<const TestContentDescription*>(untyped_content);
747
std::string content_type = (protocol == PROTOCOL_GINGLE ?
748
content->gingle_content_type :
749
content->content_type);
750
*elem = new buzz::XmlElement(
751
buzz::QName(content_type, "description"), true);
755
void OnSessionCreate(cricket::Session* session, bool initiate) {
758
void OnSessionDestroy(cricket::Session* session) {
762
struct ChannelHandler : sigslot::has_slots<> {
763
explicit ChannelHandler(cricket::TransportChannel* p, const std::string& name)
764
: channel(p), last_readable(false), last_writable(false), data_count(0),
765
last_size(0), name(name) {
766
p->SignalReadableState.connect(this, &ChannelHandler::OnReadableState);
767
p->SignalWritableState.connect(this, &ChannelHandler::OnWritableState);
768
p->SignalReadPacket.connect(this, &ChannelHandler::OnReadPacket);
771
bool writable() const {
772
return last_writable && channel->writable();
775
bool readable() const {
776
return last_readable && channel->readable();
779
void OnReadableState(cricket::TransportChannel* p) {
780
EXPECT_EQ(channel, p);
781
last_readable = channel->readable();
784
void OnWritableState(cricket::TransportChannel* p) {
785
EXPECT_EQ(channel, p);
786
last_writable = channel->writable();
789
void OnReadPacket(cricket::TransportChannel* p, const char* buf,
791
if (memcmp(buf, name.c_str(), name.size()) != 0)
792
return; // drop packet if packet doesn't belong to this channel. This
793
// can happen when transport channels are muxed together.
794
buf += name.size(); // Remove channel name from the message.
795
size -= name.size(); // Decrement size by channel name string size.
796
EXPECT_EQ(channel, p);
797
EXPECT_LE(size, sizeof(last_data));
800
std::memcpy(last_data, buf, size);
803
void Send(const char* data, size_t size) {
804
std::string data_with_id(name);
805
data_with_id += data;
806
int result = channel->SendPacket(data_with_id.c_str(), data_with_id.size());
807
EXPECT_EQ(static_cast<int>(data_with_id.size()), result);
810
cricket::TransportChannel* channel;
811
bool last_readable, last_writable;
813
char last_data[4096];
818
void PrintStanza(const std::string& message,
819
const buzz::XmlElement* stanza) {
820
printf("%s: %s\n", message.c_str(), stanza->Str().c_str());
823
class TestClient : public sigslot::has_slots<> {
825
TestClient(cricket::PortAllocator* port_allocator,
826
int* next_message_id,
827
const std::string& local_name,
828
SignalingProtocol start_protocol,
829
const std::string& content_type,
830
const std::string& content_name_a,
831
const std::string& channel_name_a,
832
const std::string& content_name_b,
833
const std::string& channel_name_b) {
834
Construct(port_allocator, next_message_id, local_name, start_protocol,
835
content_type, content_name_a, channel_name_a,
836
content_name_b, channel_name_b);
841
session_manager->DestroySession(session);
842
EXPECT_EQ(1U, session_destroyed_count);
844
delete session_manager;
848
void Construct(cricket::PortAllocator* pa,
850
const std::string& lname,
851
SignalingProtocol protocol,
852
const std::string& cont_type,
853
const std::string& cont_name_a,
854
const std::string& chan_name_a,
855
const std::string& cont_name_b,
856
const std::string& chan_name_b) {
857
port_allocator_ = pa;
858
next_message_id = message_id;
860
start_protocol = protocol;
861
content_type = cont_type;
862
content_name_a = cont_name_a;
863
channel_name_a = chan_name_a;
864
content_name_b = cont_name_b;
865
channel_name_b = chan_name_b;
866
session_created_count = 0;
867
session_destroyed_count = 0;
868
session_remote_description_update_count = 0;
869
last_expected_sent_stanza = NULL;
871
last_session_state = cricket::BaseSession::STATE_INIT;
874
blow_up_on_error = true;
877
session_manager = new cricket::SessionManager(port_allocator_);
878
session_manager->SignalSessionCreate.connect(
879
this, &TestClient::OnSessionCreate);
880
session_manager->SignalSessionDestroy.connect(
881
this, &TestClient::OnSessionDestroy);
882
session_manager->SignalOutgoingMessage.connect(
883
this, &TestClient::OnOutgoingMessage);
885
client = new TestSessionClient();
886
session_manager->AddClient(content_type, client);
887
EXPECT_EQ(client, session_manager->GetClient(content_type));
890
uint32 sent_stanza_count() const {
891
return sent_stanzas.size();
894
const buzz::XmlElement* stanza() const {
895
return last_expected_sent_stanza;
898
cricket::BaseSession::State session_state() const {
899
EXPECT_EQ(last_session_state, session->state());
900
return session->state();
903
void SetSessionState(cricket::BaseSession::State state) {
904
session->SetState(state);
905
EXPECT_EQ_WAIT(last_session_state, session->state(), kEventTimeout);
908
void CreateSession() {
909
session_manager->CreateSession(local_name, content_type);
912
void DeliverStanza(const buzz::XmlElement* stanza) {
913
session_manager->OnIncomingMessage(stanza);
916
void DeliverStanza(const std::string& str) {
917
buzz::XmlElement* stanza = buzz::XmlElement::ForStr(str);
918
session_manager->OnIncomingMessage(stanza);
922
void DeliverAckToLastStanza() {
923
const buzz::XmlElement* orig_stanza = stanza();
924
const buzz::XmlElement* response_stanza =
925
buzz::XmlElement::ForStr(IqAck(orig_stanza->Attr(buzz::QN_IQ), "", ""));
926
session_manager->OnIncomingResponse(orig_stanza, response_stanza);
927
delete response_stanza;
930
void ExpectSentStanza(const std::string& expected) {
931
EXPECT_TRUE(!sent_stanzas.empty()) <<
932
"Found no stanza when expected " << expected;
934
last_expected_sent_stanza = sent_stanzas.front();
935
sent_stanzas.pop_front();
937
std::string actual = last_expected_sent_stanza->Str();
938
EXPECT_EQ(expected, actual);
941
void SkipUnsentStanza() {
942
GetNextOutgoingMessageID();
945
bool HasTransport(const std::string& content_name) const {
946
ASSERT(session != NULL);
947
const cricket::Transport* transport = session->GetTransport(content_name);
948
return transport != NULL && (kTransportType == transport->type());
951
bool HasChannel(const std::string& content_name,
952
const std::string& channel_name) const {
953
ASSERT(session != NULL);
954
const cricket::TransportChannel* channel =
955
session->GetChannel(content_name, channel_name);
956
return channel != NULL && (channel_name == channel->name());
959
cricket::TransportChannel* GetChannel(const std::string& content_name,
960
const std::string& channel_name) const {
961
ASSERT(session != NULL);
962
return session->GetChannel(content_name, channel_name);
965
void OnSessionCreate(cricket::Session* created_session, bool initiate) {
966
session_created_count += 1;
968
session = created_session;
969
session->set_current_protocol(start_protocol);
970
session->set_allow_local_ips(true);
971
session->SignalState.connect(this, &TestClient::OnSessionState);
972
session->SignalError.connect(this, &TestClient::OnSessionError);
973
session->SignalRemoteDescriptionUpdate.connect(
974
this, &TestClient::OnSessionRemoteDescriptionUpdate);
979
void OnSessionDestroy(cricket::Session *session) {
980
session_destroyed_count += 1;
983
void OnSessionState(cricket::BaseSession* session,
984
cricket::BaseSession::State state) {
985
// EXPECT_EQ does not allow use of this, hence the tmp variable.
986
cricket::BaseSession* tmp = this->session;
987
EXPECT_EQ(tmp, session);
988
last_session_state = state;
991
void OnSessionError(cricket::BaseSession* session,
992
cricket::BaseSession::Error error) {
993
// EXPECT_EQ does not allow use of this, hence the tmp variable.
994
cricket::BaseSession* tmp = this->session;
995
EXPECT_EQ(tmp, session);
996
if (blow_up_on_error) {
1003
void OnSessionRemoteDescriptionUpdate(cricket::BaseSession* session,
1004
const cricket::ContentInfos& contents) {
1005
session_remote_description_update_count++;
1008
void PrepareCandidates() {
1009
session_manager->OnSignalingReady();
1012
void OnOutgoingMessage(cricket::SessionManager* manager,
1013
const buzz::XmlElement* stanza) {
1014
buzz::XmlElement* elem = new buzz::XmlElement(*stanza);
1015
EXPECT_TRUE(elem->Name() == buzz::QN_IQ);
1016
EXPECT_TRUE(elem->HasAttr(buzz::QN_TO));
1017
EXPECT_FALSE(elem->HasAttr(buzz::QN_FROM));
1018
EXPECT_TRUE(elem->HasAttr(buzz::QN_TYPE));
1019
EXPECT_TRUE((elem->Attr(buzz::QN_TYPE) == "set") ||
1020
(elem->Attr(buzz::QN_TYPE) == "result") ||
1021
(elem->Attr(buzz::QN_TYPE) == "error"));
1023
elem->SetAttr(buzz::QN_FROM, local_name);
1024
if (elem->Attr(buzz::QN_TYPE) == "set") {
1025
EXPECT_FALSE(elem->HasAttr(buzz::QN_ID));
1026
elem->SetAttr(buzz::QN_ID, GetNextOutgoingMessageID());
1029
// Uncommenting this is useful for debugging.
1030
// PrintStanza("OutgoingMessage", elem);
1031
sent_stanzas.push_back(elem);
1034
std::string GetNextOutgoingMessageID() {
1035
int message_id = (*next_message_id)++;
1036
std::ostringstream ost;
1041
void CreateChannels() {
1042
ASSERT(session != NULL);
1043
chan_a = new ChannelHandler(
1044
session->CreateChannel(content_name_a, channel_name_a), channel_name_a);
1045
chan_b = new ChannelHandler(
1046
session->CreateChannel(content_name_b, channel_name_b), channel_name_b);
1049
int* next_message_id;
1050
std::string local_name;
1051
SignalingProtocol start_protocol;
1052
std::string content_type;
1053
std::string content_name_a;
1054
std::string channel_name_a;
1055
std::string content_name_b;
1056
std::string channel_name_b;
1058
uint32 session_created_count;
1059
uint32 session_destroyed_count;
1060
uint32 session_remote_description_update_count;
1061
std::deque<buzz::XmlElement*> sent_stanzas;
1062
buzz::XmlElement* last_expected_sent_stanza;
1064
cricket::SessionManager* session_manager;
1065
TestSessionClient* client;
1066
cricket::PortAllocator* port_allocator_;
1067
cricket::Session* session;
1068
cricket::BaseSession::State last_session_state;
1069
ChannelHandler* chan_a;
1070
ChannelHandler* chan_b;
1071
bool blow_up_on_error;
1075
class SessionTest : public testing::Test {
1077
virtual void SetUp() {
1078
// Seed needed for each test to satisfy expectations.
1079
talk_base::SetRandomTestMode(true);
1082
virtual void TearDown() {
1083
talk_base::SetRandomTestMode(false);
1086
// Tests sending data between two clients, over two channels.
1087
void TestSendRecv(ChannelHandler* chan1a,
1088
ChannelHandler* chan1b,
1089
ChannelHandler* chan2a,
1090
ChannelHandler* chan2b) {
1091
const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam";
1092
const char* dat2a = "mapssnaebdekabmapsmapsmapsmapsmapsmapsmaps";
1093
const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce...";
1094
const char* dat2b = "...ecuas yanrom a htiw etteverC a rodimrehT retsboL";
1096
for (int i = 0; i < 20; i++) {
1097
chan1a->Send(dat1a, strlen(dat1a));
1098
chan1b->Send(dat1b, strlen(dat1b));
1099
chan2a->Send(dat2a, strlen(dat2a));
1100
chan2b->Send(dat2b, strlen(dat2b));
1102
EXPECT_EQ_WAIT(i + 1, chan1a->data_count, kEventTimeout);
1103
EXPECT_EQ_WAIT(i + 1, chan1b->data_count, kEventTimeout);
1104
EXPECT_EQ_WAIT(i + 1, chan2a->data_count, kEventTimeout);
1105
EXPECT_EQ_WAIT(i + 1, chan2b->data_count, kEventTimeout);
1107
EXPECT_EQ(strlen(dat2a), chan1a->last_size);
1108
EXPECT_EQ(strlen(dat2b), chan1b->last_size);
1109
EXPECT_EQ(strlen(dat1a), chan2a->last_size);
1110
EXPECT_EQ(strlen(dat1b), chan2b->last_size);
1112
EXPECT_EQ(0, std::memcmp(chan1a->last_data, dat2a,
1114
EXPECT_EQ(0, std::memcmp(chan1b->last_data, dat2b,
1116
EXPECT_EQ(0, std::memcmp(chan2a->last_data, dat1a,
1118
EXPECT_EQ(0, std::memcmp(chan2b->last_data, dat1b,
1123
// Test an initiate from one client to another, each with
1124
// independent initial protocols. Checks for the correct initiates,
1125
// candidates, and accept messages, and tests that working network
1126
// channels are established.
1127
void TestSession(SignalingProtocol initiator_protocol,
1128
SignalingProtocol responder_protocol,
1129
SignalingProtocol resulting_protocol,
1130
const std::string& gingle_content_type,
1131
const std::string& content_type,
1132
const std::string& content_name_a,
1133
const std::string& channel_name_a,
1134
const std::string& content_name_b,
1135
const std::string& channel_name_b,
1136
const std::string& initiate_xml,
1137
const std::string& transport_info_a_xml,
1138
const std::string& transport_info_b_xml,
1139
const std::string& transport_info_reply_a_xml,
1140
const std::string& transport_info_reply_b_xml,
1141
const std::string& accept_xml,
1142
bool bundle = false) {
1143
talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1144
new TestPortAllocator());
1145
int next_message_id = 0;
1147
talk_base::scoped_ptr<TestClient> initiator(
1148
new TestClient(allocator.get(), &next_message_id,
1149
kInitiator, initiator_protocol,
1151
content_name_a, channel_name_a,
1152
content_name_b, channel_name_b));
1153
talk_base::scoped_ptr<TestClient> responder(
1154
new TestClient(allocator.get(), &next_message_id,
1155
kResponder, responder_protocol,
1157
content_name_a, channel_name_a,
1158
content_name_b, channel_name_b));
1160
// Create Session and check channels and state.
1161
initiator->CreateSession();
1162
EXPECT_EQ(1U, initiator->session_created_count);
1163
EXPECT_EQ(kSessionId, initiator->session->id());
1164
EXPECT_EQ(initiator->session->local_name(), kInitiator);
1165
EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1166
initiator->session_state());
1168
EXPECT_TRUE(initiator->HasTransport(content_name_a));
1169
EXPECT_TRUE(initiator->HasChannel(content_name_a, channel_name_a));
1170
EXPECT_TRUE(initiator->HasTransport(content_name_b));
1171
EXPECT_TRUE(initiator->HasChannel(content_name_b, channel_name_b));
1173
// Initiate and expect initiate message sent.
1174
cricket::SessionDescription* offer = NewTestSessionDescription(
1175
gingle_content_type,
1176
content_name_a, content_type,
1177
content_name_b, content_type);
1179
cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1180
group.AddContentName(content_name_a);
1181
group.AddContentName(content_name_b);
1182
EXPECT_TRUE(group.HasContentName(content_name_a));
1183
EXPECT_TRUE(group.HasContentName(content_name_b));
1184
offer->AddGroup(group);
1186
EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1187
EXPECT_EQ(initiator->session->remote_name(), kResponder);
1188
EXPECT_EQ(initiator->session->local_description(), offer);
1190
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1191
EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1192
initiator->session_state());
1194
initiator->ExpectSentStanza(
1195
IqSet("0", kInitiator, kResponder, initiate_xml));
1197
// Deliver the initiate. Expect ack and session created with
1199
responder->DeliverStanza(initiator->stanza());
1200
responder->ExpectSentStanza(
1201
IqAck("0", kResponder, kInitiator));
1202
EXPECT_EQ(0U, responder->sent_stanza_count());
1204
EXPECT_EQ(1U, responder->session_created_count);
1205
EXPECT_EQ(kSessionId, responder->session->id());
1206
EXPECT_EQ(responder->session->local_name(), kResponder);
1207
EXPECT_EQ(responder->session->remote_name(), kInitiator);
1208
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1209
responder->session_state());
1211
EXPECT_TRUE(responder->HasTransport(content_name_a));
1212
EXPECT_TRUE(responder->HasChannel(content_name_a, channel_name_a));
1213
EXPECT_TRUE(responder->HasTransport(content_name_b));
1214
EXPECT_TRUE(responder->HasChannel(content_name_b, channel_name_b));
1216
// Expect transport-info message from initiator.
1217
// But don't send candidates until initiate ack is received.
1218
initiator->PrepareCandidates();
1219
WAIT(initiator->sent_stanza_count() > 0, 100);
1220
EXPECT_EQ(0U, initiator->sent_stanza_count());
1221
initiator->DeliverAckToLastStanza();
1222
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1223
initiator->ExpectSentStanza(
1224
IqSet("1", kInitiator, kResponder, transport_info_a_xml));
1226
// Deliver transport-info and expect ack.
1227
responder->DeliverStanza(initiator->stanza());
1228
responder->ExpectSentStanza(
1229
IqAck("1", kResponder, kInitiator));
1231
if (!transport_info_b_xml.empty()) {
1232
// Expect second transport-info message from initiator.
1233
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1234
initiator->ExpectSentStanza(
1235
IqSet("2", kInitiator, kResponder, transport_info_b_xml));
1236
EXPECT_EQ(0U, initiator->sent_stanza_count());
1238
// Deliver second transport-info message and expect ack.
1239
responder->DeliverStanza(initiator->stanza());
1240
responder->ExpectSentStanza(
1241
IqAck("2", kResponder, kInitiator));
1243
EXPECT_EQ(0U, initiator->sent_stanza_count());
1244
EXPECT_EQ(0U, responder->sent_stanza_count());
1245
initiator->SkipUnsentStanza();
1248
// Expect reply transport-info message from responder.
1249
responder->PrepareCandidates();
1250
EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1251
responder->ExpectSentStanza(
1252
IqSet("3", kResponder, kInitiator, transport_info_reply_a_xml));
1254
// Deliver reply transport-info and expect ack.
1255
initiator->DeliverStanza(responder->stanza());
1256
initiator->ExpectSentStanza(
1257
IqAck("3", kInitiator, kResponder));
1259
if (!transport_info_reply_b_xml.empty()) {
1260
// Expect second reply transport-info message from responder.
1261
EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1262
responder->ExpectSentStanza(
1263
IqSet("4", kResponder, kInitiator, transport_info_reply_b_xml));
1264
EXPECT_EQ(0U, responder->sent_stanza_count());
1266
// Deliver second reply transport-info message and expect ack.
1267
initiator->DeliverStanza(responder->stanza());
1268
initiator->ExpectSentStanza(
1269
IqAck("4", kInitiator, kResponder));
1270
EXPECT_EQ(0U, initiator->sent_stanza_count());
1272
EXPECT_EQ(0U, initiator->sent_stanza_count());
1273
EXPECT_EQ(0U, responder->sent_stanza_count());
1274
responder->SkipUnsentStanza();
1277
// The channels should be able to become writable at this point. This
1278
// requires pinging, so it may take a little while.
1279
EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1280
initiator->chan_a->readable(), kEventTimeout);
1281
EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1282
initiator->chan_b->readable(), kEventTimeout);
1283
EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1284
responder->chan_a->readable(), kEventTimeout);
1285
EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1286
responder->chan_b->readable(), kEventTimeout);
1288
// Accept the session and expect accept stanza.
1289
cricket::SessionDescription* answer = NewTestSessionDescription(
1290
gingle_content_type,
1291
content_name_a, content_type,
1292
content_name_b, content_type);
1294
cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1295
group.AddContentName(content_name_a);
1296
group.AddContentName(content_name_b);
1297
EXPECT_TRUE(group.HasContentName(content_name_a));
1298
EXPECT_TRUE(group.HasContentName(content_name_b));
1299
answer->AddGroup(group);
1301
EXPECT_TRUE(responder->session->Accept(answer));
1302
EXPECT_EQ(responder->session->local_description(), answer);
1304
responder->ExpectSentStanza(
1305
IqSet("5", kResponder, kInitiator, accept_xml));
1307
EXPECT_EQ(0U, responder->sent_stanza_count());
1309
// Deliver the accept message and expect an ack.
1310
initiator->DeliverStanza(responder->stanza());
1311
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1312
initiator->ExpectSentStanza(
1313
IqAck("5", kInitiator, kResponder));
1314
EXPECT_EQ(0U, initiator->sent_stanza_count());
1316
// Both sessions should be in progress and have functioning
1318
EXPECT_EQ(resulting_protocol, initiator->session->current_protocol());
1319
EXPECT_EQ(resulting_protocol, responder->session->current_protocol());
1320
EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1321
initiator->session_state(), kEventTimeout);
1322
EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1323
responder->session_state(), kEventTimeout);
1325
cricket::TransportChannel* initiator_chan_a = initiator->chan_a->channel;
1326
cricket::TransportChannel* initiator_chan_b = initiator->chan_b->channel;
1328
// Since we know these are TransportChannelProxy, type cast it.
1329
cricket::TransportChannelProxy* initiator_proxy_chan_a =
1330
static_cast<cricket::TransportChannelProxy*>(initiator_chan_a);
1331
cricket::TransportChannelProxy* initiator_proxy_chan_b =
1332
static_cast<cricket::TransportChannelProxy*>(initiator_chan_b);
1333
EXPECT_TRUE(initiator_proxy_chan_a->impl() != NULL);
1334
EXPECT_TRUE(initiator_proxy_chan_b->impl() != NULL);
1335
EXPECT_EQ(initiator_proxy_chan_a->impl(), initiator_proxy_chan_b->impl());
1337
cricket::TransportChannel* responder_chan_a = responder->chan_a->channel;
1338
cricket::TransportChannel* responder_chan_b = responder->chan_b->channel;
1340
// Since we know these are TransportChannelProxy, type cast it.
1341
cricket::TransportChannelProxy* responder_proxy_chan_a =
1342
static_cast<cricket::TransportChannelProxy*>(responder_chan_a);
1343
cricket::TransportChannelProxy* responder_proxy_chan_b =
1344
static_cast<cricket::TransportChannelProxy*>(responder_chan_b);
1345
EXPECT_TRUE(responder_proxy_chan_a->impl() != NULL);
1346
EXPECT_TRUE(responder_proxy_chan_b->impl() != NULL);
1347
EXPECT_EQ(responder_proxy_chan_a->impl(), responder_proxy_chan_b->impl());
1349
TestSendRecv(initiator->chan_a, initiator->chan_b,
1350
responder->chan_a, responder->chan_b);
1352
if (resulting_protocol == PROTOCOL_JINGLE) {
1353
// Deliver a description-info message to the initiator and check if the
1354
// content description changes.
1355
EXPECT_EQ(0U, initiator->session_remote_description_update_count);
1357
const cricket::SessionDescription* old_session_desc =
1358
initiator->session->remote_description();
1359
const cricket::ContentInfo* old_content_a =
1360
old_session_desc->GetContentByName(content_name_a);
1361
const cricket::ContentDescription* old_content_desc_a =
1362
old_content_a->description;
1363
const cricket::ContentInfo* old_content_b =
1364
old_session_desc->GetContentByName(content_name_b);
1365
const cricket::ContentDescription* old_content_desc_b =
1366
old_content_b->description;
1367
EXPECT_TRUE(old_content_desc_a != NULL);
1368
EXPECT_TRUE(old_content_desc_b != NULL);
1370
LOG(LS_INFO) << "A " << old_content_a->name;
1371
LOG(LS_INFO) << "B " << old_content_b->name;
1373
std::string description_info_xml =
1374
JingleDescriptionInfoXml(content_name_a, content_type);
1375
initiator->DeliverStanza(
1376
IqSet("6", kResponder, kInitiator, description_info_xml));
1377
responder->SkipUnsentStanza();
1378
EXPECT_EQ(1U, initiator->session_remote_description_update_count);
1380
const cricket::SessionDescription* new_session_desc =
1381
initiator->session->remote_description();
1382
const cricket::ContentInfo* new_content_a =
1383
new_session_desc->GetContentByName(content_name_a);
1384
const cricket::ContentDescription* new_content_desc_a =
1385
new_content_a->description;
1386
const cricket::ContentInfo* new_content_b =
1387
new_session_desc->GetContentByName(content_name_b);
1388
const cricket::ContentDescription* new_content_desc_b =
1389
new_content_b->description;
1390
EXPECT_TRUE(new_content_desc_a != NULL);
1391
EXPECT_TRUE(new_content_desc_b != NULL);
1393
// TODO: We used to replace contents from an update, but
1394
// that no longer works with partial updates. We need to figure out
1395
// a way to merge patial updates into contents. For now, users of
1396
// Session should listen to SignalRemoteDescriptionUpdate and handle
1397
// updates. They should not expect remote_description to be the
1399
// See session.cc OnDescriptionInfoMessage.
1401
// EXPECT_NE(old_content_desc_a, new_content_desc_a);
1403
// if (content_name_a != content_name_b) {
1404
// // If content_name_a != content_name_b, then b's content description
1405
// // should not have changed since the description-info message only
1406
// // contained an update for content_name_a.
1407
// EXPECT_EQ(old_content_desc_b, new_content_desc_b);
1410
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1411
initiator->ExpectSentStanza(
1412
IqAck("6", kInitiator, kResponder));
1413
EXPECT_EQ(0U, initiator->sent_stanza_count());
1415
responder->SkipUnsentStanza();
1418
initiator->session->Terminate();
1419
initiator->ExpectSentStanza(
1420
IqSet("7", kInitiator, kResponder,
1421
TerminateXml(resulting_protocol,
1422
cricket::STR_TERMINATE_SUCCESS)));
1424
responder->DeliverStanza(initiator->stanza());
1425
responder->ExpectSentStanza(
1426
IqAck("7", kResponder, kInitiator));
1427
EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
1428
initiator->session_state());
1429
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
1430
responder->session_state());
1433
// Test an initiate with other content, called "main".
1434
void TestOtherContent(SignalingProtocol initiator_protocol,
1435
SignalingProtocol responder_protocol,
1436
SignalingProtocol resulting_protocol) {
1437
std::string content_name = "main";
1438
std::string content_type = "http://oink.splat/session";
1439
std::string content_name_a = content_name;
1440
std::string channel_name_a = "rtcp";
1441
std::string content_name_b = content_name;
1442
std::string channel_name_b = "rtp";
1443
std::string initiate_xml = InitiateXml(
1445
content_name_a, content_type);
1446
std::string transport_info_a_xml = TransportInfo4Xml(
1447
initiator_protocol, content_name,
1448
channel_name_a, 0, 1,
1449
channel_name_b, 2, 3);
1450
std::string transport_info_b_xml = "";
1451
std::string transport_info_reply_a_xml = TransportInfo4Xml(
1452
resulting_protocol, content_name,
1453
channel_name_a, 4, 5,
1454
channel_name_b, 6, 7);
1455
std::string transport_info_reply_b_xml = "";
1456
std::string accept_xml = AcceptXml(
1458
content_name_a, content_type);
1461
TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1464
content_name_a, channel_name_a,
1465
content_name_b, channel_name_b,
1467
transport_info_a_xml, transport_info_b_xml,
1468
transport_info_reply_a_xml, transport_info_reply_b_xml,
1472
// Test an initiate with audio content.
1473
void TestAudioContent(SignalingProtocol initiator_protocol,
1474
SignalingProtocol responder_protocol,
1475
SignalingProtocol resulting_protocol) {
1476
std::string gingle_content_type = cricket::NS_GINGLE_AUDIO;
1477
std::string content_name = cricket::CN_AUDIO;
1478
std::string content_type = cricket::NS_JINGLE_RTP;
1479
std::string channel_name_a = "rtcp";
1480
std::string channel_name_b = "rtp";
1481
std::string initiate_xml = InitiateXml(
1483
gingle_content_type,
1484
content_name, content_type,
1486
std::string transport_info_a_xml = TransportInfo4Xml(
1487
initiator_protocol, content_name,
1488
channel_name_a, 0, 1,
1489
channel_name_b, 2, 3);
1490
std::string transport_info_b_xml = "";
1491
std::string transport_info_reply_a_xml = TransportInfo4Xml(
1492
resulting_protocol, content_name,
1493
channel_name_a, 4, 5,
1494
channel_name_b, 6, 7);
1495
std::string transport_info_reply_b_xml = "";
1496
std::string accept_xml = AcceptXml(
1498
gingle_content_type,
1499
content_name, content_type,
1503
TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1504
gingle_content_type,
1506
content_name, channel_name_a,
1507
content_name, channel_name_b,
1509
transport_info_a_xml, transport_info_b_xml,
1510
transport_info_reply_a_xml, transport_info_reply_b_xml,
1514
// Since media content is "split" into two contents (audio and
1515
// video), we need to treat it special.
1516
void TestVideoContents(SignalingProtocol initiator_protocol,
1517
SignalingProtocol responder_protocol,
1518
SignalingProtocol resulting_protocol) {
1519
std::string content_type = cricket::NS_JINGLE_RTP;
1520
std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
1521
std::string content_name_a = cricket::CN_AUDIO;
1522
std::string channel_name_a = "rtcp";
1523
std::string content_name_b = cricket::CN_VIDEO;
1524
std::string channel_name_b = "video_rtp";
1526
std::string initiate_xml = InitiateXml(
1528
gingle_content_type,
1529
content_name_a, content_type,
1530
content_name_b, content_type);
1531
std::string transport_info_a_xml = TransportInfo2Xml(
1532
initiator_protocol, content_name_a,
1533
channel_name_a, 0, 1);
1534
std::string transport_info_b_xml = TransportInfo2Xml(
1535
initiator_protocol, content_name_b,
1536
channel_name_b, 2, 3);
1537
std::string transport_info_reply_a_xml = TransportInfo2Xml(
1538
resulting_protocol, content_name_a,
1539
channel_name_a, 4, 5);
1540
std::string transport_info_reply_b_xml = TransportInfo2Xml(
1541
resulting_protocol, content_name_b,
1542
channel_name_b, 6, 7);
1543
std::string accept_xml = AcceptXml(
1545
gingle_content_type,
1546
content_name_a, content_type,
1547
content_name_b, content_type);
1549
TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1550
gingle_content_type,
1552
content_name_a, channel_name_a,
1553
content_name_b, channel_name_b,
1555
transport_info_a_xml, transport_info_b_xml,
1556
transport_info_reply_a_xml, transport_info_reply_b_xml,
1560
void TestBadRedirect(SignalingProtocol protocol) {
1561
std::string content_name = "main";
1562
std::string content_type = "http://oink.splat/session";
1563
std::string channel_name_a = "chana";
1564
std::string channel_name_b = "chanb";
1565
std::string initiate_xml = InitiateXml(
1566
protocol, content_name, content_type);
1567
std::string transport_info_xml = TransportInfo4Xml(
1568
protocol, content_name,
1569
channel_name_a, 0, 1,
1570
channel_name_b, 2, 3);
1571
std::string transport_info_reply_xml = TransportInfo4Xml(
1572
protocol, content_name,
1573
channel_name_a, 4, 5,
1574
channel_name_b, 6, 7);
1575
std::string accept_xml = AcceptXml(
1576
protocol, content_name, content_type);
1577
std::string responder_full = kResponder + "/full";
1579
talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1580
new TestPortAllocator());
1581
int next_message_id = 0;
1583
talk_base::scoped_ptr<TestClient> initiator(
1584
new TestClient(allocator.get(), &next_message_id,
1585
kInitiator, protocol,
1587
content_name, channel_name_a,
1588
content_name, channel_name_b));
1590
talk_base::scoped_ptr<TestClient> responder(
1591
new TestClient(allocator.get(), &next_message_id,
1592
responder_full, protocol,
1594
content_name, channel_name_a,
1595
content_name, channel_name_b));
1597
// Create Session and check channels and state.
1598
initiator->CreateSession();
1599
EXPECT_EQ(1U, initiator->session_created_count);
1600
EXPECT_EQ(kSessionId, initiator->session->id());
1601
EXPECT_EQ(initiator->session->local_name(), kInitiator);
1602
EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1603
initiator->session_state());
1605
EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_a));
1606
EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_b));
1608
// Initiate and expect initiate message sent.
1609
cricket::SessionDescription* offer = NewTestSessionDescription(
1610
content_name, content_type);
1611
EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1612
EXPECT_EQ(initiator->session->remote_name(), kResponder);
1613
EXPECT_EQ(initiator->session->local_description(), offer);
1615
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1616
EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1617
initiator->session_state());
1618
initiator->ExpectSentStanza(
1619
IqSet("0", kInitiator, kResponder, initiate_xml));
1621
// Expect transport-info message from initiator.
1622
initiator->DeliverAckToLastStanza();
1623
initiator->PrepareCandidates();
1624
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1625
initiator->ExpectSentStanza(
1626
IqSet("1", kInitiator, kResponder, transport_info_xml));
1628
// Send an unauthorized redirect to the initiator and expect it be ignored.
1629
initiator->blow_up_on_error = false;
1630
const buzz::XmlElement* initiate_stanza = initiator->stanza();
1631
talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
1632
buzz::XmlElement::ForStr(
1633
IqError("ER", kResponder, kInitiator,
1634
RedirectXml(protocol, initiate_xml, "not@allowed.com"))));
1635
initiator->session_manager->OnFailedSend(
1636
initiate_stanza, redirect_stanza.get());
1637
EXPECT_EQ(initiator->session->remote_name(), kResponder);
1638
initiator->blow_up_on_error = true;
1639
EXPECT_EQ(initiator->error_count, 1);
1642
void TestGoodRedirect(SignalingProtocol protocol) {
1643
std::string content_name = "main";
1644
std::string content_type = "http://oink.splat/session";
1645
std::string channel_name_a = "chana";
1646
std::string channel_name_b = "chanb";
1647
std::string initiate_xml = InitiateXml(
1648
protocol, content_name, content_type);
1649
std::string transport_info_xml = TransportInfo4Xml(
1650
protocol, content_name,
1651
channel_name_a, 0, 1,
1652
channel_name_b, 2, 3);
1653
std::string transport_info_reply_xml = TransportInfo4Xml(
1654
protocol, content_name,
1655
channel_name_a, 4, 5,
1656
channel_name_b, 6, 7);
1657
std::string accept_xml = AcceptXml(
1658
protocol, content_name, content_type);
1659
std::string responder_full = kResponder + "/full";
1661
talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1662
new TestPortAllocator());
1663
int next_message_id = 0;
1665
talk_base::scoped_ptr<TestClient> initiator(
1666
new TestClient(allocator.get(), &next_message_id,
1667
kInitiator, protocol,
1669
content_name, channel_name_a,
1670
content_name, channel_name_b));
1672
talk_base::scoped_ptr<TestClient> responder(
1673
new TestClient(allocator.get(), &next_message_id,
1674
responder_full, protocol,
1676
content_name, channel_name_a,
1677
content_name, channel_name_b));
1679
// Create Session and check channels and state.
1680
initiator->CreateSession();
1681
EXPECT_EQ(1U, initiator->session_created_count);
1682
EXPECT_EQ(kSessionId, initiator->session->id());
1683
EXPECT_EQ(initiator->session->local_name(), kInitiator);
1684
EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1685
initiator->session_state());
1687
EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_a));
1688
EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_b));
1690
// Initiate and expect initiate message sent.
1691
cricket::SessionDescription* offer = NewTestSessionDescription(
1692
content_name, content_type);
1693
EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1694
EXPECT_EQ(initiator->session->remote_name(), kResponder);
1695
EXPECT_EQ(initiator->session->local_description(), offer);
1697
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1698
EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1699
initiator->session_state());
1700
initiator->ExpectSentStanza(
1701
IqSet("0", kInitiator, kResponder, initiate_xml));
1703
// Expect transport-info message from initiator.
1704
initiator->DeliverAckToLastStanza();
1705
initiator->PrepareCandidates();
1706
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1707
initiator->ExpectSentStanza(
1708
IqSet("1", kInitiator, kResponder, transport_info_xml));
1710
// Send a redirect to the initiator and expect all of the message
1712
const buzz::XmlElement* initiate_stanza = initiator->stanza();
1713
talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
1714
buzz::XmlElement::ForStr(
1715
IqError("ER2", kResponder, kInitiator,
1716
RedirectXml(protocol, initiate_xml, responder_full))));
1717
initiator->session_manager->OnFailedSend(
1718
initiate_stanza, redirect_stanza.get());
1719
EXPECT_EQ(initiator->session->remote_name(), responder_full);
1721
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1722
initiator->ExpectSentStanza(
1723
IqSet("2", kInitiator, responder_full, initiate_xml));
1724
initiator->ExpectSentStanza(
1725
IqSet("3", kInitiator, responder_full, transport_info_xml));
1727
// Deliver the initiate. Expect ack and session created with
1729
responder->DeliverStanza(
1730
IqSet("2", kInitiator, responder_full, initiate_xml));
1731
responder->ExpectSentStanza(
1732
IqAck("2", responder_full, kInitiator));
1733
EXPECT_EQ(0U, responder->sent_stanza_count());
1735
EXPECT_EQ(1U, responder->session_created_count);
1736
EXPECT_EQ(kSessionId, responder->session->id());
1737
EXPECT_EQ(responder->session->local_name(), responder_full);
1738
EXPECT_EQ(responder->session->remote_name(), kInitiator);
1739
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1740
responder->session_state());
1742
EXPECT_TRUE(responder->HasChannel(content_name, channel_name_a));
1743
EXPECT_TRUE(responder->HasChannel(content_name, channel_name_b));
1745
// Deliver transport-info and expect ack.
1746
responder->DeliverStanza(
1747
IqSet("3", kInitiator, responder_full, transport_info_xml));
1748
responder->ExpectSentStanza(
1749
IqAck("3", responder_full, kInitiator));
1751
// Expect reply transport-infos sent to new remote JID
1752
responder->PrepareCandidates();
1753
EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1754
responder->ExpectSentStanza(
1755
IqSet("4", responder_full, kInitiator, transport_info_reply_xml));
1757
initiator->DeliverStanza(responder->stanza());
1758
initiator->ExpectSentStanza(
1759
IqAck("4", kInitiator, responder_full));
1761
// The channels should be able to become writable at this point. This
1762
// requires pinging, so it may take a little while.
1763
EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1764
initiator->chan_a->readable(), kEventTimeout);
1765
EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1766
initiator->chan_b->readable(), kEventTimeout);
1767
EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1768
responder->chan_a->readable(), kEventTimeout);
1769
EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1770
responder->chan_b->readable(), kEventTimeout);
1772
// Accept the session and expect accept stanza.
1773
cricket::SessionDescription* answer = NewTestSessionDescription(
1774
content_name, content_type);
1775
EXPECT_TRUE(responder->session->Accept(answer));
1776
EXPECT_EQ(responder->session->local_description(), answer);
1778
responder->ExpectSentStanza(
1779
IqSet("5", responder_full, kInitiator, accept_xml));
1780
EXPECT_EQ(0U, responder->sent_stanza_count());
1782
// Deliver the accept message and expect an ack.
1783
initiator->DeliverStanza(responder->stanza());
1784
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1785
initiator->ExpectSentStanza(
1786
IqAck("5", kInitiator, responder_full));
1787
EXPECT_EQ(0U, initiator->sent_stanza_count());
1789
// Both sessions should be in progress and have functioning
1791
EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1792
initiator->session_state(), kEventTimeout);
1793
EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1794
responder->session_state(), kEventTimeout);
1795
TestSendRecv(initiator->chan_a, initiator->chan_b,
1796
responder->chan_a, responder->chan_b);
1799
void TestCandidatesInInitiateAndAccept(const std::string& test_name) {
1800
std::string content_name = "main";
1801
std::string content_type = "http://oink.splat/session";
1802
std::string channel_name_a = "rtcp";
1803
std::string channel_name_b = "rtp";
1804
cricket::SignalingProtocol protocol = PROTOCOL_JINGLE;
1806
talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1807
new TestPortAllocator());
1808
int next_message_id = 0;
1810
talk_base::scoped_ptr<TestClient> initiator(
1811
new TestClient(allocator.get(), &next_message_id,
1812
kInitiator, protocol,
1814
content_name, channel_name_a,
1815
content_name, channel_name_b));
1817
talk_base::scoped_ptr<TestClient> responder(
1818
new TestClient(allocator.get(), &next_message_id,
1819
kResponder, protocol,
1821
content_name, channel_name_a,
1822
content_name, channel_name_b));
1824
// Create Session and check channels and state.
1825
initiator->CreateSession();
1826
EXPECT_TRUE(initiator->HasTransport(content_name));
1827
EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_a));
1828
EXPECT_TRUE(initiator->HasTransport(content_name));
1829
EXPECT_TRUE(initiator->HasChannel(content_name, channel_name_b));
1831
// Initiate and expect initiate message sent.
1832
cricket::SessionDescription* offer = NewTestSessionDescription(
1833
content_name, content_type);
1834
EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1836
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1837
EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1838
initiator->session_state());
1839
initiator->ExpectSentStanza(
1840
IqSet("0", kInitiator, kResponder,
1841
InitiateXml(protocol, content_name, content_type)));
1843
// Fake the delivery the initiate and candidates together.
1844
responder->DeliverStanza(
1845
IqSet("A", kInitiator, kResponder,
1846
JingleInitiateActionXml(
1848
content_name, content_type, kTransportType,
1849
P2pCandidateXml(channel_name_a, 0) +
1850
P2pCandidateXml(channel_name_a, 1) +
1851
P2pCandidateXml(channel_name_b, 2) +
1852
P2pCandidateXml(channel_name_b, 3)))));
1853
responder->ExpectSentStanza(
1854
IqAck("A", kResponder, kInitiator));
1855
EXPECT_EQ(0U, responder->sent_stanza_count());
1857
EXPECT_EQ(1U, responder->session_created_count);
1858
EXPECT_EQ(kSessionId, responder->session->id());
1859
EXPECT_EQ(responder->session->local_name(), kResponder);
1860
EXPECT_EQ(responder->session->remote_name(), kInitiator);
1861
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1862
responder->session_state());
1864
EXPECT_TRUE(responder->HasTransport(content_name));
1865
EXPECT_TRUE(responder->HasChannel(content_name, channel_name_a));
1866
EXPECT_TRUE(responder->HasTransport(content_name));
1867
EXPECT_TRUE(responder->HasChannel(content_name, channel_name_b));
1869
// Expect transport-info message from initiator.
1870
// But don't send candidates until initiate ack is received.
1871
initiator->DeliverAckToLastStanza();
1872
initiator->PrepareCandidates();
1873
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1874
initiator->ExpectSentStanza(
1875
IqSet("1", kInitiator, kResponder,
1876
TransportInfo4Xml(protocol, content_name,
1877
channel_name_a, 0, 1,
1878
channel_name_b, 2, 3)));
1880
responder->PrepareCandidates();
1881
EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1882
responder->ExpectSentStanza(
1883
IqSet("2", kResponder, kInitiator,
1884
TransportInfo4Xml(protocol, content_name,
1885
channel_name_a, 4, 5,
1886
channel_name_b, 6, 7)));
1888
// Accept the session and expect accept stanza.
1889
cricket::SessionDescription* answer = NewTestSessionDescription(
1890
content_name, content_type);
1891
EXPECT_TRUE(responder->session->Accept(answer));
1893
responder->ExpectSentStanza(
1894
IqSet("3", kResponder, kInitiator,
1895
AcceptXml(protocol, content_name, content_type)));
1896
EXPECT_EQ(0U, responder->sent_stanza_count());
1898
// Fake the delivery the accept and candidates together.
1899
initiator->DeliverStanza(
1900
IqSet("B", kResponder, kInitiator,
1901
JingleActionXml("session-accept",
1903
content_name, content_type, kTransportType,
1904
P2pCandidateXml(channel_name_a, 4) +
1905
P2pCandidateXml(channel_name_a, 5) +
1906
P2pCandidateXml(channel_name_b, 6) +
1907
P2pCandidateXml(channel_name_b, 7)))));
1908
EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1909
initiator->ExpectSentStanza(
1910
IqAck("B", kInitiator, kResponder));
1911
EXPECT_EQ(0U, initiator->sent_stanza_count());
1913
// The channels should be able to become writable at this point. This
1914
// requires pinging, so it may take a little while.
1915
EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1916
initiator->chan_a->readable(), kEventTimeout);
1917
EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1918
initiator->chan_b->readable(), kEventTimeout);
1919
EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1920
responder->chan_a->readable(), kEventTimeout);
1921
EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1922
responder->chan_b->readable(), kEventTimeout);
1925
// Both sessions should be in progress and have functioning
1927
EXPECT_EQ(protocol, initiator->session->current_protocol());
1928
EXPECT_EQ(protocol, responder->session->current_protocol());
1929
EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1930
initiator->session_state(), kEventTimeout);
1931
EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1932
responder->session_state(), kEventTimeout);
1933
TestSendRecv(initiator->chan_a, initiator->chan_b,
1934
responder->chan_a, responder->chan_b);
1937
// Tests that when an initiator terminates right after initiate,
1938
// everything behaves correctly.
1939
void TestEarlyTerminationFromInitiator(SignalingProtocol protocol) {
1940
std::string content_name = "main";
1941
std::string content_type = "http://oink.splat/session";
1943
talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1944
new TestPortAllocator());
1945
int next_message_id = 0;
1947
talk_base::scoped_ptr<TestClient> initiator(
1948
new TestClient(allocator.get(), &next_message_id,
1949
kInitiator, protocol,
1952
content_name, "b"));
1954
talk_base::scoped_ptr<TestClient> responder(
1955
new TestClient(allocator.get(), &next_message_id,
1956
kResponder, protocol,
1959
content_name, "b"));
1962
initiator->CreateSession();
1963
EXPECT_TRUE(initiator->session->Initiate(
1964
kResponder, NewTestSessionDescription(content_name, content_type)));
1965
initiator->ExpectSentStanza(
1966
IqSet("0", kInitiator, kResponder,
1967
InitiateXml(protocol, content_name, content_type)));
1968
EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1969
initiator->session_state());
1971
responder->DeliverStanza(initiator->stanza());
1972
responder->ExpectSentStanza(
1973
IqAck("0", kResponder, kInitiator));
1974
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1975
responder->session_state());
1977
initiator->session->TerminateWithReason(cricket::STR_TERMINATE_ERROR);
1978
initiator->ExpectSentStanza(
1979
IqSet("1", kInitiator, kResponder,
1980
TerminateXml(protocol, cricket::STR_TERMINATE_ERROR)));
1981
EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
1982
initiator->session_state());
1984
responder->DeliverStanza(initiator->stanza());
1985
responder->ExpectSentStanza(
1986
IqAck("1", kResponder, kInitiator));
1987
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
1988
responder->session_state());
1991
// Tests that when the responder rejects, everything behaves
1993
void TestRejection(SignalingProtocol protocol) {
1994
std::string content_name = "main";
1995
std::string content_type = "http://oink.splat/session";
1997
talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1998
new TestPortAllocator());
1999
int next_message_id = 0;
2001
talk_base::scoped_ptr<TestClient> initiator(
2002
new TestClient(allocator.get(), &next_message_id,
2003
kInitiator, protocol,
2006
content_name, "b"));
2009
initiator->CreateSession();
2010
EXPECT_TRUE(initiator->session->Initiate(
2011
kResponder, NewTestSessionDescription(content_name, content_type)));
2012
initiator->ExpectSentStanza(
2013
IqSet("0", kInitiator, kResponder,
2014
InitiateXml(protocol, content_name, content_type)));
2015
EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
2016
initiator->session_state());
2018
initiator->DeliverStanza(
2019
IqSet("1", kResponder, kInitiator,
2020
RejectXml(protocol, cricket::STR_TERMINATE_ERROR)));
2021
initiator->ExpectSentStanza(
2022
IqAck("1", kInitiator, kResponder));
2023
if (protocol == PROTOCOL_JINGLE) {
2024
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
2025
initiator->session_state());
2027
EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDREJECT,
2028
initiator->session_state());
2032
void TestTransportMux() {
2033
SignalingProtocol initiator_protocol = PROTOCOL_JINGLE;
2034
SignalingProtocol responder_protocol = PROTOCOL_JINGLE;
2035
SignalingProtocol resulting_protocol = PROTOCOL_JINGLE;
2036
std::string content_type = cricket::NS_JINGLE_RTP;
2037
std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
2038
std::string content_name_a = cricket::CN_AUDIO;
2039
std::string channel_name_a = "rtcp";
2040
std::string content_name_b = cricket::CN_VIDEO;
2041
std::string channel_name_b = "video_rtp";
2043
std::string initiate_xml = InitiateXml(
2045
gingle_content_type,
2046
content_name_a, content_type,
2047
content_name_b, content_type, true);
2048
std::string transport_info_a_xml = TransportInfo2Xml(
2049
initiator_protocol, content_name_a,
2050
channel_name_a, 0, 1);
2051
std::string transport_info_b_xml = TransportInfo2Xml(
2052
initiator_protocol, content_name_b,
2053
channel_name_b, 2, 3);
2054
std::string transport_info_reply_a_xml = TransportInfo2Xml(
2055
resulting_protocol, content_name_a,
2056
channel_name_a, 4, 5);
2057
std::string transport_info_reply_b_xml = TransportInfo2Xml(
2058
resulting_protocol, content_name_b,
2059
channel_name_b, 6, 7);
2060
std::string accept_xml = AcceptXml(
2062
gingle_content_type,
2063
content_name_a, content_type,
2064
content_name_b, content_type, true);
2066
TestSession(initiator_protocol, responder_protocol, resulting_protocol,
2067
gingle_content_type,
2069
content_name_a, channel_name_a,
2070
content_name_b, channel_name_b,
2072
transport_info_a_xml, transport_info_b_xml,
2073
transport_info_reply_a_xml, transport_info_reply_b_xml,
2079
// For each of these, "X => Y = Z" means "if a client with protocol X
2080
// initiates to a client with protocol Y, they end up speaking protocol Z.
2082
// Gingle => Gingle = Gingle (with other content)
2083
TEST_F(SessionTest, GingleToGingleOtherContent) {
2084
TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2087
// Gingle => Gingle = Gingle (with audio content)
2088
TEST_F(SessionTest, GingleToGingleAudioContent) {
2089
TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2092
// Gingle => Gingle = Gingle (with video contents)
2093
TEST_F(SessionTest, GingleToGingleVideoContents) {
2094
TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2098
// Jingle => Jingle = Jingle (with other content)
2099
TEST_F(SessionTest, JingleToJingleOtherContent) {
2100
TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2103
// Jingle => Jingle = Jingle (with audio content)
2104
TEST_F(SessionTest, JingleToJingleAudioContent) {
2105
TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2108
// Jingle => Jingle = Jingle (with video contents)
2109
TEST_F(SessionTest, JingleToJingleVideoContents) {
2110
TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2114
// Hybrid => Hybrid = Jingle (with other content)
2115
TEST_F(SessionTest, HybridToHybridOtherContent) {
2116
TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2119
// Hybrid => Hybrid = Jingle (with audio content)
2120
TEST_F(SessionTest, HybridToHybridAudioContent) {
2121
TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2124
// Hybrid => Hybrid = Jingle (with video contents)
2125
TEST_F(SessionTest, HybridToHybridVideoContents) {
2126
TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2130
// Gingle => Hybrid = Gingle (with other content)
2131
TEST_F(SessionTest, GingleToHybridOtherContent) {
2132
TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2135
// Gingle => Hybrid = Gingle (with audio content)
2136
TEST_F(SessionTest, GingleToHybridAudioContent) {
2137
TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2140
// Gingle => Hybrid = Gingle (with video contents)
2141
TEST_F(SessionTest, GingleToHybridVideoContents) {
2142
TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2146
// Jingle => Hybrid = Jingle (with other content)
2147
TEST_F(SessionTest, JingleToHybridOtherContent) {
2148
TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2151
// Jingle => Hybrid = Jingle (with audio content)
2152
TEST_F(SessionTest, JingleToHybridAudioContent) {
2153
TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2156
// Jingle => Hybrid = Jingle (with video contents)
2157
TEST_F(SessionTest, JingleToHybridVideoContents) {
2158
TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2162
// Hybrid => Gingle = Gingle (with other content)
2163
TEST_F(SessionTest, HybridToGingleOtherContent) {
2164
TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2167
// Hybrid => Gingle = Gingle (with audio content)
2168
TEST_F(SessionTest, HybridToGingleAudioContent) {
2169
TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2172
// Hybrid => Gingle = Gingle (with video contents)
2173
TEST_F(SessionTest, HybridToGingleVideoContents) {
2174
TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2178
// Hybrid => Jingle = Jingle (with other content)
2179
TEST_F(SessionTest, HybridToJingleOtherContent) {
2180
TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2183
// Hybrid => Jingle = Jingle (with audio content)
2184
TEST_F(SessionTest, HybridToJingleAudioContent) {
2185
TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2188
// Hybrid => Jingle = Jingle (with video contents)
2189
TEST_F(SessionTest, HybridToJingleVideoContents) {
2190
TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2194
TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) {
2195
TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE);
2198
TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) {
2199
TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE);
2202
TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) {
2203
TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID);
2206
TEST_F(SessionTest, GingleRejection) {
2207
TestRejection(PROTOCOL_GINGLE);
2210
TEST_F(SessionTest, JingleRejection) {
2211
TestRejection(PROTOCOL_JINGLE);
2214
TEST_F(SessionTest, GingleGoodRedirect) {
2215
TestGoodRedirect(PROTOCOL_GINGLE);
2218
TEST_F(SessionTest, JingleGoodRedirect) {
2219
TestGoodRedirect(PROTOCOL_JINGLE);
2222
TEST_F(SessionTest, GingleBadRedirect) {
2223
TestBadRedirect(PROTOCOL_GINGLE);
2226
TEST_F(SessionTest, JingleBadRedirect) {
2227
TestBadRedirect(PROTOCOL_JINGLE);
2230
TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) {
2231
TestCandidatesInInitiateAndAccept("Candidates in initiate/accept");
2234
TEST_F(SessionTest, TestTransportMux) {