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