blob: ab4620f879efdb77c028856edd4d3bc1977981e8 [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
28#include <cstring>
29#include <sstream>
30#include <deque>
31#include <map>
32
33#include "talk/base/base64.h"
34#include "talk/base/common.h"
mallinath@webrtc.org1112c302013-09-23 20:34:45 +000035#include "talk/base/dscp.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036#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;
827 std::memcpy(last_data, buf, size);
828 }
829
830 void Send(const char* data, size_t size) {
831 std::string data_with_id(name);
832 data_with_id += data;
833 int result = channel->SendPacket(data_with_id.c_str(), data_with_id.size(),
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000834 talk_base::DSCP_NO_CHANGE, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 EXPECT_EQ(static_cast<int>(data_with_id.size()), result);
836 }
837
838 cricket::TransportChannel* channel;
839 bool last_readable, last_writable;
840 int data_count;
841 char last_data[4096];
842 size_t last_size;
843 std::string name;
844};
845
846void PrintStanza(const std::string& message,
847 const buzz::XmlElement* stanza) {
848 printf("%s: %s\n", message.c_str(), stanza->Str().c_str());
849}
850
851class TestClient : public sigslot::has_slots<> {
852 public:
853 // TODO: Add channel_component_a/b as inputs to the ctor.
854 TestClient(cricket::PortAllocator* port_allocator,
855 int* next_message_id,
856 const std::string& local_name,
857 SignalingProtocol start_protocol,
858 const std::string& content_type,
859 const std::string& content_name_a,
860 const std::string& channel_name_a,
861 const std::string& content_name_b,
862 const std::string& channel_name_b) {
863 Construct(port_allocator, next_message_id, local_name, start_protocol,
864 content_type, content_name_a, channel_name_a,
865 content_name_b, channel_name_b);
866 }
867
868 ~TestClient() {
869 if (session) {
870 session_manager->DestroySession(session);
871 EXPECT_EQ(1U, session_destroyed_count);
872 }
873 delete session_manager;
874 delete client;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000875 for (std::deque<buzz::XmlElement*>::iterator it = sent_stanzas.begin();
876 it != sent_stanzas.end(); ++it) {
877 delete *it;
878 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000879 }
880
881 void Construct(cricket::PortAllocator* pa,
882 int* message_id,
883 const std::string& lname,
884 SignalingProtocol protocol,
885 const std::string& cont_type,
886 const std::string& cont_name_a,
887 const std::string& chan_name_a,
888 const std::string& cont_name_b,
889 const std::string& chan_name_b) {
890 port_allocator_ = pa;
891 next_message_id = message_id;
892 local_name = lname;
893 start_protocol = protocol;
894 content_type = cont_type;
895 content_name_a = cont_name_a;
896 channel_name_a = chan_name_a;
897 content_name_b = cont_name_b;
898 channel_name_b = chan_name_b;
899 session_created_count = 0;
900 session_destroyed_count = 0;
901 session_remote_description_update_count = 0;
902 new_local_description = false;
903 new_remote_description = false;
904 last_content_action = cricket::CA_OFFER;
905 last_content_source = cricket::CS_LOCAL;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906 session = NULL;
907 last_session_state = cricket::BaseSession::STATE_INIT;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000908 blow_up_on_error = true;
909 error_count = 0;
910
911 session_manager = new cricket::SessionManager(port_allocator_);
912 session_manager->SignalSessionCreate.connect(
913 this, &TestClient::OnSessionCreate);
914 session_manager->SignalSessionDestroy.connect(
915 this, &TestClient::OnSessionDestroy);
916 session_manager->SignalOutgoingMessage.connect(
917 this, &TestClient::OnOutgoingMessage);
918
919 client = new TestSessionClient();
920 session_manager->AddClient(content_type, client);
921 EXPECT_EQ(client, session_manager->GetClient(content_type));
922 }
923
924 uint32 sent_stanza_count() const {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000925 return static_cast<uint32>(sent_stanzas.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926 }
927
928 const buzz::XmlElement* stanza() const {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000929 return last_expected_sent_stanza.get();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000930 }
931
932 cricket::BaseSession::State session_state() const {
933 EXPECT_EQ(last_session_state, session->state());
934 return session->state();
935 }
936
937 void SetSessionState(cricket::BaseSession::State state) {
938 session->SetState(state);
939 EXPECT_EQ_WAIT(last_session_state, session->state(), kEventTimeout);
940 }
941
942 void CreateSession() {
943 session_manager->CreateSession(local_name, content_type);
944 }
945
946 void DeliverStanza(const buzz::XmlElement* stanza) {
947 session_manager->OnIncomingMessage(stanza);
948 }
949
950 void DeliverStanza(const std::string& str) {
951 buzz::XmlElement* stanza = buzz::XmlElement::ForStr(str);
952 session_manager->OnIncomingMessage(stanza);
953 delete stanza;
954 }
955
956 void DeliverAckToLastStanza() {
957 const buzz::XmlElement* orig_stanza = stanza();
958 const buzz::XmlElement* response_stanza =
959 buzz::XmlElement::ForStr(IqAck(orig_stanza->Attr(buzz::QN_IQ), "", ""));
960 session_manager->OnIncomingResponse(orig_stanza, response_stanza);
961 delete response_stanza;
962 }
963
964 void ExpectSentStanza(const std::string& expected) {
965 EXPECT_TRUE(!sent_stanzas.empty()) <<
966 "Found no stanza when expected " << expected;
967
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000968 last_expected_sent_stanza.reset(sent_stanzas.front());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 sent_stanzas.pop_front();
970
971 std::string actual = last_expected_sent_stanza->Str();
972 EXPECT_EQ(expected, actual);
973 }
974
975 void SkipUnsentStanza() {
976 GetNextOutgoingMessageID();
977 }
978
979 bool HasTransport(const std::string& content_name) const {
980 ASSERT(session != NULL);
981 const cricket::Transport* transport = session->GetTransport(content_name);
982 return transport != NULL && (kTransportType == transport->type());
983 }
984
985 bool HasChannel(const std::string& content_name,
986 int component) const {
987 ASSERT(session != NULL);
988 const cricket::TransportChannel* channel =
989 session->GetChannel(content_name, component);
990 return channel != NULL && (component == channel->component());
991 }
992
993 cricket::TransportChannel* GetChannel(const std::string& content_name,
994 int component) const {
995 ASSERT(session != NULL);
996 return session->GetChannel(content_name, component);
997 }
998
999 void OnSessionCreate(cricket::Session* created_session, bool initiate) {
1000 session_created_count += 1;
1001
1002 session = created_session;
1003 session->set_current_protocol(start_protocol);
1004 session->SignalState.connect(this, &TestClient::OnSessionState);
1005 session->SignalError.connect(this, &TestClient::OnSessionError);
1006 session->SignalRemoteDescriptionUpdate.connect(
1007 this, &TestClient::OnSessionRemoteDescriptionUpdate);
1008 session->SignalNewLocalDescription.connect(
1009 this, &TestClient::OnNewLocalDescription);
1010 session->SignalNewRemoteDescription.connect(
1011 this, &TestClient::OnNewRemoteDescription);
1012
1013 CreateChannels();
1014 }
1015
1016 void OnSessionDestroy(cricket::Session *session) {
1017 session_destroyed_count += 1;
1018 }
1019
1020 void OnSessionState(cricket::BaseSession* session,
1021 cricket::BaseSession::State state) {
1022 // EXPECT_EQ does not allow use of this, hence the tmp variable.
1023 cricket::BaseSession* tmp = this->session;
1024 EXPECT_EQ(tmp, session);
1025 last_session_state = state;
1026 }
1027
1028 void OnSessionError(cricket::BaseSession* session,
1029 cricket::BaseSession::Error error) {
1030 // EXPECT_EQ does not allow use of this, hence the tmp variable.
1031 cricket::BaseSession* tmp = this->session;
1032 EXPECT_EQ(tmp, session);
1033 if (blow_up_on_error) {
1034 EXPECT_TRUE(false);
1035 } else {
1036 error_count++;
1037 }
1038 }
1039
1040 void OnSessionRemoteDescriptionUpdate(cricket::BaseSession* session,
1041 const cricket::ContentInfos& contents) {
1042 session_remote_description_update_count++;
1043 }
1044
1045 void OnNewLocalDescription(cricket::BaseSession* session,
1046 cricket::ContentAction action) {
1047 new_local_description = true;
1048 last_content_action = action;
1049 last_content_source = cricket::CS_LOCAL;
1050 }
1051
1052 void OnNewRemoteDescription(cricket::BaseSession* session,
1053 cricket::ContentAction action) {
1054 new_remote_description = true;
1055 last_content_action = action;
1056 last_content_source = cricket::CS_REMOTE;
1057 }
1058
1059 void PrepareCandidates() {
1060 session_manager->OnSignalingReady();
1061 }
1062
1063 void OnOutgoingMessage(cricket::SessionManager* manager,
1064 const buzz::XmlElement* stanza) {
1065 buzz::XmlElement* elem = new buzz::XmlElement(*stanza);
1066 EXPECT_TRUE(elem->Name() == buzz::QN_IQ);
1067 EXPECT_TRUE(elem->HasAttr(buzz::QN_TO));
1068 EXPECT_FALSE(elem->HasAttr(buzz::QN_FROM));
1069 EXPECT_TRUE(elem->HasAttr(buzz::QN_TYPE));
1070 EXPECT_TRUE((elem->Attr(buzz::QN_TYPE) == "set") ||
1071 (elem->Attr(buzz::QN_TYPE) == "result") ||
1072 (elem->Attr(buzz::QN_TYPE) == "error"));
1073
1074 elem->SetAttr(buzz::QN_FROM, local_name);
1075 if (elem->Attr(buzz::QN_TYPE) == "set") {
1076 EXPECT_FALSE(elem->HasAttr(buzz::QN_ID));
1077 elem->SetAttr(buzz::QN_ID, GetNextOutgoingMessageID());
1078 }
1079
1080 // Uncommenting this is useful for debugging.
1081 // PrintStanza("OutgoingMessage", elem);
1082 sent_stanzas.push_back(elem);
1083 }
1084
1085 std::string GetNextOutgoingMessageID() {
1086 int message_id = (*next_message_id)++;
1087 std::ostringstream ost;
1088 ost << message_id;
1089 return ost.str();
1090 }
1091
1092 void CreateChannels() {
1093 ASSERT(session != NULL);
1094 // We either have a single content with multiple components (RTP/RTCP), or
1095 // multiple contents with single components, but not both.
1096 int component_a = 1;
1097 int component_b = (content_name_a == content_name_b) ? 2 : 1;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001098 chan_a.reset(new ChannelHandler(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001099 session->CreateChannel(content_name_a, channel_name_a, component_a),
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001100 channel_name_a));
1101 chan_b.reset(new ChannelHandler(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001102 session->CreateChannel(content_name_b, channel_name_b, component_b),
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001103 channel_name_b));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104 }
1105
1106 int* next_message_id;
1107 std::string local_name;
1108 SignalingProtocol start_protocol;
1109 std::string content_type;
1110 std::string content_name_a;
1111 std::string channel_name_a;
1112 std::string content_name_b;
1113 std::string channel_name_b;
1114
1115 uint32 session_created_count;
1116 uint32 session_destroyed_count;
1117 uint32 session_remote_description_update_count;
1118 bool new_local_description;
1119 bool new_remote_description;
1120 cricket::ContentAction last_content_action;
1121 cricket::ContentSource last_content_source;
1122 std::deque<buzz::XmlElement*> sent_stanzas;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001123 talk_base::scoped_ptr<buzz::XmlElement> last_expected_sent_stanza;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001124
1125 cricket::SessionManager* session_manager;
1126 TestSessionClient* client;
1127 cricket::PortAllocator* port_allocator_;
1128 cricket::Session* session;
1129 cricket::BaseSession::State last_session_state;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001130 talk_base::scoped_ptr<ChannelHandler> chan_a;
1131 talk_base::scoped_ptr<ChannelHandler> chan_b;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001132 bool blow_up_on_error;
1133 int error_count;
1134};
1135
1136class SessionTest : public testing::Test {
1137 protected:
1138 virtual void SetUp() {
1139 // Seed needed for each test to satisfy expectations.
1140 talk_base::SetRandomTestMode(true);
1141 }
1142
1143 virtual void TearDown() {
1144 talk_base::SetRandomTestMode(false);
1145 }
1146
1147 // Tests sending data between two clients, over two channels.
1148 void TestSendRecv(ChannelHandler* chan1a,
1149 ChannelHandler* chan1b,
1150 ChannelHandler* chan2a,
1151 ChannelHandler* chan2b) {
1152 const char* dat1a = "spamspamspamspamspamspamspambakedbeansspam";
1153 const char* dat2a = "mapssnaebdekabmapsmapsmapsmapsmapsmapsmaps";
1154 const char* dat1b = "Lobster Thermidor a Crevette with a mornay sauce...";
1155 const char* dat2b = "...ecuas yanrom a htiw etteverC a rodimrehT retsboL";
1156
1157 for (int i = 0; i < 20; i++) {
1158 chan1a->Send(dat1a, strlen(dat1a));
1159 chan1b->Send(dat1b, strlen(dat1b));
1160 chan2a->Send(dat2a, strlen(dat2a));
1161 chan2b->Send(dat2b, strlen(dat2b));
1162
1163 EXPECT_EQ_WAIT(i + 1, chan1a->data_count, kEventTimeout);
1164 EXPECT_EQ_WAIT(i + 1, chan1b->data_count, kEventTimeout);
1165 EXPECT_EQ_WAIT(i + 1, chan2a->data_count, kEventTimeout);
1166 EXPECT_EQ_WAIT(i + 1, chan2b->data_count, kEventTimeout);
1167
1168 EXPECT_EQ(strlen(dat2a), chan1a->last_size);
1169 EXPECT_EQ(strlen(dat2b), chan1b->last_size);
1170 EXPECT_EQ(strlen(dat1a), chan2a->last_size);
1171 EXPECT_EQ(strlen(dat1b), chan2b->last_size);
1172
1173 EXPECT_EQ(0, std::memcmp(chan1a->last_data, dat2a,
1174 strlen(dat2a)));
1175 EXPECT_EQ(0, std::memcmp(chan1b->last_data, dat2b,
1176 strlen(dat2b)));
1177 EXPECT_EQ(0, std::memcmp(chan2a->last_data, dat1a,
1178 strlen(dat1a)));
1179 EXPECT_EQ(0, std::memcmp(chan2b->last_data, dat1b,
1180 strlen(dat1b)));
1181 }
1182 }
1183
1184 // Test an initiate from one client to another, each with
1185 // independent initial protocols. Checks for the correct initiates,
1186 // candidates, and accept messages, and tests that working network
1187 // channels are established.
1188 void TestSession(SignalingProtocol initiator_protocol,
1189 SignalingProtocol responder_protocol,
1190 SignalingProtocol resulting_protocol,
1191 const std::string& gingle_content_type,
1192 const std::string& content_type,
1193 const std::string& content_name_a,
1194 const std::string& channel_name_a,
1195 const std::string& content_name_b,
1196 const std::string& channel_name_b,
1197 const std::string& initiate_xml,
1198 const std::string& transport_info_a_xml,
1199 const std::string& transport_info_b_xml,
1200 const std::string& transport_info_reply_a_xml,
1201 const std::string& transport_info_reply_b_xml,
1202 const std::string& accept_xml,
1203 bool bundle = false) {
1204 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1205 new TestPortAllocator());
1206 int next_message_id = 0;
1207
1208 talk_base::scoped_ptr<TestClient> initiator(
1209 new TestClient(allocator.get(), &next_message_id,
1210 kInitiator, initiator_protocol,
1211 content_type,
1212 content_name_a, channel_name_a,
1213 content_name_b, channel_name_b));
1214 talk_base::scoped_ptr<TestClient> responder(
1215 new TestClient(allocator.get(), &next_message_id,
1216 kResponder, responder_protocol,
1217 content_type,
1218 content_name_a, channel_name_a,
1219 content_name_b, channel_name_b));
1220
1221 // Create Session and check channels and state.
1222 initiator->CreateSession();
1223 EXPECT_EQ(1U, initiator->session_created_count);
1224 EXPECT_EQ(kSessionId, initiator->session->id());
1225 EXPECT_EQ(initiator->session->local_name(), kInitiator);
1226 EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1227 initiator->session_state());
1228
1229 // See comment in CreateChannels about how we choose component IDs.
1230 int component_a = 1;
1231 int component_b = (content_name_a == content_name_b) ? 2 : 1;
1232 EXPECT_TRUE(initiator->HasTransport(content_name_a));
1233 EXPECT_TRUE(initiator->HasChannel(content_name_a, component_a));
1234 EXPECT_TRUE(initiator->HasTransport(content_name_b));
1235 EXPECT_TRUE(initiator->HasChannel(content_name_b, component_b));
1236
1237 // Initiate and expect initiate message sent.
1238 cricket::SessionDescription* offer = NewTestSessionDescription(
1239 gingle_content_type,
1240 content_name_a, content_type,
1241 content_name_b, content_type);
1242 if (bundle) {
1243 cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1244 group.AddContentName(content_name_a);
1245 group.AddContentName(content_name_b);
1246 EXPECT_TRUE(group.HasContentName(content_name_a));
1247 EXPECT_TRUE(group.HasContentName(content_name_b));
1248 offer->AddGroup(group);
1249 }
1250 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1251 EXPECT_EQ(initiator->session->remote_name(), kResponder);
1252 EXPECT_EQ(initiator->session->local_description(), offer);
1253
1254 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1255 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1256 initiator->session_state());
1257
1258 initiator->ExpectSentStanza(
1259 IqSet("0", kInitiator, kResponder, initiate_xml));
1260
1261 // Deliver the initiate. Expect ack and session created with
1262 // transports.
1263 responder->DeliverStanza(initiator->stanza());
1264 responder->ExpectSentStanza(
1265 IqAck("0", kResponder, kInitiator));
1266 EXPECT_EQ(0U, responder->sent_stanza_count());
1267
1268 EXPECT_EQ(1U, responder->session_created_count);
1269 EXPECT_EQ(kSessionId, responder->session->id());
1270 EXPECT_EQ(responder->session->local_name(), kResponder);
1271 EXPECT_EQ(responder->session->remote_name(), kInitiator);
1272 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1273 responder->session_state());
1274
1275 EXPECT_TRUE(responder->HasTransport(content_name_a));
1276 EXPECT_TRUE(responder->HasChannel(content_name_a, component_a));
1277 EXPECT_TRUE(responder->HasTransport(content_name_b));
1278 EXPECT_TRUE(responder->HasChannel(content_name_b, component_b));
1279
1280 // Expect transport-info message from initiator.
1281 // But don't send candidates until initiate ack is received.
1282 initiator->PrepareCandidates();
1283 WAIT(initiator->sent_stanza_count() > 0, 100);
1284 EXPECT_EQ(0U, initiator->sent_stanza_count());
1285 initiator->DeliverAckToLastStanza();
1286 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1287 initiator->ExpectSentStanza(
1288 IqSet("1", kInitiator, kResponder, transport_info_a_xml));
1289
1290 // Deliver transport-info and expect ack.
1291 responder->DeliverStanza(initiator->stanza());
1292 responder->ExpectSentStanza(
1293 IqAck("1", kResponder, kInitiator));
1294
1295 if (!transport_info_b_xml.empty()) {
1296 // Expect second transport-info message from initiator.
1297 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1298 initiator->ExpectSentStanza(
1299 IqSet("2", kInitiator, kResponder, transport_info_b_xml));
1300 EXPECT_EQ(0U, initiator->sent_stanza_count());
1301
1302 // Deliver second transport-info message and expect ack.
1303 responder->DeliverStanza(initiator->stanza());
1304 responder->ExpectSentStanza(
1305 IqAck("2", kResponder, kInitiator));
1306 } else {
1307 EXPECT_EQ(0U, initiator->sent_stanza_count());
1308 EXPECT_EQ(0U, responder->sent_stanza_count());
1309 initiator->SkipUnsentStanza();
1310 }
1311
1312 // Expect reply transport-info message from responder.
1313 responder->PrepareCandidates();
1314 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1315 responder->ExpectSentStanza(
1316 IqSet("3", kResponder, kInitiator, transport_info_reply_a_xml));
1317
1318 // Deliver reply transport-info and expect ack.
1319 initiator->DeliverStanza(responder->stanza());
1320 initiator->ExpectSentStanza(
1321 IqAck("3", kInitiator, kResponder));
1322
1323 if (!transport_info_reply_b_xml.empty()) {
1324 // Expect second reply transport-info message from responder.
1325 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1326 responder->ExpectSentStanza(
1327 IqSet("4", kResponder, kInitiator, transport_info_reply_b_xml));
1328 EXPECT_EQ(0U, responder->sent_stanza_count());
1329
1330 // Deliver second reply transport-info message and expect ack.
1331 initiator->DeliverStanza(responder->stanza());
1332 initiator->ExpectSentStanza(
1333 IqAck("4", kInitiator, kResponder));
1334 EXPECT_EQ(0U, initiator->sent_stanza_count());
1335 } else {
1336 EXPECT_EQ(0U, initiator->sent_stanza_count());
1337 EXPECT_EQ(0U, responder->sent_stanza_count());
1338 responder->SkipUnsentStanza();
1339 }
1340
1341 // The channels should be able to become writable at this point. This
1342 // requires pinging, so it may take a little while.
1343 EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1344 initiator->chan_a->readable(), kEventTimeout);
1345 EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1346 initiator->chan_b->readable(), kEventTimeout);
1347 EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1348 responder->chan_a->readable(), kEventTimeout);
1349 EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1350 responder->chan_b->readable(), kEventTimeout);
1351
1352 // Accept the session and expect accept stanza.
1353 cricket::SessionDescription* answer = NewTestSessionDescription(
1354 gingle_content_type,
1355 content_name_a, content_type,
1356 content_name_b, content_type);
1357 if (bundle) {
1358 cricket::ContentGroup group(cricket::GROUP_TYPE_BUNDLE);
1359 group.AddContentName(content_name_a);
1360 group.AddContentName(content_name_b);
1361 EXPECT_TRUE(group.HasContentName(content_name_a));
1362 EXPECT_TRUE(group.HasContentName(content_name_b));
1363 answer->AddGroup(group);
1364 }
1365 EXPECT_TRUE(responder->session->Accept(answer));
1366 EXPECT_EQ(responder->session->local_description(), answer);
1367
1368 responder->ExpectSentStanza(
1369 IqSet("5", kResponder, kInitiator, accept_xml));
1370
1371 EXPECT_EQ(0U, responder->sent_stanza_count());
1372
1373 // Deliver the accept message and expect an ack.
1374 initiator->DeliverStanza(responder->stanza());
1375 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1376 initiator->ExpectSentStanza(
1377 IqAck("5", kInitiator, kResponder));
1378 EXPECT_EQ(0U, initiator->sent_stanza_count());
1379
1380 // Both sessions should be in progress and have functioning
1381 // channels.
1382 EXPECT_EQ(resulting_protocol, initiator->session->current_protocol());
1383 EXPECT_EQ(resulting_protocol, responder->session->current_protocol());
1384 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1385 initiator->session_state(), kEventTimeout);
1386 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1387 responder->session_state(), kEventTimeout);
1388 if (bundle) {
1389 cricket::TransportChannel* initiator_chan_a = initiator->chan_a->channel;
1390 cricket::TransportChannel* initiator_chan_b = initiator->chan_b->channel;
1391
1392 // Since we know these are TransportChannelProxy, type cast it.
1393 cricket::TransportChannelProxy* initiator_proxy_chan_a =
1394 static_cast<cricket::TransportChannelProxy*>(initiator_chan_a);
1395 cricket::TransportChannelProxy* initiator_proxy_chan_b =
1396 static_cast<cricket::TransportChannelProxy*>(initiator_chan_b);
1397 EXPECT_TRUE(initiator_proxy_chan_a->impl() != NULL);
1398 EXPECT_TRUE(initiator_proxy_chan_b->impl() != NULL);
1399 EXPECT_EQ(initiator_proxy_chan_a->impl(), initiator_proxy_chan_b->impl());
1400
1401 cricket::TransportChannel* responder_chan_a = responder->chan_a->channel;
1402 cricket::TransportChannel* responder_chan_b = responder->chan_b->channel;
1403
1404 // Since we know these are TransportChannelProxy, type cast it.
1405 cricket::TransportChannelProxy* responder_proxy_chan_a =
1406 static_cast<cricket::TransportChannelProxy*>(responder_chan_a);
1407 cricket::TransportChannelProxy* responder_proxy_chan_b =
1408 static_cast<cricket::TransportChannelProxy*>(responder_chan_b);
1409 EXPECT_TRUE(responder_proxy_chan_a->impl() != NULL);
1410 EXPECT_TRUE(responder_proxy_chan_b->impl() != NULL);
1411 EXPECT_EQ(responder_proxy_chan_a->impl(), responder_proxy_chan_b->impl());
1412 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001413 TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(),
1414 responder->chan_a.get(), responder->chan_b.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001415
1416 if (resulting_protocol == PROTOCOL_JINGLE) {
1417 // Deliver a description-info message to the initiator and check if the
1418 // content description changes.
1419 EXPECT_EQ(0U, initiator->session_remote_description_update_count);
1420
1421 const cricket::SessionDescription* old_session_desc =
1422 initiator->session->remote_description();
1423 const cricket::ContentInfo* old_content_a =
1424 old_session_desc->GetContentByName(content_name_a);
1425 const cricket::ContentDescription* old_content_desc_a =
1426 old_content_a->description;
1427 const cricket::ContentInfo* old_content_b =
1428 old_session_desc->GetContentByName(content_name_b);
1429 const cricket::ContentDescription* old_content_desc_b =
1430 old_content_b->description;
1431 EXPECT_TRUE(old_content_desc_a != NULL);
1432 EXPECT_TRUE(old_content_desc_b != NULL);
1433
1434 LOG(LS_INFO) << "A " << old_content_a->name;
1435 LOG(LS_INFO) << "B " << old_content_b->name;
1436
1437 std::string description_info_xml =
1438 JingleDescriptionInfoXml(content_name_a, content_type);
1439 initiator->DeliverStanza(
1440 IqSet("6", kResponder, kInitiator, description_info_xml));
1441 responder->SkipUnsentStanza();
1442 EXPECT_EQ(1U, initiator->session_remote_description_update_count);
1443
1444 const cricket::SessionDescription* new_session_desc =
1445 initiator->session->remote_description();
1446 const cricket::ContentInfo* new_content_a =
1447 new_session_desc->GetContentByName(content_name_a);
1448 const cricket::ContentDescription* new_content_desc_a =
1449 new_content_a->description;
1450 const cricket::ContentInfo* new_content_b =
1451 new_session_desc->GetContentByName(content_name_b);
1452 const cricket::ContentDescription* new_content_desc_b =
1453 new_content_b->description;
1454 EXPECT_TRUE(new_content_desc_a != NULL);
1455 EXPECT_TRUE(new_content_desc_b != NULL);
1456
1457 // TODO: We used to replace contents from an update, but
1458 // that no longer works with partial updates. We need to figure out
1459 // a way to merge patial updates into contents. For now, users of
1460 // Session should listen to SignalRemoteDescriptionUpdate and handle
1461 // updates. They should not expect remote_description to be the
1462 // latest value.
1463 // See session.cc OnDescriptionInfoMessage.
1464
1465 // EXPECT_NE(old_content_desc_a, new_content_desc_a);
1466
1467 // if (content_name_a != content_name_b) {
1468 // // If content_name_a != content_name_b, then b's content description
1469 // // should not have changed since the description-info message only
1470 // // contained an update for content_name_a.
1471 // EXPECT_EQ(old_content_desc_b, new_content_desc_b);
1472 // }
1473
1474 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1475 initiator->ExpectSentStanza(
1476 IqAck("6", kInitiator, kResponder));
1477 EXPECT_EQ(0U, initiator->sent_stanza_count());
1478 } else {
1479 responder->SkipUnsentStanza();
1480 }
1481
1482 initiator->session->Terminate();
1483 initiator->ExpectSentStanza(
1484 IqSet("7", kInitiator, kResponder,
1485 TerminateXml(resulting_protocol,
1486 cricket::STR_TERMINATE_SUCCESS)));
1487
1488 responder->DeliverStanza(initiator->stanza());
1489 responder->ExpectSentStanza(
1490 IqAck("7", kResponder, kInitiator));
1491 EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
1492 initiator->session_state());
1493 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
1494 responder->session_state());
1495 }
1496
1497 // Test an initiate with other content, called "main".
1498 void TestOtherContent(SignalingProtocol initiator_protocol,
1499 SignalingProtocol responder_protocol,
1500 SignalingProtocol resulting_protocol) {
1501 std::string content_name = "main";
1502 std::string content_type = "http://oink.splat/session";
1503 std::string content_name_a = content_name;
1504 std::string channel_name_a = "rtp";
1505 std::string content_name_b = content_name;
1506 std::string channel_name_b = "rtcp";
1507 std::string initiate_xml = InitiateXml(
1508 initiator_protocol,
1509 content_name_a, content_type);
1510 std::string transport_info_a_xml = TransportInfo4Xml(
1511 initiator_protocol, content_name,
1512 channel_name_a, 0, 1,
1513 channel_name_b, 2, 3);
1514 std::string transport_info_b_xml = "";
1515 std::string transport_info_reply_a_xml = TransportInfo4Xml(
1516 resulting_protocol, content_name,
1517 channel_name_a, 4, 5,
1518 channel_name_b, 6, 7);
1519 std::string transport_info_reply_b_xml = "";
1520 std::string accept_xml = AcceptXml(
1521 resulting_protocol,
1522 content_name_a, content_type);
1523
1524
1525 TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1526 content_type,
1527 content_type,
1528 content_name_a, channel_name_a,
1529 content_name_b, channel_name_b,
1530 initiate_xml,
1531 transport_info_a_xml, transport_info_b_xml,
1532 transport_info_reply_a_xml, transport_info_reply_b_xml,
1533 accept_xml);
1534 }
1535
1536 // Test an initiate with audio content.
1537 void TestAudioContent(SignalingProtocol initiator_protocol,
1538 SignalingProtocol responder_protocol,
1539 SignalingProtocol resulting_protocol) {
1540 std::string gingle_content_type = cricket::NS_GINGLE_AUDIO;
1541 std::string content_name = cricket::CN_AUDIO;
1542 std::string content_type = cricket::NS_JINGLE_RTP;
1543 std::string channel_name_a = "rtp";
1544 std::string channel_name_b = "rtcp";
1545 std::string initiate_xml = InitiateXml(
1546 initiator_protocol,
1547 gingle_content_type,
1548 content_name, content_type,
1549 "", "");
1550 std::string transport_info_a_xml = TransportInfo4Xml(
1551 initiator_protocol, content_name,
1552 channel_name_a, 0, 1,
1553 channel_name_b, 2, 3);
1554 std::string transport_info_b_xml = "";
1555 std::string transport_info_reply_a_xml = TransportInfo4Xml(
1556 resulting_protocol, content_name,
1557 channel_name_a, 4, 5,
1558 channel_name_b, 6, 7);
1559 std::string transport_info_reply_b_xml = "";
1560 std::string accept_xml = AcceptXml(
1561 resulting_protocol,
1562 gingle_content_type,
1563 content_name, content_type,
1564 "", "");
1565
1566
1567 TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1568 gingle_content_type,
1569 content_type,
1570 content_name, channel_name_a,
1571 content_name, channel_name_b,
1572 initiate_xml,
1573 transport_info_a_xml, transport_info_b_xml,
1574 transport_info_reply_a_xml, transport_info_reply_b_xml,
1575 accept_xml);
1576 }
1577
1578 // Since media content is "split" into two contents (audio and
1579 // video), we need to treat it special.
1580 void TestVideoContents(SignalingProtocol initiator_protocol,
1581 SignalingProtocol responder_protocol,
1582 SignalingProtocol resulting_protocol) {
1583 std::string content_type = cricket::NS_JINGLE_RTP;
1584 std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
1585 std::string content_name_a = cricket::CN_AUDIO;
1586 std::string channel_name_a = "rtp";
1587 std::string content_name_b = cricket::CN_VIDEO;
1588 std::string channel_name_b = "video_rtp";
1589
1590 std::string initiate_xml = InitiateXml(
1591 initiator_protocol,
1592 gingle_content_type,
1593 content_name_a, content_type,
1594 content_name_b, content_type);
1595 std::string transport_info_a_xml = TransportInfo2Xml(
1596 initiator_protocol, content_name_a,
1597 channel_name_a, 0, 1);
1598 std::string transport_info_b_xml = TransportInfo2Xml(
1599 initiator_protocol, content_name_b,
1600 channel_name_b, 2, 3);
1601 std::string transport_info_reply_a_xml = TransportInfo2Xml(
1602 resulting_protocol, content_name_a,
1603 channel_name_a, 4, 5);
1604 std::string transport_info_reply_b_xml = TransportInfo2Xml(
1605 resulting_protocol, content_name_b,
1606 channel_name_b, 6, 7);
1607 std::string accept_xml = AcceptXml(
1608 resulting_protocol,
1609 gingle_content_type,
1610 content_name_a, content_type,
1611 content_name_b, content_type);
1612
1613 TestSession(initiator_protocol, responder_protocol, resulting_protocol,
1614 gingle_content_type,
1615 content_type,
1616 content_name_a, channel_name_a,
1617 content_name_b, channel_name_b,
1618 initiate_xml,
1619 transport_info_a_xml, transport_info_b_xml,
1620 transport_info_reply_a_xml, transport_info_reply_b_xml,
1621 accept_xml);
1622 }
1623
1624 void TestBadRedirect(SignalingProtocol protocol) {
1625 std::string content_name = "main";
1626 std::string content_type = "http://oink.splat/session";
1627 std::string channel_name_a = "chana";
1628 std::string channel_name_b = "chanb";
1629 std::string initiate_xml = InitiateXml(
1630 protocol, content_name, content_type);
1631 std::string transport_info_xml = TransportInfo4Xml(
1632 protocol, content_name,
1633 channel_name_a, 0, 1,
1634 channel_name_b, 2, 3);
1635 std::string transport_info_reply_xml = TransportInfo4Xml(
1636 protocol, content_name,
1637 channel_name_a, 4, 5,
1638 channel_name_b, 6, 7);
1639 std::string accept_xml = AcceptXml(
1640 protocol, content_name, content_type);
1641 std::string responder_full = kResponder + "/full";
1642
1643 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1644 new TestPortAllocator());
1645 int next_message_id = 0;
1646
1647 talk_base::scoped_ptr<TestClient> initiator(
1648 new TestClient(allocator.get(), &next_message_id,
1649 kInitiator, protocol,
1650 content_type,
1651 content_name, channel_name_a,
1652 content_name, channel_name_b));
1653
1654 talk_base::scoped_ptr<TestClient> responder(
1655 new TestClient(allocator.get(), &next_message_id,
1656 responder_full, protocol,
1657 content_type,
1658 content_name, channel_name_a,
1659 content_name, channel_name_b));
1660
1661 // Create Session and check channels and state.
1662 initiator->CreateSession();
1663 EXPECT_EQ(1U, initiator->session_created_count);
1664 EXPECT_EQ(kSessionId, initiator->session->id());
1665 EXPECT_EQ(initiator->session->local_name(), kInitiator);
1666 EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1667 initiator->session_state());
1668
1669 EXPECT_TRUE(initiator->HasChannel(content_name, 1));
1670 EXPECT_TRUE(initiator->HasChannel(content_name, 2));
1671
1672 // Initiate and expect initiate message sent.
1673 cricket::SessionDescription* offer = NewTestSessionDescription(
1674 content_name, content_type);
1675 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1676 EXPECT_EQ(initiator->session->remote_name(), kResponder);
1677 EXPECT_EQ(initiator->session->local_description(), offer);
1678
1679 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1680 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1681 initiator->session_state());
1682 initiator->ExpectSentStanza(
1683 IqSet("0", kInitiator, kResponder, initiate_xml));
1684
1685 // Expect transport-info message from initiator.
1686 initiator->DeliverAckToLastStanza();
1687 initiator->PrepareCandidates();
1688 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1689 initiator->ExpectSentStanza(
1690 IqSet("1", kInitiator, kResponder, transport_info_xml));
1691
1692 // Send an unauthorized redirect to the initiator and expect it be ignored.
1693 initiator->blow_up_on_error = false;
1694 const buzz::XmlElement* initiate_stanza = initiator->stanza();
1695 talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
1696 buzz::XmlElement::ForStr(
1697 IqError("ER", kResponder, kInitiator,
1698 RedirectXml(protocol, initiate_xml, "not@allowed.com"))));
1699 initiator->session_manager->OnFailedSend(
1700 initiate_stanza, redirect_stanza.get());
1701 EXPECT_EQ(initiator->session->remote_name(), kResponder);
1702 initiator->blow_up_on_error = true;
1703 EXPECT_EQ(initiator->error_count, 1);
1704 }
1705
1706 void TestGoodRedirect(SignalingProtocol protocol) {
1707 std::string content_name = "main";
1708 std::string content_type = "http://oink.splat/session";
1709 std::string channel_name_a = "chana";
1710 std::string channel_name_b = "chanb";
1711 std::string initiate_xml = InitiateXml(
1712 protocol, content_name, content_type);
1713 std::string transport_info_xml = TransportInfo4Xml(
1714 protocol, content_name,
1715 channel_name_a, 0, 1,
1716 channel_name_b, 2, 3);
1717 std::string transport_info_reply_xml = TransportInfo4Xml(
1718 protocol, content_name,
1719 channel_name_a, 4, 5,
1720 channel_name_b, 6, 7);
1721 std::string accept_xml = AcceptXml(
1722 protocol, content_name, content_type);
1723 std::string responder_full = kResponder + "/full";
1724
1725 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1726 new TestPortAllocator());
1727 int next_message_id = 0;
1728
1729 talk_base::scoped_ptr<TestClient> initiator(
1730 new TestClient(allocator.get(), &next_message_id,
1731 kInitiator, protocol,
1732 content_type,
1733 content_name, channel_name_a,
1734 content_name, channel_name_b));
1735
1736 talk_base::scoped_ptr<TestClient> responder(
1737 new TestClient(allocator.get(), &next_message_id,
1738 responder_full, protocol,
1739 content_type,
1740 content_name, channel_name_a,
1741 content_name, channel_name_b));
1742
1743 // Create Session and check channels and state.
1744 initiator->CreateSession();
1745 EXPECT_EQ(1U, initiator->session_created_count);
1746 EXPECT_EQ(kSessionId, initiator->session->id());
1747 EXPECT_EQ(initiator->session->local_name(), kInitiator);
1748 EXPECT_EQ(cricket::BaseSession::STATE_INIT,
1749 initiator->session_state());
1750
1751 EXPECT_TRUE(initiator->HasChannel(content_name, 1));
1752 EXPECT_TRUE(initiator->HasChannel(content_name, 2));
1753
1754 // Initiate and expect initiate message sent.
1755 cricket::SessionDescription* offer = NewTestSessionDescription(
1756 content_name, content_type);
1757 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1758 EXPECT_EQ(initiator->session->remote_name(), kResponder);
1759 EXPECT_EQ(initiator->session->local_description(), offer);
1760
1761 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1762 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1763 initiator->session_state());
1764 initiator->ExpectSentStanza(
1765 IqSet("0", kInitiator, kResponder, initiate_xml));
1766
1767 // Expect transport-info message from initiator.
1768 initiator->DeliverAckToLastStanza();
1769 initiator->PrepareCandidates();
1770 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1771 initiator->ExpectSentStanza(
1772 IqSet("1", kInitiator, kResponder, transport_info_xml));
1773
1774 // Send a redirect to the initiator and expect all of the message
1775 // to be resent.
1776 const buzz::XmlElement* initiate_stanza = initiator->stanza();
1777 talk_base::scoped_ptr<buzz::XmlElement> redirect_stanza(
1778 buzz::XmlElement::ForStr(
1779 IqError("ER2", kResponder, kInitiator,
1780 RedirectXml(protocol, initiate_xml, responder_full))));
1781 initiator->session_manager->OnFailedSend(
1782 initiate_stanza, redirect_stanza.get());
1783 EXPECT_EQ(initiator->session->remote_name(), responder_full);
1784
1785 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1786 initiator->ExpectSentStanza(
1787 IqSet("2", kInitiator, responder_full, initiate_xml));
1788 initiator->ExpectSentStanza(
1789 IqSet("3", kInitiator, responder_full, transport_info_xml));
1790
1791 // Deliver the initiate. Expect ack and session created with
1792 // transports.
1793 responder->DeliverStanza(
1794 IqSet("2", kInitiator, responder_full, initiate_xml));
1795 responder->ExpectSentStanza(
1796 IqAck("2", responder_full, kInitiator));
1797 EXPECT_EQ(0U, responder->sent_stanza_count());
1798
1799 EXPECT_EQ(1U, responder->session_created_count);
1800 EXPECT_EQ(kSessionId, responder->session->id());
1801 EXPECT_EQ(responder->session->local_name(), responder_full);
1802 EXPECT_EQ(responder->session->remote_name(), kInitiator);
1803 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1804 responder->session_state());
1805
1806 EXPECT_TRUE(responder->HasChannel(content_name, 1));
1807 EXPECT_TRUE(responder->HasChannel(content_name, 2));
1808
1809 // Deliver transport-info and expect ack.
1810 responder->DeliverStanza(
1811 IqSet("3", kInitiator, responder_full, transport_info_xml));
1812 responder->ExpectSentStanza(
1813 IqAck("3", responder_full, kInitiator));
1814
1815 // Expect reply transport-infos sent to new remote JID
1816 responder->PrepareCandidates();
1817 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1818 responder->ExpectSentStanza(
1819 IqSet("4", responder_full, kInitiator, transport_info_reply_xml));
1820
1821 initiator->DeliverStanza(responder->stanza());
1822 initiator->ExpectSentStanza(
1823 IqAck("4", kInitiator, responder_full));
1824
1825 // The channels should be able to become writable at this point. This
1826 // requires pinging, so it may take a little while.
1827 EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1828 initiator->chan_a->readable(), kEventTimeout);
1829 EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1830 initiator->chan_b->readable(), kEventTimeout);
1831 EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1832 responder->chan_a->readable(), kEventTimeout);
1833 EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1834 responder->chan_b->readable(), kEventTimeout);
1835
1836 // Accept the session and expect accept stanza.
1837 cricket::SessionDescription* answer = NewTestSessionDescription(
1838 content_name, content_type);
1839 EXPECT_TRUE(responder->session->Accept(answer));
1840 EXPECT_EQ(responder->session->local_description(), answer);
1841
1842 responder->ExpectSentStanza(
1843 IqSet("5", responder_full, kInitiator, accept_xml));
1844 EXPECT_EQ(0U, responder->sent_stanza_count());
1845
1846 // Deliver the accept message and expect an ack.
1847 initiator->DeliverStanza(responder->stanza());
1848 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1849 initiator->ExpectSentStanza(
1850 IqAck("5", kInitiator, responder_full));
1851 EXPECT_EQ(0U, initiator->sent_stanza_count());
1852
1853 // Both sessions should be in progress and have functioning
1854 // channels.
1855 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1856 initiator->session_state(), kEventTimeout);
1857 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1858 responder->session_state(), kEventTimeout);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001859 TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(),
1860 responder->chan_a.get(), responder->chan_b.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001861 }
1862
1863 void TestCandidatesInInitiateAndAccept(const std::string& test_name) {
1864 std::string content_name = "main";
1865 std::string content_type = "http://oink.splat/session";
1866 std::string channel_name_a = "rtp";
1867 std::string channel_name_b = "rtcp";
1868 cricket::SignalingProtocol protocol = PROTOCOL_JINGLE;
1869
1870 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
1871 new TestPortAllocator());
1872 int next_message_id = 0;
1873
1874 talk_base::scoped_ptr<TestClient> initiator(
1875 new TestClient(allocator.get(), &next_message_id,
1876 kInitiator, protocol,
1877 content_type,
1878 content_name, channel_name_a,
1879 content_name, channel_name_b));
1880
1881 talk_base::scoped_ptr<TestClient> responder(
1882 new TestClient(allocator.get(), &next_message_id,
1883 kResponder, protocol,
1884 content_type,
1885 content_name, channel_name_a,
1886 content_name, channel_name_b));
1887
1888 // Create Session and check channels and state.
1889 initiator->CreateSession();
1890 EXPECT_TRUE(initiator->HasTransport(content_name));
1891 EXPECT_TRUE(initiator->HasChannel(content_name, 1));
1892 EXPECT_TRUE(initiator->HasTransport(content_name));
1893 EXPECT_TRUE(initiator->HasChannel(content_name, 2));
1894
1895 // Initiate and expect initiate message sent.
1896 cricket::SessionDescription* offer = NewTestSessionDescription(
1897 content_name, content_type);
1898 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
1899
1900 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1901 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
1902 initiator->session_state());
1903 initiator->ExpectSentStanza(
1904 IqSet("0", kInitiator, kResponder,
1905 InitiateXml(protocol, content_name, content_type)));
1906
1907 // Fake the delivery the initiate and candidates together.
1908 responder->DeliverStanza(
1909 IqSet("A", kInitiator, kResponder,
1910 JingleInitiateActionXml(
1911 JingleContentXml(
1912 content_name, content_type, kTransportType,
1913 P2pCandidateXml(channel_name_a, 0) +
1914 P2pCandidateXml(channel_name_a, 1) +
1915 P2pCandidateXml(channel_name_b, 2) +
1916 P2pCandidateXml(channel_name_b, 3)))));
1917 responder->ExpectSentStanza(
1918 IqAck("A", kResponder, kInitiator));
1919 EXPECT_EQ(0U, responder->sent_stanza_count());
1920
1921 EXPECT_EQ(1U, responder->session_created_count);
1922 EXPECT_EQ(kSessionId, responder->session->id());
1923 EXPECT_EQ(responder->session->local_name(), kResponder);
1924 EXPECT_EQ(responder->session->remote_name(), kInitiator);
1925 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
1926 responder->session_state());
1927
1928 EXPECT_TRUE(responder->HasTransport(content_name));
1929 EXPECT_TRUE(responder->HasChannel(content_name, 1));
1930 EXPECT_TRUE(responder->HasTransport(content_name));
1931 EXPECT_TRUE(responder->HasChannel(content_name, 2));
1932
1933 // Expect transport-info message from initiator.
1934 // But don't send candidates until initiate ack is received.
1935 initiator->DeliverAckToLastStanza();
1936 initiator->PrepareCandidates();
1937 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1938 initiator->ExpectSentStanza(
1939 IqSet("1", kInitiator, kResponder,
1940 TransportInfo4Xml(protocol, content_name,
1941 channel_name_a, 0, 1,
1942 channel_name_b, 2, 3)));
1943
1944 responder->PrepareCandidates();
1945 EXPECT_TRUE_WAIT(responder->sent_stanza_count() > 0, kEventTimeout);
1946 responder->ExpectSentStanza(
1947 IqSet("2", kResponder, kInitiator,
1948 TransportInfo4Xml(protocol, content_name,
1949 channel_name_a, 4, 5,
1950 channel_name_b, 6, 7)));
1951
1952 // Accept the session and expect accept stanza.
1953 cricket::SessionDescription* answer = NewTestSessionDescription(
1954 content_name, content_type);
1955 EXPECT_TRUE(responder->session->Accept(answer));
1956
1957 responder->ExpectSentStanza(
1958 IqSet("3", kResponder, kInitiator,
1959 AcceptXml(protocol, content_name, content_type)));
1960 EXPECT_EQ(0U, responder->sent_stanza_count());
1961
1962 // Fake the delivery the accept and candidates together.
1963 initiator->DeliverStanza(
1964 IqSet("B", kResponder, kInitiator,
1965 JingleActionXml("session-accept",
1966 JingleContentXml(
1967 content_name, content_type, kTransportType,
1968 P2pCandidateXml(channel_name_a, 4) +
1969 P2pCandidateXml(channel_name_a, 5) +
1970 P2pCandidateXml(channel_name_b, 6) +
1971 P2pCandidateXml(channel_name_b, 7)))));
1972 EXPECT_TRUE_WAIT(initiator->sent_stanza_count() > 0, kEventTimeout);
1973 initiator->ExpectSentStanza(
1974 IqAck("B", kInitiator, kResponder));
1975 EXPECT_EQ(0U, initiator->sent_stanza_count());
1976
1977 // The channels should be able to become writable at this point. This
1978 // requires pinging, so it may take a little while.
1979 EXPECT_TRUE_WAIT(initiator->chan_a->writable() &&
1980 initiator->chan_a->readable(), kEventTimeout);
1981 EXPECT_TRUE_WAIT(initiator->chan_b->writable() &&
1982 initiator->chan_b->readable(), kEventTimeout);
1983 EXPECT_TRUE_WAIT(responder->chan_a->writable() &&
1984 responder->chan_a->readable(), kEventTimeout);
1985 EXPECT_TRUE_WAIT(responder->chan_b->writable() &&
1986 responder->chan_b->readable(), kEventTimeout);
1987
1988
1989 // Both sessions should be in progress and have functioning
1990 // channels.
1991 EXPECT_EQ(protocol, initiator->session->current_protocol());
1992 EXPECT_EQ(protocol, responder->session->current_protocol());
1993 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1994 initiator->session_state(), kEventTimeout);
1995 EXPECT_EQ_WAIT(cricket::BaseSession::STATE_INPROGRESS,
1996 responder->session_state(), kEventTimeout);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001997 TestSendRecv(initiator->chan_a.get(), initiator->chan_b.get(),
1998 responder->chan_a.get(), responder->chan_b.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001999 }
2000
2001 // Tests that when an initiator terminates right after initiate,
2002 // everything behaves correctly.
2003 void TestEarlyTerminationFromInitiator(SignalingProtocol protocol) {
2004 std::string content_name = "main";
2005 std::string content_type = "http://oink.splat/session";
2006
2007 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2008 new TestPortAllocator());
2009 int next_message_id = 0;
2010
2011 talk_base::scoped_ptr<TestClient> initiator(
2012 new TestClient(allocator.get(), &next_message_id,
2013 kInitiator, protocol,
2014 content_type,
2015 content_name, "a",
2016 content_name, "b"));
2017
2018 talk_base::scoped_ptr<TestClient> responder(
2019 new TestClient(allocator.get(), &next_message_id,
2020 kResponder, protocol,
2021 content_type,
2022 content_name, "a",
2023 content_name, "b"));
2024
2025 // Send initiate
2026 initiator->CreateSession();
2027 EXPECT_TRUE(initiator->session->Initiate(
2028 kResponder, NewTestSessionDescription(content_name, content_type)));
2029 initiator->ExpectSentStanza(
2030 IqSet("0", kInitiator, kResponder,
2031 InitiateXml(protocol, content_name, content_type)));
2032 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
2033 initiator->session_state());
2034
2035 responder->DeliverStanza(initiator->stanza());
2036 responder->ExpectSentStanza(
2037 IqAck("0", kResponder, kInitiator));
2038 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDINITIATE,
2039 responder->session_state());
2040
2041 initiator->session->TerminateWithReason(cricket::STR_TERMINATE_ERROR);
2042 initiator->ExpectSentStanza(
2043 IqSet("1", kInitiator, kResponder,
2044 TerminateXml(protocol, cricket::STR_TERMINATE_ERROR)));
2045 EXPECT_EQ(cricket::BaseSession::STATE_SENTTERMINATE,
2046 initiator->session_state());
2047
2048 responder->DeliverStanza(initiator->stanza());
2049 responder->ExpectSentStanza(
2050 IqAck("1", kResponder, kInitiator));
2051 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
2052 responder->session_state());
2053 }
2054
2055 // Tests that when the responder rejects, everything behaves
2056 // correctly.
2057 void TestRejection(SignalingProtocol protocol) {
2058 std::string content_name = "main";
2059 std::string content_type = "http://oink.splat/session";
2060
2061 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2062 new TestPortAllocator());
2063 int next_message_id = 0;
2064
2065 talk_base::scoped_ptr<TestClient> initiator(
2066 new TestClient(allocator.get(), &next_message_id,
2067 kInitiator, protocol,
2068 content_type,
2069 content_name, "a",
2070 content_name, "b"));
2071
2072 // Send initiate
2073 initiator->CreateSession();
2074 EXPECT_TRUE(initiator->session->Initiate(
2075 kResponder, NewTestSessionDescription(content_name, content_type)));
2076 initiator->ExpectSentStanza(
2077 IqSet("0", kInitiator, kResponder,
2078 InitiateXml(protocol, content_name, content_type)));
2079 EXPECT_EQ(cricket::BaseSession::STATE_SENTINITIATE,
2080 initiator->session_state());
2081
2082 initiator->DeliverStanza(
2083 IqSet("1", kResponder, kInitiator,
2084 RejectXml(protocol, cricket::STR_TERMINATE_ERROR)));
2085 initiator->ExpectSentStanza(
2086 IqAck("1", kInitiator, kResponder));
2087 if (protocol == PROTOCOL_JINGLE) {
2088 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDTERMINATE,
2089 initiator->session_state());
2090 } else {
2091 EXPECT_EQ(cricket::BaseSession::STATE_RECEIVEDREJECT,
2092 initiator->session_state());
2093 }
2094 }
2095
2096 void TestTransportMux() {
2097 SignalingProtocol initiator_protocol = PROTOCOL_JINGLE;
2098 SignalingProtocol responder_protocol = PROTOCOL_JINGLE;
2099 SignalingProtocol resulting_protocol = PROTOCOL_JINGLE;
2100 std::string content_type = cricket::NS_JINGLE_RTP;
2101 std::string gingle_content_type = cricket::NS_GINGLE_VIDEO;
2102 std::string content_name_a = cricket::CN_AUDIO;
2103 std::string channel_name_a = "rtp";
2104 std::string content_name_b = cricket::CN_VIDEO;
2105 std::string channel_name_b = "video_rtp";
2106
2107 std::string initiate_xml = InitiateXml(
2108 initiator_protocol,
2109 gingle_content_type,
2110 content_name_a, content_type,
2111 content_name_b, content_type, true);
2112 std::string transport_info_a_xml = TransportInfo2Xml(
2113 initiator_protocol, content_name_a,
2114 channel_name_a, 0, 1);
2115 std::string transport_info_b_xml = TransportInfo2Xml(
2116 initiator_protocol, content_name_b,
2117 channel_name_b, 2, 3);
2118 std::string transport_info_reply_a_xml = TransportInfo2Xml(
2119 resulting_protocol, content_name_a,
2120 channel_name_a, 4, 5);
2121 std::string transport_info_reply_b_xml = TransportInfo2Xml(
2122 resulting_protocol, content_name_b,
2123 channel_name_b, 6, 7);
2124 std::string accept_xml = AcceptXml(
2125 resulting_protocol,
2126 gingle_content_type,
2127 content_name_a, content_type,
2128 content_name_b, content_type, true);
2129
2130 TestSession(initiator_protocol, responder_protocol, resulting_protocol,
2131 gingle_content_type,
2132 content_type,
2133 content_name_a, channel_name_a,
2134 content_name_b, channel_name_b,
2135 initiate_xml,
2136 transport_info_a_xml, transport_info_b_xml,
2137 transport_info_reply_a_xml, transport_info_reply_b_xml,
2138 accept_xml,
2139 true);
2140 }
2141
2142 void TestSendDescriptionInfo() {
2143 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2144 new TestPortAllocator());
2145 int next_message_id = 0;
2146
2147 std::string content_name = "content-name";
2148 std::string content_type = "content-type";
2149 talk_base::scoped_ptr<TestClient> initiator(
2150 new TestClient(allocator.get(), &next_message_id,
2151 kInitiator, PROTOCOL_JINGLE,
2152 content_type,
2153 content_name, "",
2154 "", ""));
2155
2156 initiator->CreateSession();
2157 cricket::SessionDescription* offer = NewTestSessionDescription(
2158 content_name, content_type);
2159 std::string initiate_xml = InitiateXml(
2160 PROTOCOL_JINGLE, content_name, content_type);
2161
2162 cricket::ContentInfos contents;
2163 TestContentDescription content(content_type, content_type);
2164 contents.push_back(
2165 cricket::ContentInfo(content_name, content_type, &content));
2166 std::string description_info_xml = JingleDescriptionInfoXml(
2167 content_name, content_type);
2168
2169 EXPECT_TRUE(initiator->session->Initiate(kResponder, offer));
2170 initiator->ExpectSentStanza(
2171 IqSet("0", kInitiator, kResponder, initiate_xml));
2172
2173 EXPECT_TRUE(initiator->session->SendDescriptionInfoMessage(contents));
2174 initiator->ExpectSentStanza(
2175 IqSet("1", kInitiator, kResponder, description_info_xml));
2176 }
2177
2178 void DoTestSignalNewDescription(
2179 TestClient* client,
2180 cricket::BaseSession::State state,
2181 cricket::ContentAction expected_content_action,
2182 cricket::ContentSource expected_content_source) {
2183 // Clean up before the new test.
2184 client->new_local_description = false;
2185 client->new_remote_description = false;
2186
2187 client->SetSessionState(state);
2188 EXPECT_EQ((expected_content_source == cricket::CS_LOCAL),
2189 client->new_local_description);
2190 EXPECT_EQ((expected_content_source == cricket::CS_REMOTE),
2191 client->new_remote_description);
2192 EXPECT_EQ(expected_content_action, client->last_content_action);
2193 EXPECT_EQ(expected_content_source, client->last_content_source);
2194 }
2195
2196 void TestCallerSignalNewDescription() {
2197 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2198 new TestPortAllocator());
2199 int next_message_id = 0;
2200
2201 std::string content_name = "content-name";
2202 std::string content_type = "content-type";
2203 talk_base::scoped_ptr<TestClient> initiator(
2204 new TestClient(allocator.get(), &next_message_id,
2205 kInitiator, PROTOCOL_JINGLE,
2206 content_type,
2207 content_name, "",
2208 "", ""));
2209
2210 initiator->CreateSession();
2211
2212 // send offer -> send update offer ->
2213 // receive pr answer -> receive update pr answer ->
2214 // receive answer
2215 DoTestSignalNewDescription(
2216 initiator.get(), cricket::BaseSession::STATE_SENTINITIATE,
2217 cricket::CA_OFFER, cricket::CS_LOCAL);
2218
2219 DoTestSignalNewDescription(
2220 initiator.get(), cricket::BaseSession::STATE_SENTINITIATE,
2221 cricket::CA_OFFER, cricket::CS_LOCAL);
2222
2223 DoTestSignalNewDescription(
2224 initiator.get(), cricket::BaseSession::STATE_RECEIVEDPRACCEPT,
2225 cricket::CA_PRANSWER, cricket::CS_REMOTE);
2226
2227 DoTestSignalNewDescription(
2228 initiator.get(), cricket::BaseSession::STATE_RECEIVEDPRACCEPT,
2229 cricket::CA_PRANSWER, cricket::CS_REMOTE);
2230
2231 DoTestSignalNewDescription(
2232 initiator.get(), cricket::BaseSession::STATE_RECEIVEDACCEPT,
2233 cricket::CA_ANSWER, cricket::CS_REMOTE);
2234 }
2235
2236 void TestCalleeSignalNewDescription() {
2237 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2238 new TestPortAllocator());
2239 int next_message_id = 0;
2240
2241 std::string content_name = "content-name";
2242 std::string content_type = "content-type";
2243 talk_base::scoped_ptr<TestClient> initiator(
2244 new TestClient(allocator.get(), &next_message_id,
2245 kInitiator, PROTOCOL_JINGLE,
2246 content_type,
2247 content_name, "",
2248 "", ""));
2249
2250 initiator->CreateSession();
2251
2252 // receive offer -> receive update offer ->
2253 // send pr answer -> send update pr answer ->
2254 // send answer
2255 DoTestSignalNewDescription(
2256 initiator.get(), cricket::BaseSession::STATE_RECEIVEDINITIATE,
2257 cricket::CA_OFFER, cricket::CS_REMOTE);
2258
2259 DoTestSignalNewDescription(
2260 initiator.get(), cricket::BaseSession::STATE_RECEIVEDINITIATE,
2261 cricket::CA_OFFER, cricket::CS_REMOTE);
2262
2263 DoTestSignalNewDescription(
2264 initiator.get(), cricket::BaseSession::STATE_SENTPRACCEPT,
2265 cricket::CA_PRANSWER, cricket::CS_LOCAL);
2266
2267 DoTestSignalNewDescription(
2268 initiator.get(), cricket::BaseSession::STATE_SENTPRACCEPT,
2269 cricket::CA_PRANSWER, cricket::CS_LOCAL);
2270
2271 DoTestSignalNewDescription(
2272 initiator.get(), cricket::BaseSession::STATE_SENTACCEPT,
2273 cricket::CA_ANSWER, cricket::CS_LOCAL);
2274 }
2275
2276 void TestGetTransportStats() {
2277 talk_base::scoped_ptr<cricket::PortAllocator> allocator(
2278 new TestPortAllocator());
2279 int next_message_id = 0;
2280
2281 std::string content_name = "content-name";
2282 std::string content_type = "content-type";
2283 talk_base::scoped_ptr<TestClient> initiator(
2284 new TestClient(allocator.get(), &next_message_id,
2285 kInitiator, PROTOCOL_JINGLE,
2286 content_type,
2287 content_name, "",
2288 "", ""));
2289 initiator->CreateSession();
2290
2291 cricket::SessionStats stats;
2292 EXPECT_TRUE(initiator->session->GetStats(&stats));
2293 // At initiation, there are 2 transports.
2294 EXPECT_EQ(2ul, stats.proxy_to_transport.size());
2295 EXPECT_EQ(2ul, stats.transport_stats.size());
2296 }
2297};
2298
2299// For each of these, "X => Y = Z" means "if a client with protocol X
2300// initiates to a client with protocol Y, they end up speaking protocol Z.
2301
2302// Gingle => Gingle = Gingle (with other content)
2303TEST_F(SessionTest, GingleToGingleOtherContent) {
2304 TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2305}
2306
2307// Gingle => Gingle = Gingle (with audio content)
2308TEST_F(SessionTest, GingleToGingleAudioContent) {
2309 TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2310}
2311
2312// Gingle => Gingle = Gingle (with video contents)
2313TEST_F(SessionTest, GingleToGingleVideoContents) {
2314 TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2315}
2316
2317// Jingle => Jingle = Jingle (with other content)
2318TEST_F(SessionTest, JingleToJingleOtherContent) {
2319 TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2320}
2321
2322// Jingle => Jingle = Jingle (with audio content)
2323TEST_F(SessionTest, JingleToJingleAudioContent) {
2324 TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2325}
2326
2327// Jingle => Jingle = Jingle (with video contents)
2328TEST_F(SessionTest, JingleToJingleVideoContents) {
2329 TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2330}
2331
2332// Hybrid => Hybrid = Jingle (with other content)
2333TEST_F(SessionTest, HybridToHybridOtherContent) {
2334 TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2335}
2336
2337// Hybrid => Hybrid = Jingle (with audio content)
2338TEST_F(SessionTest, HybridToHybridAudioContent) {
2339 TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2340}
2341
2342// Hybrid => Hybrid = Jingle (with video contents)
2343TEST_F(SessionTest, HybridToHybridVideoContents) {
2344 TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2345}
2346
2347// Gingle => Hybrid = Gingle (with other content)
2348TEST_F(SessionTest, GingleToHybridOtherContent) {
2349 TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2350}
2351
2352// Gingle => Hybrid = Gingle (with audio content)
2353TEST_F(SessionTest, GingleToHybridAudioContent) {
2354 TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2355}
2356
2357// Gingle => Hybrid = Gingle (with video contents)
2358TEST_F(SessionTest, GingleToHybridVideoContents) {
2359 TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
2360}
2361
2362// Jingle => Hybrid = Jingle (with other content)
2363TEST_F(SessionTest, JingleToHybridOtherContent) {
2364 TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2365}
2366
2367// Jingle => Hybrid = Jingle (with audio content)
2368TEST_F(SessionTest, JingleToHybridAudioContent) {
2369 TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2370}
2371
2372// Jingle => Hybrid = Jingle (with video contents)
2373TEST_F(SessionTest, JingleToHybridVideoContents) {
2374 TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
2375}
2376
2377// Hybrid => Gingle = Gingle (with other content)
2378TEST_F(SessionTest, HybridToGingleOtherContent) {
2379 TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2380}
2381
2382// Hybrid => Gingle = Gingle (with audio content)
2383TEST_F(SessionTest, HybridToGingleAudioContent) {
2384 TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2385}
2386
2387// Hybrid => Gingle = Gingle (with video contents)
2388TEST_F(SessionTest, HybridToGingleVideoContents) {
2389 TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
2390}
2391
2392// Hybrid => Jingle = Jingle (with other content)
2393TEST_F(SessionTest, HybridToJingleOtherContent) {
2394 TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2395}
2396
2397// Hybrid => Jingle = Jingle (with audio content)
2398TEST_F(SessionTest, HybridToJingleAudioContent) {
2399 TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2400}
2401
2402// Hybrid => Jingle = Jingle (with video contents)
2403TEST_F(SessionTest, HybridToJingleVideoContents) {
2404 TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
2405}
2406
2407TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) {
2408 TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE);
2409}
2410
2411TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) {
2412 TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE);
2413}
2414
2415TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) {
2416 TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID);
2417}
2418
2419TEST_F(SessionTest, GingleRejection) {
2420 TestRejection(PROTOCOL_GINGLE);
2421}
2422
2423TEST_F(SessionTest, JingleRejection) {
2424 TestRejection(PROTOCOL_JINGLE);
2425}
2426
2427TEST_F(SessionTest, GingleGoodRedirect) {
2428 TestGoodRedirect(PROTOCOL_GINGLE);
2429}
2430
2431TEST_F(SessionTest, JingleGoodRedirect) {
2432 TestGoodRedirect(PROTOCOL_JINGLE);
2433}
2434
2435TEST_F(SessionTest, GingleBadRedirect) {
2436 TestBadRedirect(PROTOCOL_GINGLE);
2437}
2438
2439TEST_F(SessionTest, JingleBadRedirect) {
2440 TestBadRedirect(PROTOCOL_JINGLE);
2441}
2442
2443TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) {
2444 TestCandidatesInInitiateAndAccept("Candidates in initiate/accept");
2445}
2446
2447TEST_F(SessionTest, TestTransportMux) {
2448 TestTransportMux();
2449}
2450
2451TEST_F(SessionTest, TestSendDescriptionInfo) {
2452 TestSendDescriptionInfo();
2453}
2454
2455TEST_F(SessionTest, TestCallerSignalNewDescription) {
2456 TestCallerSignalNewDescription();
2457}
2458
2459TEST_F(SessionTest, TestCalleeSignalNewDescription) {
2460 TestCalleeSignalNewDescription();
2461}
2462
2463TEST_F(SessionTest, TestGetTransportStats) {
2464 TestGetTransportStats();
2465}