Home | History | Annotate | Download | only in base
      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 
     59 using cricket::SignalingProtocol;
     60 using cricket::PROTOCOL_HYBRID;
     61 using cricket::PROTOCOL_JINGLE;
     62 using cricket::PROTOCOL_GINGLE;
     63 
     64 static const std::string kInitiator = "init (at) init.com";
     65 static const std::string kResponder = "resp (at) resp.com";
     66 // Expected from test random number generator.
     67 static 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.
     70 static 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.
     74 static const int kEventTimeout = 5000;
     75 
     76 static const int kNumPorts = 2;
     77 static const int kPort0 = 28653;
     78 static const int kPortStep = 5;
     79 
     80 int GetPort(int port_index) {
     81   return kPort0 + (port_index * kPortStep);
     82 }
     83 
     84 std::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.
     89 std::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.
     94 std::string GetPassword(int port_index) {
     95   return "password" + std::string(8, rtc::ToString(port_index)[0]);
     96 }
     97 
     98 std::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 
    110 std::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 
    125 std::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 
    140 std::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 
    152 std::string GingleDescriptionXml(const std::string& content_type) {
    153   return "<description"
    154       " xmlns=\"" + content_type + "\""
    155       "/>";
    156 }
    157 
    158 std::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 
    184 std::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 
    195 std::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 
    206 std::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 
    223 std::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 
    239 std::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 
    261 std::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 
    276 std::string GingleInitiateXml(const std::string& content_type) {
    277   return GingleSessionXml(
    278       "initiate",
    279       GingleDescriptionXml(content_type));
    280 }
    281 
    282 std::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 
    303 std::string GingleAcceptXml(const std::string& content_type) {
    304   return GingleSessionXml(
    305       "accept",
    306       GingleDescriptionXml(content_type));
    307 }
    308 
    309 std::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 
    331 std::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 
    340 std::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 
    354 std::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 
    366 std::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 
    383 std::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 
    390 std::string GingleRejectXml(const std::string& reason) {
    391   return GingleSessionXml(
    392       "reject",
    393       "<" + reason + "/>");
    394 }
    395 
    396 std::string JingleTerminateXml(const std::string& reason) {
    397     return JingleActionXml(
    398         "session-terminate",
    399         "<reason><" + reason + "/></reason>");
    400 }
    401 
    402 std::string GingleTerminateXml(const std::string& reason) {
    403   return GingleSessionXml(
    404       "terminate",
    405       "<" + reason + "/>");
    406 }
    407 
    408 std::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 
    418 std::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 
    428 std::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 
    450 std::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 
    459 std::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 
    482 std::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 
    492 std::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 
    516 std::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 
    547 std::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 
    561 std::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 
    575 std::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
    590 class 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 
    659 class 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 
    677 class 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 
    692 cricket::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 
    714 cricket::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 
    728 struct 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 
    774 struct 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 
    832 void PrintStanza(const std::string& message,
    833                  const buzz::XmlElement* stanza) {
    834   printf("%s: %s\n", message.c_str(), stanza->Str().c_str());
    835 }
    836 
    837 class 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 
   1122 class 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 (at) 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)
   2285 TEST_F(SessionTest, GingleToGingleOtherContent) {
   2286   TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
   2287 }
   2288 
   2289 // Gingle => Gingle = Gingle (with audio content)
   2290 TEST_F(SessionTest, GingleToGingleAudioContent) {
   2291   TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
   2292 }
   2293 
   2294 // Gingle => Gingle = Gingle (with video contents)
   2295 TEST_F(SessionTest, GingleToGingleVideoContents) {
   2296   TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
   2297 }
   2298 
   2299 // Jingle => Jingle = Jingle (with other content)
   2300 TEST_F(SessionTest, JingleToJingleOtherContent) {
   2301   TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
   2302 }
   2303 
   2304 // Jingle => Jingle = Jingle (with audio content)
   2305 TEST_F(SessionTest, JingleToJingleAudioContent) {
   2306   TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
   2307 }
   2308 
   2309 // Jingle => Jingle = Jingle (with video contents)
   2310 TEST_F(SessionTest, JingleToJingleVideoContents) {
   2311   TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
   2312 }
   2313 
   2314 // Hybrid => Hybrid = Jingle (with other content)
   2315 TEST_F(SessionTest, HybridToHybridOtherContent) {
   2316   TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
   2317 }
   2318 
   2319 // Hybrid => Hybrid = Jingle (with audio content)
   2320 TEST_F(SessionTest, HybridToHybridAudioContent) {
   2321   TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
   2322 }
   2323 
   2324 // Hybrid => Hybrid = Jingle (with video contents)
   2325 TEST_F(SessionTest, HybridToHybridVideoContents) {
   2326   TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
   2327 }
   2328 
   2329 // Gingle => Hybrid = Gingle (with other content)
   2330 TEST_F(SessionTest, GingleToHybridOtherContent) {
   2331   TestOtherContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
   2332 }
   2333 
   2334 // Gingle => Hybrid = Gingle (with audio content)
   2335 TEST_F(SessionTest, GingleToHybridAudioContent) {
   2336   TestAudioContent(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
   2337 }
   2338 
   2339 // Gingle => Hybrid = Gingle (with video contents)
   2340 TEST_F(SessionTest, GingleToHybridVideoContents) {
   2341   TestVideoContents(PROTOCOL_GINGLE, PROTOCOL_HYBRID, PROTOCOL_GINGLE);
   2342 }
   2343 
   2344 // Jingle => Hybrid = Jingle (with other content)
   2345 TEST_F(SessionTest, JingleToHybridOtherContent) {
   2346   TestOtherContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
   2347 }
   2348 
   2349 // Jingle => Hybrid = Jingle (with audio content)
   2350 TEST_F(SessionTest, JingleToHybridAudioContent) {
   2351   TestAudioContent(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
   2352 }
   2353 
   2354 // Jingle => Hybrid = Jingle (with video contents)
   2355 TEST_F(SessionTest, JingleToHybridVideoContents) {
   2356   TestVideoContents(PROTOCOL_JINGLE, PROTOCOL_HYBRID, PROTOCOL_JINGLE);
   2357 }
   2358 
   2359 // Hybrid => Gingle = Gingle (with other content)
   2360 TEST_F(SessionTest, HybridToGingleOtherContent) {
   2361   TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
   2362 }
   2363 
   2364 // Hybrid => Gingle = Gingle (with audio content)
   2365 TEST_F(SessionTest, HybridToGingleAudioContent) {
   2366   TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
   2367 }
   2368 
   2369 // Hybrid => Gingle = Gingle (with video contents)
   2370 TEST_F(SessionTest, HybridToGingleVideoContents) {
   2371   TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_GINGLE, PROTOCOL_GINGLE);
   2372 }
   2373 
   2374 // Hybrid => Jingle = Jingle (with other content)
   2375 TEST_F(SessionTest, HybridToJingleOtherContent) {
   2376   TestOtherContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
   2377 }
   2378 
   2379 // Hybrid => Jingle = Jingle (with audio content)
   2380 TEST_F(SessionTest, HybridToJingleAudioContent) {
   2381   TestAudioContent(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
   2382 }
   2383 
   2384 // Hybrid => Jingle = Jingle (with video contents)
   2385 TEST_F(SessionTest, HybridToJingleVideoContents) {
   2386   TestVideoContents(PROTOCOL_HYBRID, PROTOCOL_JINGLE, PROTOCOL_JINGLE);
   2387 }
   2388 
   2389 TEST_F(SessionTest, GingleEarlyTerminationFromInitiator) {
   2390   TestEarlyTerminationFromInitiator(PROTOCOL_GINGLE);
   2391 }
   2392 
   2393 TEST_F(SessionTest, JingleEarlyTerminationFromInitiator) {
   2394   TestEarlyTerminationFromInitiator(PROTOCOL_JINGLE);
   2395 }
   2396 
   2397 TEST_F(SessionTest, HybridEarlyTerminationFromInitiator) {
   2398   TestEarlyTerminationFromInitiator(PROTOCOL_HYBRID);
   2399 }
   2400 
   2401 TEST_F(SessionTest, GingleRejection) {
   2402   TestRejection(PROTOCOL_GINGLE);
   2403 }
   2404 
   2405 TEST_F(SessionTest, JingleRejection) {
   2406   TestRejection(PROTOCOL_JINGLE);
   2407 }
   2408 
   2409 TEST_F(SessionTest, GingleGoodRedirect) {
   2410   TestGoodRedirect(PROTOCOL_GINGLE);
   2411 }
   2412 
   2413 TEST_F(SessionTest, JingleGoodRedirect) {
   2414   TestGoodRedirect(PROTOCOL_JINGLE);
   2415 }
   2416 
   2417 TEST_F(SessionTest, GingleBadRedirect) {
   2418   TestBadRedirect(PROTOCOL_GINGLE);
   2419 }
   2420 
   2421 TEST_F(SessionTest, JingleBadRedirect) {
   2422   TestBadRedirect(PROTOCOL_JINGLE);
   2423 }
   2424 
   2425 TEST_F(SessionTest, TestCandidatesInInitiateAndAccept) {
   2426   TestCandidatesInInitiateAndAccept("Candidates in initiate/accept");
   2427 }
   2428 
   2429 TEST_F(SessionTest, TestTransportMux) {
   2430   TestTransportMux();
   2431 }
   2432 
   2433 TEST_F(SessionTest, TestSendDescriptionInfo) {
   2434   TestSendDescriptionInfo();
   2435 }
   2436 
   2437 TEST_F(SessionTest, TestCallerSignalNewDescription) {
   2438   TestCallerSignalNewDescription();
   2439 }
   2440 
   2441 TEST_F(SessionTest, TestCalleeSignalNewDescription) {
   2442   TestCalleeSignalNewDescription();
   2443 }
   2444 
   2445 TEST_F(SessionTest, TestGetTransportStats) {
   2446   TestGetTransportStats();
   2447 }
   2448