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