Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2011, Google Inc.
      4  * Copyright 2011, RTFM, Inc.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions are met:
      8  *
      9  *  1. Redistributions of source code must retain the above copyright notice,
     10  *     this list of conditions and the following disclaimer.
     11  *  2. Redistributions in binary form must reproduce the above copyright notice,
     12  *     this list of conditions and the following disclaimer in the documentation
     13  *     and/or other materials provided with the distribution.
     14  *  3. The name of the author may not be used to endorse or promote products
     15  *     derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     20  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <set>
     30 
     31 #include "talk/base/common.h"
     32 #include "talk/base/gunit.h"
     33 #include "talk/base/helpers.h"
     34 #include "talk/base/scoped_ptr.h"
     35 #include "talk/base/stringutils.h"
     36 #include "talk/base/thread.h"
     37 #include "talk/p2p/base/fakesession.h"
     38 #include "talk/base/ssladapter.h"
     39 #include "talk/base/sslidentity.h"
     40 #include "talk/base/sslstreamadapter.h"
     41 #include "talk/p2p/base/dtlstransport.h"
     42 
     43 #define MAYBE_SKIP_TEST(feature)                    \
     44   if (!(talk_base::SSLStreamAdapter::feature())) {  \
     45     LOG(LS_INFO) << "Feature disabled... skipping"; \
     46     return;                                         \
     47   }
     48 
     49 static const char AES_CM_128_HMAC_SHA1_80[] = "AES_CM_128_HMAC_SHA1_80";
     50 static const char kIceUfrag1[] = "TESTICEUFRAG0001";
     51 static const char kIcePwd1[] = "TESTICEPWD00000000000001";
     52 static const size_t kPacketNumOffset = 8;
     53 static const size_t kPacketHeaderLen = 12;
     54 
     55 static bool IsRtpLeadByte(uint8 b) {
     56   return ((b & 0xC0) == 0x80);
     57 }
     58 
     59 class DtlsTestClient : public sigslot::has_slots<> {
     60  public:
     61   DtlsTestClient(const std::string& name,
     62                  talk_base::Thread* signaling_thread,
     63                  talk_base::Thread* worker_thread) :
     64       name_(name),
     65       signaling_thread_(signaling_thread),
     66       worker_thread_(worker_thread),
     67       protocol_(cricket::ICEPROTO_GOOGLE),
     68       packet_size_(0),
     69       use_dtls_srtp_(false),
     70       negotiated_dtls_(false),
     71       received_dtls_client_hello_(false),
     72       received_dtls_server_hello_(false) {
     73   }
     74   void SetIceProtocol(cricket::TransportProtocol proto) {
     75     protocol_ = proto;
     76   }
     77   void CreateIdentity() {
     78     identity_.reset(talk_base::SSLIdentity::Generate(name_));
     79   }
     80   void SetupSrtp() {
     81     ASSERT(identity_.get() != NULL);
     82     use_dtls_srtp_ = true;
     83   }
     84   void SetupChannels(int count, cricket::IceRole role) {
     85     transport_.reset(new cricket::DtlsTransport<cricket::FakeTransport>(
     86         signaling_thread_, worker_thread_, "dtls content name", NULL,
     87         identity_.get()));
     88     transport_->SetAsync(true);
     89     transport_->SetIceRole(role);
     90     transport_->SetIceTiebreaker(
     91         (role == cricket::ICEROLE_CONTROLLING) ? 1 : 2);
     92     transport_->SignalWritableState.connect(this,
     93         &DtlsTestClient::OnTransportWritableState);
     94 
     95     for (int i = 0; i < count; ++i) {
     96       cricket::DtlsTransportChannelWrapper* channel =
     97           static_cast<cricket::DtlsTransportChannelWrapper*>(
     98               transport_->CreateChannel(i));
     99       ASSERT_TRUE(channel != NULL);
    100       channel->SignalWritableState.connect(this,
    101         &DtlsTestClient::OnTransportChannelWritableState);
    102       channel->SignalReadPacket.connect(this,
    103         &DtlsTestClient::OnTransportChannelReadPacket);
    104       channels_.push_back(channel);
    105 
    106       // Hook the raw packets so that we can verify they are encrypted.
    107       channel->channel()->SignalReadPacket.connect(
    108           this, &DtlsTestClient::OnFakeTransportChannelReadPacket);
    109     }
    110   }
    111   cricket::FakeTransportChannel* GetFakeChannel(int component) {
    112     cricket::TransportChannelImpl* ch = transport_->GetChannel(component);
    113     cricket::DtlsTransportChannelWrapper* wrapper =
    114         static_cast<cricket::DtlsTransportChannelWrapper*>(ch);
    115     return (wrapper) ?
    116         static_cast<cricket::FakeTransportChannel*>(wrapper->channel()) : NULL;
    117   }
    118 
    119   // Offer DTLS if we have an identity; pass in a remote fingerprint only if
    120   // both sides support DTLS.
    121   void Negotiate(DtlsTestClient* peer) {
    122     Negotiate(identity_.get(), (identity_) ? peer->identity_.get() : NULL);
    123   }
    124 
    125   // Allow any DTLS configuration to be specified (including invalid ones).
    126   void Negotiate(talk_base::SSLIdentity* local_identity,
    127                  talk_base::SSLIdentity* remote_identity) {
    128     talk_base::scoped_ptr<talk_base::SSLFingerprint> local_fingerprint;
    129     talk_base::scoped_ptr<talk_base::SSLFingerprint> remote_fingerprint;
    130     if (local_identity) {
    131       local_fingerprint.reset(talk_base::SSLFingerprint::Create(
    132           talk_base::DIGEST_SHA_1, local_identity));
    133       ASSERT_TRUE(local_fingerprint.get() != NULL);
    134     }
    135     if (remote_identity) {
    136       remote_fingerprint.reset(talk_base::SSLFingerprint::Create(
    137           talk_base::DIGEST_SHA_1, remote_identity));
    138       ASSERT_TRUE(remote_fingerprint.get() != NULL);
    139     }
    140     if (use_dtls_srtp_) {
    141       for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it =
    142            channels_.begin(); it != channels_.end(); ++it) {
    143         std::vector<std::string> ciphers;
    144         ciphers.push_back(AES_CM_128_HMAC_SHA1_80);
    145         ASSERT_TRUE((*it)->SetSrtpCiphers(ciphers));
    146       }
    147     }
    148 
    149     std::string transport_type = (protocol_ == cricket::ICEPROTO_GOOGLE) ?
    150         cricket::NS_GINGLE_P2P : cricket::NS_JINGLE_ICE_UDP;
    151     cricket::TransportDescription local_desc(
    152         transport_type, std::vector<std::string>(), kIceUfrag1, kIcePwd1,
    153         cricket::ICEMODE_FULL, local_fingerprint.get(),
    154         cricket::Candidates());
    155     ASSERT_TRUE(transport_->SetLocalTransportDescription(local_desc,
    156                                                          cricket::CA_OFFER));
    157     cricket::TransportDescription remote_desc(
    158         transport_type, std::vector<std::string>(), kIceUfrag1, kIcePwd1,
    159         cricket::ICEMODE_FULL, remote_fingerprint.get(),
    160         cricket::Candidates());
    161     ASSERT_TRUE(transport_->SetRemoteTransportDescription(remote_desc,
    162                                                           cricket::CA_ANSWER));
    163 
    164     negotiated_dtls_ = (local_identity && remote_identity);
    165   }
    166 
    167   bool Connect(DtlsTestClient* peer) {
    168     transport_->ConnectChannels();
    169     transport_->SetDestination(peer->transport_.get());
    170     return true;
    171   }
    172 
    173   bool writable() const { return transport_->writable(); }
    174 
    175   void CheckRole(talk_base::SSLRole role) {
    176     if (role == talk_base::SSL_CLIENT) {
    177       ASSERT_FALSE(received_dtls_client_hello_);
    178       ASSERT_TRUE(received_dtls_server_hello_);
    179     } else {
    180       ASSERT_TRUE(received_dtls_client_hello_);
    181       ASSERT_FALSE(received_dtls_server_hello_);
    182     }
    183   }
    184 
    185   void CheckSrtp(const std::string& expected_cipher) {
    186     for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it =
    187            channels_.begin(); it != channels_.end(); ++it) {
    188       std::string cipher;
    189 
    190       bool rv = (*it)->GetSrtpCipher(&cipher);
    191       if (negotiated_dtls_ && !expected_cipher.empty()) {
    192         ASSERT_TRUE(rv);
    193 
    194         ASSERT_EQ(cipher, expected_cipher);
    195       } else {
    196         ASSERT_FALSE(rv);
    197       }
    198     }
    199   }
    200 
    201   void SendPackets(size_t channel, size_t size, size_t count, bool srtp) {
    202     ASSERT(channel < channels_.size());
    203     talk_base::scoped_array<char> packet(new char[size]);
    204     size_t sent = 0;
    205     do {
    206       // Fill the packet with a known value and a sequence number to check
    207       // against, and make sure that it doesn't look like DTLS.
    208       memset(packet.get(), sent & 0xff, size);
    209       packet[0] = (srtp) ? 0x80 : 0x00;
    210       talk_base::SetBE32(packet.get() + kPacketNumOffset,
    211                          static_cast<uint32>(sent));
    212 
    213       // Only set the bypass flag if we've activated DTLS.
    214       int flags = (identity_.get() && srtp) ? cricket::PF_SRTP_BYPASS : 0;
    215       int rv = channels_[channel]->SendPacket(packet.get(), size, flags);
    216       ASSERT_GT(rv, 0);
    217       ASSERT_EQ(size, static_cast<size_t>(rv));
    218       ++sent;
    219     } while (sent < count);
    220   }
    221 
    222   void ExpectPackets(size_t channel, size_t size) {
    223     packet_size_ = size;
    224     received_.clear();
    225   }
    226 
    227   size_t NumPacketsReceived() {
    228     return received_.size();
    229   }
    230 
    231   bool VerifyPacket(const char* data, size_t size, uint32* out_num) {
    232     if (size != packet_size_ ||
    233         (data[0] != 0 && static_cast<uint8>(data[0]) != 0x80)) {
    234       return false;
    235     }
    236     uint32 packet_num = talk_base::GetBE32(data + kPacketNumOffset);
    237     for (size_t i = kPacketHeaderLen; i < size; ++i) {
    238       if (static_cast<uint8>(data[i]) != (packet_num & 0xff)) {
    239         return false;
    240       }
    241     }
    242     if (out_num) {
    243       *out_num = packet_num;
    244     }
    245     return true;
    246   }
    247   bool VerifyEncryptedPacket(const char* data, size_t size) {
    248     // This is an encrypted data packet; let's make sure it's mostly random;
    249     // less than 10% of the bytes should be equal to the cleartext packet.
    250     if (size <= packet_size_) {
    251       return false;
    252     }
    253     uint32 packet_num = talk_base::GetBE32(data + kPacketNumOffset);
    254     int num_matches = 0;
    255     for (size_t i = kPacketNumOffset; i < size; ++i) {
    256       if (static_cast<uint8>(data[i]) == (packet_num & 0xff)) {
    257         ++num_matches;
    258       }
    259     }
    260     return (num_matches < ((static_cast<int>(size) - 5) / 10));
    261   }
    262 
    263   // Transport callbacks
    264   void OnTransportWritableState(cricket::Transport* transport) {
    265     LOG(LS_INFO) << name_ << ": is writable";
    266   }
    267 
    268   // Transport channel callbacks
    269   void OnTransportChannelWritableState(cricket::TransportChannel* channel) {
    270     LOG(LS_INFO) << name_ << ": Channel '" << channel->component()
    271                  << "' is writable";
    272   }
    273 
    274   void OnTransportChannelReadPacket(cricket::TransportChannel* channel,
    275                                     const char* data, size_t size,
    276                                     int flags) {
    277     uint32 packet_num = 0;
    278     ASSERT_TRUE(VerifyPacket(data, size, &packet_num));
    279     received_.insert(packet_num);
    280     // Only DTLS-SRTP packets should have the bypass flag set.
    281     int expected_flags = (identity_.get() && IsRtpLeadByte(data[0])) ?
    282         cricket::PF_SRTP_BYPASS : 0;
    283     ASSERT_EQ(expected_flags, flags);
    284   }
    285 
    286   // Hook into the raw packet stream to make sure DTLS packets are encrypted.
    287   void OnFakeTransportChannelReadPacket(cricket::TransportChannel* channel,
    288                                         const char* data, size_t size,
    289                                         int flags) {
    290     // Flags shouldn't be set on the underlying TransportChannel packets.
    291     ASSERT_EQ(0, flags);
    292 
    293     // Look at the handshake packets to see what role we played.
    294     // Check that non-handshake packets are DTLS data or SRTP bypass.
    295     if (negotiated_dtls_) {
    296       if (data[0] == 22 && size > 17) {
    297         if (data[13] == 1) {
    298           received_dtls_client_hello_ = true;
    299         } else if (data[13] == 2) {
    300           received_dtls_server_hello_ = true;
    301         }
    302       } else if (!(data[0] >= 20 && data[0] <= 22)) {
    303         ASSERT_TRUE(data[0] == 23 || IsRtpLeadByte(data[0]));
    304         if (data[0] == 23) {
    305           ASSERT_TRUE(VerifyEncryptedPacket(data, size));
    306         } else if (IsRtpLeadByte(data[0])) {
    307           ASSERT_TRUE(VerifyPacket(data, size, NULL));
    308         }
    309       }
    310     }
    311   }
    312 
    313  private:
    314   std::string name_;
    315   talk_base::Thread* signaling_thread_;
    316   talk_base::Thread* worker_thread_;
    317   cricket::TransportProtocol protocol_;
    318   talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
    319   talk_base::scoped_ptr<cricket::FakeTransport> transport_;
    320   std::vector<cricket::DtlsTransportChannelWrapper*> channels_;
    321   size_t packet_size_;
    322   std::set<int> received_;
    323   bool use_dtls_srtp_;
    324   bool negotiated_dtls_;
    325   bool received_dtls_client_hello_;
    326   bool received_dtls_server_hello_;
    327 };
    328 
    329 
    330 class DtlsTransportChannelTest : public testing::Test {
    331  public:
    332   static void SetUpTestCase() {
    333     talk_base::InitializeSSL();
    334   }
    335 
    336   static void TearDownTestCase() {
    337     talk_base::CleanupSSL();
    338   }
    339 
    340   DtlsTransportChannelTest() :
    341       client1_("P1", talk_base::Thread::Current(),
    342                talk_base::Thread::Current()),
    343       client2_("P2", talk_base::Thread::Current(),
    344                talk_base::Thread::Current()),
    345       channel_ct_(1),
    346       use_dtls_(false),
    347       use_dtls_srtp_(false) {
    348   }
    349 
    350   void SetChannelCount(size_t channel_ct) {
    351     channel_ct_ = static_cast<int>(channel_ct);
    352   }
    353   void PrepareDtls(bool c1, bool c2) {
    354     if (c1) {
    355       client1_.CreateIdentity();
    356     }
    357     if (c2) {
    358       client2_.CreateIdentity();
    359     }
    360     if (c1 && c2)
    361       use_dtls_ = true;
    362   }
    363   void PrepareDtlsSrtp(bool c1, bool c2) {
    364     if (!use_dtls_)
    365       return;
    366 
    367     if (c1)
    368       client1_.SetupSrtp();
    369     if (c2)
    370       client2_.SetupSrtp();
    371 
    372     if (c1 && c2)
    373       use_dtls_srtp_ = true;
    374   }
    375 
    376   bool Connect() {
    377     Negotiate();
    378 
    379     bool rv = client1_.Connect(&client2_);
    380     EXPECT_TRUE(rv);
    381     if (!rv)
    382       return false;
    383 
    384     EXPECT_TRUE_WAIT(client1_.writable() && client2_.writable(), 10000);
    385     if (!client1_.writable() || !client2_.writable())
    386       return false;
    387 
    388     // Check that we used the right roles.
    389     if (use_dtls_) {
    390       client1_.CheckRole(talk_base::SSL_SERVER);
    391       client2_.CheckRole(talk_base::SSL_CLIENT);
    392     }
    393 
    394     // Check that we negotiated the right ciphers.
    395     if (use_dtls_srtp_) {
    396       client1_.CheckSrtp(AES_CM_128_HMAC_SHA1_80);
    397       client2_.CheckSrtp(AES_CM_128_HMAC_SHA1_80);
    398     } else {
    399       client1_.CheckSrtp("");
    400       client2_.CheckSrtp("");
    401     }
    402 
    403     return true;
    404   }
    405   void Negotiate() {
    406     client1_.SetupChannels(channel_ct_, cricket::ICEROLE_CONTROLLING);
    407     client2_.SetupChannels(channel_ct_, cricket::ICEROLE_CONTROLLED);
    408     client2_.Negotiate(&client1_);
    409     client1_.Negotiate(&client2_);
    410   }
    411 
    412   void TestTransfer(size_t channel, size_t size, size_t count, bool srtp) {
    413     LOG(LS_INFO) << "Expect packets, size=" << size;
    414     client2_.ExpectPackets(channel, size);
    415     client1_.SendPackets(channel, size, count, srtp);
    416     EXPECT_EQ_WAIT(count, client2_.NumPacketsReceived(), 10000);
    417   }
    418 
    419  protected:
    420   DtlsTestClient client1_;
    421   DtlsTestClient client2_;
    422   int channel_ct_;
    423   bool use_dtls_;
    424   bool use_dtls_srtp_;
    425 };
    426 
    427 // Test that transport negotiation of ICE, no DTLS works properly.
    428 TEST_F(DtlsTransportChannelTest, TestChannelSetupIce) {
    429   client1_.SetIceProtocol(cricket::ICEPROTO_RFC5245);
    430   client2_.SetIceProtocol(cricket::ICEPROTO_RFC5245);
    431   Negotiate();
    432   cricket::FakeTransportChannel* channel1 = client1_.GetFakeChannel(0);
    433   cricket::FakeTransportChannel* channel2 = client2_.GetFakeChannel(0);
    434   ASSERT_TRUE(channel1 != NULL);
    435   ASSERT_TRUE(channel2 != NULL);
    436   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole());
    437   EXPECT_EQ(1U, channel1->IceTiebreaker());
    438   EXPECT_EQ(cricket::ICEPROTO_RFC5245, channel1->protocol());
    439   EXPECT_EQ(kIceUfrag1, channel1->ice_ufrag());
    440   EXPECT_EQ(kIcePwd1, channel1->ice_pwd());
    441   EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel2->GetIceRole());
    442   EXPECT_EQ(2U, channel2->IceTiebreaker());
    443   EXPECT_EQ(cricket::ICEPROTO_RFC5245, channel2->protocol());
    444 }
    445 
    446 // Test that transport negotiation of GICE, no DTLS works properly.
    447 TEST_F(DtlsTransportChannelTest, TestChannelSetupGice) {
    448   client1_.SetIceProtocol(cricket::ICEPROTO_GOOGLE);
    449   client2_.SetIceProtocol(cricket::ICEPROTO_GOOGLE);
    450   Negotiate();
    451   cricket::FakeTransportChannel* channel1 = client1_.GetFakeChannel(0);
    452   cricket::FakeTransportChannel* channel2 = client2_.GetFakeChannel(0);
    453   ASSERT_TRUE(channel1 != NULL);
    454   ASSERT_TRUE(channel2 != NULL);
    455   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole());
    456   EXPECT_EQ(1U, channel1->IceTiebreaker());
    457   EXPECT_EQ(cricket::ICEPROTO_GOOGLE, channel1->protocol());
    458   EXPECT_EQ(kIceUfrag1, channel1->ice_ufrag());
    459   EXPECT_EQ(kIcePwd1, channel1->ice_pwd());
    460   EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel2->GetIceRole());
    461   EXPECT_EQ(2U, channel2->IceTiebreaker());
    462   EXPECT_EQ(cricket::ICEPROTO_GOOGLE, channel2->protocol());
    463 }
    464 
    465 // Connect without DTLS, and transfer some data.
    466 TEST_F(DtlsTransportChannelTest, TestTransfer) {
    467   ASSERT_TRUE(Connect());
    468   TestTransfer(0, 1000, 100, false);
    469 }
    470 
    471 // Create two channels without DTLS, and transfer some data.
    472 TEST_F(DtlsTransportChannelTest, TestTransferTwoChannels) {
    473   SetChannelCount(2);
    474   ASSERT_TRUE(Connect());
    475   TestTransfer(0, 1000, 100, false);
    476   TestTransfer(1, 1000, 100, false);
    477 }
    478 
    479 // Connect without DTLS, and transfer SRTP data.
    480 TEST_F(DtlsTransportChannelTest, TestTransferSrtp) {
    481   ASSERT_TRUE(Connect());
    482   TestTransfer(0, 1000, 100, true);
    483 }
    484 
    485 // Create two channels without DTLS, and transfer SRTP data.
    486 TEST_F(DtlsTransportChannelTest, TestTransferSrtpTwoChannels) {
    487   SetChannelCount(2);
    488   ASSERT_TRUE(Connect());
    489   TestTransfer(0, 1000, 100, true);
    490   TestTransfer(1, 1000, 100, true);
    491 }
    492 
    493 // Connect with DTLS, and transfer some data.
    494 TEST_F(DtlsTransportChannelTest, TestTransferDtls) {
    495   MAYBE_SKIP_TEST(HaveDtls);
    496   PrepareDtls(true, true);
    497   ASSERT_TRUE(Connect());
    498   TestTransfer(0, 1000, 100, false);
    499 }
    500 
    501 // Create two channels with DTLS, and transfer some data.
    502 TEST_F(DtlsTransportChannelTest, TestTransferDtlsTwoChannels) {
    503   MAYBE_SKIP_TEST(HaveDtls);
    504   SetChannelCount(2);
    505   PrepareDtls(true, true);
    506   ASSERT_TRUE(Connect());
    507   TestTransfer(0, 1000, 100, false);
    508   TestTransfer(1, 1000, 100, false);
    509 }
    510 
    511 // Connect with A doing DTLS and B not, and transfer some data.
    512 TEST_F(DtlsTransportChannelTest, TestTransferDtlsRejected) {
    513   PrepareDtls(true, false);
    514   ASSERT_TRUE(Connect());
    515   TestTransfer(0, 1000, 100, false);
    516 }
    517 
    518 // Connect with B doing DTLS and A not, and transfer some data.
    519 TEST_F(DtlsTransportChannelTest, TestTransferDtlsNotOffered) {
    520   PrepareDtls(false, true);
    521   ASSERT_TRUE(Connect());
    522   TestTransfer(0, 1000, 100, false);
    523 }
    524 
    525 // Connect with DTLS, negotiate DTLS-SRTP, and transfer SRTP using bypass.
    526 TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtp) {
    527   MAYBE_SKIP_TEST(HaveDtlsSrtp);
    528   PrepareDtls(true, true);
    529   PrepareDtlsSrtp(true, true);
    530   ASSERT_TRUE(Connect());
    531   TestTransfer(0, 1000, 100, true);
    532 }
    533 
    534 
    535 // Connect with DTLS. A does DTLS-SRTP but B does not.
    536 TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpRejected) {
    537   MAYBE_SKIP_TEST(HaveDtlsSrtp);
    538   PrepareDtls(true, true);
    539   PrepareDtlsSrtp(true, false);
    540   ASSERT_TRUE(Connect());
    541 }
    542 
    543 // Connect with DTLS. B does DTLS-SRTP but A does not.
    544 TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpNotOffered) {
    545   MAYBE_SKIP_TEST(HaveDtlsSrtp);
    546   PrepareDtls(true, true);
    547   PrepareDtlsSrtp(false, true);
    548   ASSERT_TRUE(Connect());
    549 }
    550 
    551 // Create two channels with DTLS, negotiate DTLS-SRTP, and transfer bypass SRTP.
    552 TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpTwoChannels) {
    553   MAYBE_SKIP_TEST(HaveDtlsSrtp);
    554   SetChannelCount(2);
    555   PrepareDtls(true, true);
    556   PrepareDtlsSrtp(true, true);
    557   ASSERT_TRUE(Connect());
    558   TestTransfer(0, 1000, 100, true);
    559   TestTransfer(1, 1000, 100, true);
    560 }
    561 
    562 // Create a single channel with DTLS, and send normal data and SRTP data on it.
    563 TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpDemux) {
    564   MAYBE_SKIP_TEST(HaveDtlsSrtp);
    565   PrepareDtls(true, true);
    566   PrepareDtlsSrtp(true, true);
    567   ASSERT_TRUE(Connect());
    568   TestTransfer(0, 1000, 100, false);
    569   TestTransfer(0, 1000, 100, true);
    570 }
    571