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