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