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