Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: webrtc/p2p/base/dtlstransportchannel_unittest.cc

Issue 2140283002: Fixing issue with DTLS channel when using "presume writable" flag. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Minor code shuffling. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/p2p/base/dtlstransportchannel.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 27 matching lines...) Expand all
38 static bool IsRtpLeadByte(uint8_t b) { 38 static bool IsRtpLeadByte(uint8_t b) {
39 return ((b & 0xC0) == 0x80); 39 return ((b & 0xC0) == 0x80);
40 } 40 }
41 41
42 cricket::TransportDescription MakeTransportDescription( 42 cricket::TransportDescription MakeTransportDescription(
43 const rtc::scoped_refptr<rtc::RTCCertificate>& cert, 43 const rtc::scoped_refptr<rtc::RTCCertificate>& cert,
44 cricket::ConnectionRole role) { 44 cricket::ConnectionRole role) {
45 std::unique_ptr<rtc::SSLFingerprint> fingerprint; 45 std::unique_ptr<rtc::SSLFingerprint> fingerprint;
46 if (cert) { 46 if (cert) {
47 std::string digest_algorithm; 47 std::string digest_algorithm;
48 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm); 48 EXPECT_TRUE(
49 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm));
50 EXPECT_FALSE(digest_algorithm.empty());
49 fingerprint.reset( 51 fingerprint.reset(
50 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity())); 52 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
53 EXPECT_TRUE(fingerprint.get() != NULL);
54 EXPECT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
51 } 55 }
52 return cricket::TransportDescription(std::vector<std::string>(), kIceUfrag1, 56 return cricket::TransportDescription(std::vector<std::string>(), kIceUfrag1,
53 kIcePwd1, cricket::ICEMODE_FULL, role, 57 kIcePwd1, cricket::ICEMODE_FULL, role,
54 fingerprint.get()); 58 fingerprint.get());
55 } 59 }
56 60
57 using cricket::ConnectionRole; 61 using cricket::ConnectionRole;
58 62
59 enum Flags { NF_REOFFER = 0x1, NF_EXPECT_FAILURE = 0x2 }; 63 enum Flags { NF_REOFFER = 0x1, NF_EXPECT_FAILURE = 0x2 };
60 64
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 121
118 // Offer DTLS if we have an identity; pass in a remote fingerprint only if 122 // Offer DTLS if we have an identity; pass in a remote fingerprint only if
119 // both sides support DTLS. 123 // both sides support DTLS.
120 void Negotiate(DtlsTestClient* peer, cricket::ContentAction action, 124 void Negotiate(DtlsTestClient* peer, cricket::ContentAction action,
121 ConnectionRole local_role, ConnectionRole remote_role, 125 ConnectionRole local_role, ConnectionRole remote_role,
122 int flags) { 126 int flags) {
123 Negotiate(certificate_, certificate_ ? peer->certificate_ : nullptr, action, 127 Negotiate(certificate_, certificate_ ? peer->certificate_ : nullptr, action,
124 local_role, remote_role, flags); 128 local_role, remote_role, flags);
125 } 129 }
126 130
131 void MaybeSetSrtpCryptoSuites() {
132 if (!use_dtls_srtp_) {
133 return;
134 }
135 std::vector<int> ciphers;
136 ciphers.push_back(rtc::SRTP_AES128_CM_SHA1_80);
137 // SRTP ciphers will be set only in the beginning.
138 for (cricket::DtlsTransportChannelWrapper* channel : channels_) {
139 EXPECT_TRUE(channel->SetSrtpCryptoSuites(ciphers));
140 }
141 }
142
143 void SetLocalTransportDescription(
144 const rtc::scoped_refptr<rtc::RTCCertificate>& cert,
145 cricket::ContentAction action,
146 ConnectionRole role,
147 int flags) {
148 // If |NF_EXPECT_FAILURE| is set, expect SRTD or SLTD to fail when
149 // content action is CA_ANSWER.
150 bool expect_success =
151 !((action == cricket::CA_ANSWER) && (flags & NF_EXPECT_FAILURE));
152 EXPECT_EQ(expect_success,
153 transport_->SetLocalTransportDescription(
154 MakeTransportDescription(cert, role), action, nullptr));
155 set_local_cert_ = (cert != nullptr);
156 }
157
158 void SetRemoteTransportDescription(
159 const rtc::scoped_refptr<rtc::RTCCertificate>& cert,
160 cricket::ContentAction action,
161 ConnectionRole role,
162 int flags) {
163 // If |NF_EXPECT_FAILURE| is set, expect SRTD or SLTD to fail when
164 // content action is CA_ANSWER.
165 bool expect_success =
166 !((action == cricket::CA_ANSWER) && (flags & NF_EXPECT_FAILURE));
167 EXPECT_EQ(expect_success,
168 transport_->SetRemoteTransportDescription(
169 MakeTransportDescription(cert, role), action, nullptr));
170 set_remote_cert_ = (cert != nullptr);
171 }
172
127 // Allow any DTLS configuration to be specified (including invalid ones). 173 // Allow any DTLS configuration to be specified (including invalid ones).
128 void Negotiate(const rtc::scoped_refptr<rtc::RTCCertificate>& local_cert, 174 void Negotiate(const rtc::scoped_refptr<rtc::RTCCertificate>& local_cert,
129 const rtc::scoped_refptr<rtc::RTCCertificate>& remote_cert, 175 const rtc::scoped_refptr<rtc::RTCCertificate>& remote_cert,
130 cricket::ContentAction action, 176 cricket::ContentAction action,
131 ConnectionRole local_role, 177 ConnectionRole local_role,
132 ConnectionRole remote_role, 178 ConnectionRole remote_role,
133 int flags) { 179 int flags) {
134 std::unique_ptr<rtc::SSLFingerprint> local_fingerprint; 180 if (!(flags & NF_REOFFER)) {
135 std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint; 181 // SRTP ciphers will be set only in the beginning.
136 if (local_cert) { 182 MaybeSetSrtpCryptoSuites();
137 std::string digest_algorithm;
138 ASSERT_TRUE(local_cert->ssl_certificate().GetSignatureDigestAlgorithm(
139 &digest_algorithm));
140 ASSERT_FALSE(digest_algorithm.empty());
141 local_fingerprint.reset(rtc::SSLFingerprint::Create(
142 digest_algorithm, local_cert->identity()));
143 ASSERT_TRUE(local_fingerprint.get() != NULL);
144 EXPECT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
145 } 183 }
146 if (remote_cert) { 184 if (action == cricket::CA_OFFER) {
147 std::string digest_algorithm; 185 SetLocalTransportDescription(local_cert, cricket::CA_OFFER, local_role,
148 ASSERT_TRUE(remote_cert->ssl_certificate().GetSignatureDigestAlgorithm( 186 flags);
149 &digest_algorithm)); 187 SetRemoteTransportDescription(remote_cert, cricket::CA_ANSWER,
150 ASSERT_FALSE(digest_algorithm.empty()); 188 remote_role, flags);
151 remote_fingerprint.reset(rtc::SSLFingerprint::Create( 189 } else {
152 digest_algorithm, remote_cert->identity())); 190 SetRemoteTransportDescription(remote_cert, cricket::CA_OFFER, remote_role,
153 ASSERT_TRUE(remote_fingerprint.get() != NULL); 191 flags);
154 EXPECT_EQ(rtc::DIGEST_SHA_256, digest_algorithm); 192 // If remote if the offerer and has no DTLS support, answer will be
193 // without any fingerprint.
194 SetLocalTransportDescription(remote_cert ? local_cert : nullptr,
195 cricket::CA_ANSWER, local_role, flags);
155 } 196 }
156
157 if (use_dtls_srtp_ && !(flags & NF_REOFFER)) {
158 // SRTP ciphers will be set only in the beginning.
159 for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it =
160 channels_.begin(); it != channels_.end(); ++it) {
161 std::vector<int> ciphers;
162 ciphers.push_back(rtc::SRTP_AES128_CM_SHA1_80);
163 ASSERT_TRUE((*it)->SetSrtpCryptoSuites(ciphers));
164 }
165 }
166
167 cricket::TransportDescription local_desc(
168 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL,
169 local_role,
170 // If remote if the offerer and has no DTLS support, answer will be
171 // without any fingerprint.
172 (action == cricket::CA_ANSWER && !remote_cert)
173 ? nullptr
174 : local_fingerprint.get());
175
176 cricket::TransportDescription remote_desc(
177 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL,
178 remote_role, remote_fingerprint.get());
179
180 bool expect_success = (flags & NF_EXPECT_FAILURE) ? false : true;
181 // If |expect_success| is false, expect SRTD or SLTD to fail when
182 // content action is CA_ANSWER.
183 if (action == cricket::CA_OFFER) {
184 ASSERT_TRUE(transport_->SetLocalTransportDescription(
185 local_desc, cricket::CA_OFFER, NULL));
186 ASSERT_EQ(expect_success, transport_->SetRemoteTransportDescription(
187 remote_desc, cricket::CA_ANSWER, NULL));
188 } else {
189 ASSERT_TRUE(transport_->SetRemoteTransportDescription(
190 remote_desc, cricket::CA_OFFER, NULL));
191 ASSERT_EQ(expect_success, transport_->SetLocalTransportDescription(
192 local_desc, cricket::CA_ANSWER, NULL));
193 }
194 negotiated_dtls_ = (local_cert && remote_cert);
195 } 197 }
196 198
197 bool Connect(DtlsTestClient* peer, bool asymmetric) { 199 bool Connect(DtlsTestClient* peer, bool asymmetric) {
198 transport_->SetDestination(peer->transport_.get(), asymmetric); 200 transport_->SetDestination(peer->transport_.get(), asymmetric);
199 return true; 201 return true;
200 } 202 }
201 203
202 bool all_channels_writable() const { 204 bool all_channels_writable() const {
203 if (channels_.empty()) { 205 if (channels_.empty()) {
204 return false; 206 return false;
(...skipping 15 matching lines...) Expand all
220 return false; 222 return false;
221 } 223 }
222 } 224 }
223 return true; 225 return true;
224 } 226 }
225 227
226 int received_dtls_client_hellos() const { 228 int received_dtls_client_hellos() const {
227 return received_dtls_client_hellos_; 229 return received_dtls_client_hellos_;
228 } 230 }
229 231
232 bool negotiated_dtls() const { return set_local_cert_ && set_remote_cert_; }
233
230 void CheckRole(rtc::SSLRole role) { 234 void CheckRole(rtc::SSLRole role) {
231 if (role == rtc::SSL_CLIENT) { 235 if (role == rtc::SSL_CLIENT) {
232 ASSERT_EQ(0, received_dtls_client_hellos_); 236 ASSERT_EQ(0, received_dtls_client_hellos_);
233 ASSERT_GT(received_dtls_server_hellos_, 0); 237 ASSERT_GT(received_dtls_server_hellos_, 0);
234 } else { 238 } else {
235 ASSERT_GT(received_dtls_client_hellos_, 0); 239 ASSERT_GT(received_dtls_client_hellos_, 0);
236 ASSERT_EQ(0, received_dtls_server_hellos_); 240 ASSERT_EQ(0, received_dtls_server_hellos_);
237 } 241 }
238 } 242 }
239 243
240 void CheckSrtp(int expected_crypto_suite) { 244 void CheckSrtp(int expected_crypto_suite) {
241 for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it = 245 for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it =
242 channels_.begin(); it != channels_.end(); ++it) { 246 channels_.begin(); it != channels_.end(); ++it) {
243 int crypto_suite; 247 int crypto_suite;
244 248
245 bool rv = (*it)->GetSrtpCryptoSuite(&crypto_suite); 249 bool rv = (*it)->GetSrtpCryptoSuite(&crypto_suite);
246 if (negotiated_dtls_ && expected_crypto_suite) { 250 if (negotiated_dtls() && expected_crypto_suite) {
247 ASSERT_TRUE(rv); 251 ASSERT_TRUE(rv);
248 252
249 ASSERT_EQ(crypto_suite, expected_crypto_suite); 253 ASSERT_EQ(crypto_suite, expected_crypto_suite);
250 } else { 254 } else {
251 ASSERT_FALSE(rv); 255 ASSERT_FALSE(rv);
252 } 256 }
253 } 257 }
254 } 258 }
255 259
256 void CheckSsl() { 260 void CheckSsl() {
257 for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it = 261 for (std::vector<cricket::DtlsTransportChannelWrapper*>::iterator it =
258 channels_.begin(); it != channels_.end(); ++it) { 262 channels_.begin(); it != channels_.end(); ++it) {
259 int cipher; 263 int cipher;
260 264
261 bool rv = (*it)->GetSslCipherSuite(&cipher); 265 bool rv = (*it)->GetSslCipherSuite(&cipher);
262 if (negotiated_dtls_) { 266 if (negotiated_dtls()) {
263 ASSERT_TRUE(rv); 267 ASSERT_TRUE(rv);
264 268
265 EXPECT_TRUE( 269 EXPECT_TRUE(
266 rtc::SSLStreamAdapter::IsAcceptableCipher(cipher, rtc::KT_DEFAULT)); 270 rtc::SSLStreamAdapter::IsAcceptableCipher(cipher, rtc::KT_DEFAULT));
267 } else { 271 } else {
268 ASSERT_FALSE(rv); 272 ASSERT_FALSE(rv);
269 } 273 }
270 } 274 }
271 } 275 }
272 276
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 ASSERT_EQ(0, flags); 385 ASSERT_EQ(0, flags);
382 386
383 // Look at the handshake packets to see what role we played. 387 // Look at the handshake packets to see what role we played.
384 // Check that non-handshake packets are DTLS data or SRTP bypass. 388 // Check that non-handshake packets are DTLS data or SRTP bypass.
385 if (data[0] == 22 && size > 17) { 389 if (data[0] == 22 && size > 17) {
386 if (data[13] == 1) { 390 if (data[13] == 1) {
387 ++received_dtls_client_hellos_; 391 ++received_dtls_client_hellos_;
388 } else if (data[13] == 2) { 392 } else if (data[13] == 2) {
389 ++received_dtls_server_hellos_; 393 ++received_dtls_server_hellos_;
390 } 394 }
391 } else if (negotiated_dtls_ && !(data[0] >= 20 && data[0] <= 22)) { 395 } else if (negotiated_dtls() && !(data[0] >= 20 && data[0] <= 22)) {
392 ASSERT_TRUE(data[0] == 23 || IsRtpLeadByte(data[0])); 396 ASSERT_TRUE(data[0] == 23 || IsRtpLeadByte(data[0]));
393 if (data[0] == 23) { 397 if (data[0] == 23) {
394 ASSERT_TRUE(VerifyEncryptedPacket(data, size)); 398 ASSERT_TRUE(VerifyEncryptedPacket(data, size));
395 } else if (IsRtpLeadByte(data[0])) { 399 } else if (IsRtpLeadByte(data[0])) {
396 ASSERT_TRUE(VerifyPacket(data, size, NULL)); 400 ASSERT_TRUE(VerifyPacket(data, size, NULL));
397 } 401 }
398 } 402 }
399 } 403 }
400 404
401 private: 405 private:
402 std::string name_; 406 std::string name_;
403 rtc::scoped_refptr<rtc::RTCCertificate> certificate_; 407 rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
404 std::unique_ptr<cricket::FakeTransport> transport_; 408 std::unique_ptr<cricket::FakeTransport> transport_;
405 std::vector<cricket::DtlsTransportChannelWrapper*> channels_; 409 std::vector<cricket::DtlsTransportChannelWrapper*> channels_;
406 size_t packet_size_ = 0u; 410 size_t packet_size_ = 0u;
407 std::set<int> received_; 411 std::set<int> received_;
408 bool use_dtls_srtp_ = false; 412 bool use_dtls_srtp_ = false;
409 rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; 413 rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
410 bool negotiated_dtls_ = false; 414 bool set_local_cert_ = false;
415 bool set_remote_cert_ = false;
411 int received_dtls_client_hellos_ = 0; 416 int received_dtls_client_hellos_ = 0;
412 int received_dtls_server_hellos_ = 0; 417 int received_dtls_server_hellos_ = 0;
413 rtc::SentPacket sent_packet_; 418 rtc::SentPacket sent_packet_;
414 }; 419 };
415 420
416 // Note that this test always uses a FakeClock, due to the |fake_clock_| member 421 // Note that this test always uses a FakeClock, due to the |fake_clock_| member
417 // variable. 422 // variable.
418 class DtlsTransportChannelTest : public testing::Test { 423 class DtlsTransportChannelTest : public testing::Test {
419 public: 424 public:
420 DtlsTransportChannelTest() 425 DtlsTransportChannelTest()
(...skipping 29 matching lines...) Expand all
450 455
451 if (c1) 456 if (c1)
452 client1_.SetupSrtp(); 457 client1_.SetupSrtp();
453 if (c2) 458 if (c2)
454 client2_.SetupSrtp(); 459 client2_.SetupSrtp();
455 460
456 if (c1 && c2) 461 if (c1 && c2)
457 use_dtls_srtp_ = true; 462 use_dtls_srtp_ = true;
458 } 463 }
459 464
460 bool Connect(ConnectionRole client1_role, ConnectionRole client2_role) { 465 // Negotiate local/remote fingerprint before or after the underlying
461 Negotiate(client1_role, client2_role); 466 // tranpsort is connected?
467 enum NegotiateOrdering { NEGOTIATE_BEFORE_CONNECT, CONNECT_BEFORE_NEGOTIATE };
468 bool Connect(ConnectionRole client1_role,
469 ConnectionRole client2_role,
470 NegotiateOrdering ordering = NEGOTIATE_BEFORE_CONNECT) {
471 bool rv;
472 if (ordering == NEGOTIATE_BEFORE_CONNECT) {
473 Negotiate(client1_role, client2_role);
474 rv = client1_.Connect(&client2_, false);
475 } else {
476 client1_.SetupChannels(channel_ct_, cricket::ICEROLE_CONTROLLING);
477 client2_.SetupChannels(channel_ct_, cricket::ICEROLE_CONTROLLED);
478 client1_.MaybeSetSrtpCryptoSuites();
479 client2_.MaybeSetSrtpCryptoSuites();
480 // This is equivalent to an offer being processed on both sides, but an
481 // answer not yet being received on the initiating side. So the
482 // connection will be made before negotiation has finished on both sides.
483 client1_.SetLocalTransportDescription(client1_.certificate(),
484 cricket::CA_OFFER, client1_role, 0);
485 client2_.SetRemoteTransportDescription(
486 client1_.certificate(), cricket::CA_OFFER, client1_role, 0);
487 client2_.SetLocalTransportDescription(
488 client2_.certificate(), cricket::CA_ANSWER, client2_role, 0);
489 rv = client1_.Connect(&client2_, false);
490 client1_.SetRemoteTransportDescription(
491 client2_.certificate(), cricket::CA_ANSWER, client2_role, 0);
492 }
462 493
463 bool rv = client1_.Connect(&client2_, false);
464 EXPECT_TRUE(rv); 494 EXPECT_TRUE(rv);
465 if (!rv) 495 if (!rv)
466 return false; 496 return false;
467 497
468 EXPECT_TRUE_WAIT( 498 EXPECT_TRUE_WAIT(
469 client1_.all_channels_writable() && client2_.all_channels_writable(), 499 client1_.all_channels_writable() && client2_.all_channels_writable(),
470 kTimeout); 500 kTimeout);
471 if (!client1_.all_channels_writable() || !client2_.all_channels_writable()) 501 if (!client1_.all_channels_writable() || !client2_.all_channels_writable())
472 return false; 502 return false;
473 503
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 // millisecond before the expected time and verify that no unexpected 1041 // millisecond before the expected time and verify that no unexpected
1012 // retransmissions were sent. Then advance it the final millisecond and 1042 // retransmissions were sent. Then advance it the final millisecond and
1013 // verify that the expected retransmission was sent. 1043 // verify that the expected retransmission was sent.
1014 fake_clock_.AdvanceTime( 1044 fake_clock_.AdvanceTime(
1015 rtc::TimeDelta::FromMilliseconds(timeout_schedule_ms[i] - 1)); 1045 rtc::TimeDelta::FromMilliseconds(timeout_schedule_ms[i] - 1));
1016 EXPECT_EQ(expected_hellos, client1_.received_dtls_client_hellos()); 1046 EXPECT_EQ(expected_hellos, client1_.received_dtls_client_hellos());
1017 fake_clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); 1047 fake_clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
1018 EXPECT_EQ(++expected_hellos, client1_.received_dtls_client_hellos()); 1048 EXPECT_EQ(++expected_hellos, client1_.received_dtls_client_hellos());
1019 } 1049 }
1020 } 1050 }
1051
1052 // Test that a DTLS connection can be made even if the underlying transport
1053 // is connected before DTLS fingerprints/roles have been negotiated.
1054 TEST_F(DtlsTransportChannelTest, TestConnectBeforeNegotiate) {
1055 MAYBE_SKIP_TEST(HaveDtls);
1056 PrepareDtls(true, true, rtc::KT_DEFAULT);
1057 ASSERT_TRUE(Connect(cricket::CONNECTIONROLE_ACTPASS,
1058 cricket::CONNECTIONROLE_ACTIVE,
1059 CONNECT_BEFORE_NEGOTIATE));
1060 TestTransfer(0, 1000, 100, false);
1061 }
OLDNEW
« no previous file with comments | « webrtc/p2p/base/dtlstransportchannel.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698