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