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 "talk/p2p/base/dtlstransportchannel.h"
30
31 #include "talk/base/buffer.h"
32 #include "talk/base/dscp.h"
33 #include "talk/base/messagequeue.h"
34 #include "talk/base/stream.h"
35 #include "talk/base/sslstreamadapter.h"
36 #include "talk/base/thread.h"
37 #include "talk/p2p/base/common.h"
38
39 namespace cricket {
40
41 // We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
42 static const size_t kDtlsRecordHeaderLen = 13;
43 static const size_t kMaxDtlsPacketLen = 2048;
44 static const size_t kMinRtpPacketLen = 12;
45
IsDtlsPacket(const char * data,size_t len)46 static bool IsDtlsPacket(const char* data, size_t len) {
47 const uint8* u = reinterpret_cast<const uint8*>(data);
48 return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
49 }
IsRtpPacket(const char * data,size_t len)50 static bool IsRtpPacket(const char* data, size_t len) {
51 const uint8* u = reinterpret_cast<const uint8*>(data);
52 return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
53 }
54
Read(void * buffer,size_t buffer_len,size_t * read,int * error)55 talk_base::StreamResult StreamInterfaceChannel::Read(void* buffer,
56 size_t buffer_len,
57 size_t* read,
58 int* error) {
59 if (state_ == talk_base::SS_CLOSED)
60 return talk_base::SR_EOS;
61 if (state_ == talk_base::SS_OPENING)
62 return talk_base::SR_BLOCK;
63
64 return fifo_.Read(buffer, buffer_len, read, error);
65 }
66
Write(const void * data,size_t data_len,size_t * written,int * error)67 talk_base::StreamResult StreamInterfaceChannel::Write(const void* data,
68 size_t data_len,
69 size_t* written,
70 int* error) {
71 // Always succeeds, since this is an unreliable transport anyway.
72 // TODO: Should this block if channel_'s temporarily unwritable?
73 talk_base::PacketOptions packet_options;
74 channel_->SendPacket(static_cast<const char*>(data), data_len,
75 packet_options);
76 if (written) {
77 *written = data_len;
78 }
79 return talk_base::SR_SUCCESS;
80 }
81
OnPacketReceived(const char * data,size_t size)82 bool StreamInterfaceChannel::OnPacketReceived(const char* data, size_t size) {
83 // We force a read event here to ensure that we don't overflow our FIFO.
84 // Under high packet rate this can occur if we wait for the FIFO to post its
85 // own SE_READ.
86 bool ret = (fifo_.WriteAll(data, size, NULL, NULL) == talk_base::SR_SUCCESS);
87 if (ret) {
88 SignalEvent(this, talk_base::SE_READ, 0);
89 }
90 return ret;
91 }
92
OnEvent(talk_base::StreamInterface * stream,int sig,int err)93 void StreamInterfaceChannel::OnEvent(talk_base::StreamInterface* stream,
94 int sig, int err) {
95 SignalEvent(this, sig, err);
96 }
97
DtlsTransportChannelWrapper(Transport * transport,TransportChannelImpl * channel)98 DtlsTransportChannelWrapper::DtlsTransportChannelWrapper(
99 Transport* transport,
100 TransportChannelImpl* channel)
101 : TransportChannelImpl(channel->content_name(), channel->component()),
102 transport_(transport),
103 worker_thread_(talk_base::Thread::Current()),
104 channel_(channel),
105 downward_(NULL),
106 dtls_state_(STATE_NONE),
107 local_identity_(NULL),
108 ssl_role_(talk_base::SSL_CLIENT) {
109 channel_->SignalReadableState.connect(this,
110 &DtlsTransportChannelWrapper::OnReadableState);
111 channel_->SignalWritableState.connect(this,
112 &DtlsTransportChannelWrapper::OnWritableState);
113 channel_->SignalReadPacket.connect(this,
114 &DtlsTransportChannelWrapper::OnReadPacket);
115 channel_->SignalReadyToSend.connect(this,
116 &DtlsTransportChannelWrapper::OnReadyToSend);
117 channel_->SignalRequestSignaling.connect(this,
118 &DtlsTransportChannelWrapper::OnRequestSignaling);
119 channel_->SignalCandidateReady.connect(this,
120 &DtlsTransportChannelWrapper::OnCandidateReady);
121 channel_->SignalCandidatesAllocationDone.connect(this,
122 &DtlsTransportChannelWrapper::OnCandidatesAllocationDone);
123 channel_->SignalRoleConflict.connect(this,
124 &DtlsTransportChannelWrapper::OnRoleConflict);
125 channel_->SignalRouteChange.connect(this,
126 &DtlsTransportChannelWrapper::OnRouteChange);
127 channel_->SignalConnectionRemoved.connect(this,
128 &DtlsTransportChannelWrapper::OnConnectionRemoved);
129 }
130
~DtlsTransportChannelWrapper()131 DtlsTransportChannelWrapper::~DtlsTransportChannelWrapper() {
132 }
133
Connect()134 void DtlsTransportChannelWrapper::Connect() {
135 // We should only get a single call to Connect.
136 ASSERT(dtls_state_ == STATE_NONE ||
137 dtls_state_ == STATE_OFFERED ||
138 dtls_state_ == STATE_ACCEPTED);
139 channel_->Connect();
140 }
141
Reset()142 void DtlsTransportChannelWrapper::Reset() {
143 channel_->Reset();
144 set_writable(false);
145 set_readable(false);
146
147 // Re-call SetupDtls()
148 if (!SetupDtls()) {
149 LOG_J(LS_ERROR, this) << "Error re-initializing DTLS";
150 dtls_state_ = STATE_CLOSED;
151 return;
152 }
153
154 dtls_state_ = STATE_ACCEPTED;
155 }
156
SetLocalIdentity(talk_base::SSLIdentity * identity)157 bool DtlsTransportChannelWrapper::SetLocalIdentity(
158 talk_base::SSLIdentity* identity) {
159 if (dtls_state_ != STATE_NONE) {
160 if (identity == local_identity_) {
161 // This may happen during renegotiation.
162 LOG_J(LS_INFO, this) << "Ignoring identical DTLS identity";
163 return true;
164 } else {
165 LOG_J(LS_ERROR, this) << "Can't change DTLS local identity in this state";
166 return false;
167 }
168 }
169
170 if (identity) {
171 local_identity_ = identity;
172 dtls_state_ = STATE_OFFERED;
173 } else {
174 LOG_J(LS_INFO, this) << "NULL DTLS identity supplied. Not doing DTLS";
175 }
176
177 return true;
178 }
179
GetLocalIdentity(talk_base::SSLIdentity ** identity) const180 bool DtlsTransportChannelWrapper::GetLocalIdentity(
181 talk_base::SSLIdentity** identity) const {
182 if (!local_identity_)
183 return false;
184
185 *identity = local_identity_->GetReference();
186 return true;
187 }
188
SetSslRole(talk_base::SSLRole role)189 bool DtlsTransportChannelWrapper::SetSslRole(talk_base::SSLRole role) {
190 if (dtls_state_ == STATE_OPEN) {
191 if (ssl_role_ != role) {
192 LOG(LS_ERROR) << "SSL Role can't be reversed after the session is setup.";
193 return false;
194 }
195 return true;
196 }
197
198 ssl_role_ = role;
199 return true;
200 }
201
GetSslRole(talk_base::SSLRole * role) const202 bool DtlsTransportChannelWrapper::GetSslRole(talk_base::SSLRole* role) const {
203 *role = ssl_role_;
204 return true;
205 }
206
SetRemoteFingerprint(const std::string & digest_alg,const uint8 * digest,size_t digest_len)207 bool DtlsTransportChannelWrapper::SetRemoteFingerprint(
208 const std::string& digest_alg,
209 const uint8* digest,
210 size_t digest_len) {
211
212 talk_base::Buffer remote_fingerprint_value(digest, digest_len);
213
214 if (dtls_state_ != STATE_NONE &&
215 remote_fingerprint_value_ == remote_fingerprint_value &&
216 !digest_alg.empty()) {
217 // This may happen during renegotiation.
218 LOG_J(LS_INFO, this) << "Ignoring identical remote DTLS fingerprint";
219 return true;
220 }
221
222 // Allow SetRemoteFingerprint with a NULL digest even if SetLocalIdentity
223 // hasn't been called.
224 if (dtls_state_ > STATE_OFFERED ||
225 (dtls_state_ == STATE_NONE && !digest_alg.empty())) {
226 LOG_J(LS_ERROR, this) << "Can't set DTLS remote settings in this state.";
227 return false;
228 }
229
230 if (digest_alg.empty()) {
231 LOG_J(LS_INFO, this) << "Other side didn't support DTLS.";
232 dtls_state_ = STATE_NONE;
233 return true;
234 }
235
236 // At this point we know we are doing DTLS
237 remote_fingerprint_value.TransferTo(&remote_fingerprint_value_);
238 remote_fingerprint_algorithm_ = digest_alg;
239
240 if (!SetupDtls()) {
241 dtls_state_ = STATE_CLOSED;
242 return false;
243 }
244
245 dtls_state_ = STATE_ACCEPTED;
246 return true;
247 }
248
GetRemoteCertificate(talk_base::SSLCertificate ** cert) const249 bool DtlsTransportChannelWrapper::GetRemoteCertificate(
250 talk_base::SSLCertificate** cert) const {
251 if (!dtls_)
252 return false;
253
254 return dtls_->GetPeerCertificate(cert);
255 }
256
SetupDtls()257 bool DtlsTransportChannelWrapper::SetupDtls() {
258 StreamInterfaceChannel* downward =
259 new StreamInterfaceChannel(worker_thread_, channel_);
260
261 dtls_.reset(talk_base::SSLStreamAdapter::Create(downward));
262 if (!dtls_) {
263 LOG_J(LS_ERROR, this) << "Failed to create DTLS adapter.";
264 delete downward;
265 return false;
266 }
267
268 downward_ = downward;
269
270 dtls_->SetIdentity(local_identity_->GetReference());
271 dtls_->SetMode(talk_base::SSL_MODE_DTLS);
272 dtls_->SetServerRole(ssl_role_);
273 dtls_->SignalEvent.connect(this, &DtlsTransportChannelWrapper::OnDtlsEvent);
274 if (!dtls_->SetPeerCertificateDigest(
275 remote_fingerprint_algorithm_,
276 reinterpret_cast<unsigned char *>(remote_fingerprint_value_.data()),
277 remote_fingerprint_value_.length())) {
278 LOG_J(LS_ERROR, this) << "Couldn't set DTLS certificate digest.";
279 return false;
280 }
281
282 // Set up DTLS-SRTP, if it's been enabled.
283 if (!srtp_ciphers_.empty()) {
284 if (!dtls_->SetDtlsSrtpCiphers(srtp_ciphers_)) {
285 LOG_J(LS_ERROR, this) << "Couldn't set DTLS-SRTP ciphers.";
286 return false;
287 }
288 } else {
289 LOG_J(LS_INFO, this) << "Not using DTLS.";
290 }
291
292 LOG_J(LS_INFO, this) << "DTLS setup complete.";
293 return true;
294 }
295
SetSrtpCiphers(const std::vector<std::string> & ciphers)296 bool DtlsTransportChannelWrapper::SetSrtpCiphers(
297 const std::vector<std::string>& ciphers) {
298 if (srtp_ciphers_ == ciphers)
299 return true;
300
301 if (dtls_state_ == STATE_OPEN) {
302 // We don't support DTLS renegotiation currently. If new set of srtp ciphers
303 // are different than what's being used currently, we will not use it.
304 // So for now, let's be happy (or sad) with a warning message.
305 std::string current_srtp_cipher;
306 if (!dtls_->GetDtlsSrtpCipher(¤t_srtp_cipher)) {
307 LOG(LS_ERROR) << "Failed to get the current SRTP cipher for DTLS channel";
308 return false;
309 }
310 const std::vector<std::string>::const_iterator iter =
311 std::find(ciphers.begin(), ciphers.end(), current_srtp_cipher);
312 if (iter == ciphers.end()) {
313 std::string requested_str;
314 for (size_t i = 0; i < ciphers.size(); ++i) {
315 requested_str.append(" ");
316 requested_str.append(ciphers[i]);
317 requested_str.append(" ");
318 }
319 LOG(LS_WARNING) << "Ignoring new set of SRTP ciphers, as DTLS "
320 << "renegotiation is not supported currently "
321 << "current cipher = " << current_srtp_cipher << " and "
322 << "requested = " << "[" << requested_str << "]";
323 }
324 return true;
325 }
326
327 if (dtls_state_ != STATE_NONE &&
328 dtls_state_ != STATE_OFFERED &&
329 dtls_state_ != STATE_ACCEPTED) {
330 ASSERT(false);
331 return false;
332 }
333
334 srtp_ciphers_ = ciphers;
335 return true;
336 }
337
GetSrtpCipher(std::string * cipher)338 bool DtlsTransportChannelWrapper::GetSrtpCipher(std::string* cipher) {
339 if (dtls_state_ != STATE_OPEN) {
340 return false;
341 }
342
343 return dtls_->GetDtlsSrtpCipher(cipher);
344 }
345
346
347 // Called from upper layers to send a media packet.
SendPacket(const char * data,size_t size,const talk_base::PacketOptions & options,int flags)348 int DtlsTransportChannelWrapper::SendPacket(
349 const char* data, size_t size,
350 const talk_base::PacketOptions& options, int flags) {
351 int result = -1;
352
353 switch (dtls_state_) {
354 case STATE_OFFERED:
355 // We don't know if we are doing DTLS yet, so we can't send a packet.
356 // TODO(ekr@rtfm.com): assert here?
357 result = -1;
358 break;
359
360 case STATE_STARTED:
361 case STATE_ACCEPTED:
362 // Can't send data until the connection is active
363 result = -1;
364 break;
365
366 case STATE_OPEN:
367 if (flags & PF_SRTP_BYPASS) {
368 ASSERT(!srtp_ciphers_.empty());
369 if (!IsRtpPacket(data, size)) {
370 result = -1;
371 break;
372 }
373
374 result = channel_->SendPacket(data, size, options);
375 } else {
376 result = (dtls_->WriteAll(data, size, NULL, NULL) ==
377 talk_base::SR_SUCCESS) ? static_cast<int>(size) : -1;
378 }
379 break;
380 // Not doing DTLS.
381 case STATE_NONE:
382 result = channel_->SendPacket(data, size, options);
383 break;
384
385 case STATE_CLOSED: // Can't send anything when we're closed.
386 return -1;
387 }
388
389 return result;
390 }
391
392 // The state transition logic here is as follows:
393 // (1) If we're not doing DTLS-SRTP, then the state is just the
394 // state of the underlying impl()
395 // (2) If we're doing DTLS-SRTP:
396 // - Prior to the DTLS handshake, the state is neither readable or
397 // writable
398 // - When the impl goes writable for the first time we
399 // start the DTLS handshake
400 // - Once the DTLS handshake completes, the state is that of the
401 // impl again
OnReadableState(TransportChannel * channel)402 void DtlsTransportChannelWrapper::OnReadableState(TransportChannel* channel) {
403 ASSERT(talk_base::Thread::Current() == worker_thread_);
404 ASSERT(channel == channel_);
405 LOG_J(LS_VERBOSE, this)
406 << "DTLSTransportChannelWrapper: channel readable state changed.";
407
408 if (dtls_state_ == STATE_NONE || dtls_state_ == STATE_OPEN) {
409 set_readable(channel_->readable());
410 // Note: SignalReadableState fired by set_readable.
411 }
412 }
413
OnWritableState(TransportChannel * channel)414 void DtlsTransportChannelWrapper::OnWritableState(TransportChannel* channel) {
415 ASSERT(talk_base::Thread::Current() == worker_thread_);
416 ASSERT(channel == channel_);
417 LOG_J(LS_VERBOSE, this)
418 << "DTLSTransportChannelWrapper: channel writable state changed.";
419
420 switch (dtls_state_) {
421 case STATE_NONE:
422 case STATE_OPEN:
423 set_writable(channel_->writable());
424 // Note: SignalWritableState fired by set_writable.
425 break;
426
427 case STATE_OFFERED:
428 // Do nothing
429 break;
430
431 case STATE_ACCEPTED:
432 if (!MaybeStartDtls()) {
433 // This should never happen:
434 // Because we are operating in a nonblocking mode and all
435 // incoming packets come in via OnReadPacket(), which rejects
436 // packets in this state, the incoming queue must be empty. We
437 // ignore write errors, thus any errors must be because of
438 // configuration and therefore are our fault.
439 // Note that in non-debug configurations, failure in
440 // MaybeStartDtls() changes the state to STATE_CLOSED.
441 ASSERT(false);
442 }
443 break;
444
445 case STATE_STARTED:
446 // Do nothing
447 break;
448
449 case STATE_CLOSED:
450 // Should not happen. Do nothing
451 break;
452 }
453 }
454
OnReadPacket(TransportChannel * channel,const char * data,size_t size,const talk_base::PacketTime & packet_time,int flags)455 void DtlsTransportChannelWrapper::OnReadPacket(
456 TransportChannel* channel, const char* data, size_t size,
457 const talk_base::PacketTime& packet_time, int flags) {
458 ASSERT(talk_base::Thread::Current() == worker_thread_);
459 ASSERT(channel == channel_);
460 ASSERT(flags == 0);
461
462 switch (dtls_state_) {
463 case STATE_NONE:
464 // We are not doing DTLS
465 SignalReadPacket(this, data, size, packet_time, 0);
466 break;
467
468 case STATE_OFFERED:
469 // Currently drop the packet, but we might in future
470 // decide to take this as evidence that the other
471 // side is ready to do DTLS and start the handshake
472 // on our end
473 LOG_J(LS_WARNING, this) << "Received packet before we know if we are "
474 << "doing DTLS or not; dropping.";
475 break;
476
477 case STATE_ACCEPTED:
478 // Drop packets received before DTLS has actually started
479 LOG_J(LS_INFO, this) << "Dropping packet received before DTLS started.";
480 break;
481
482 case STATE_STARTED:
483 case STATE_OPEN:
484 // We should only get DTLS or SRTP packets; STUN's already been demuxed.
485 // Is this potentially a DTLS packet?
486 if (IsDtlsPacket(data, size)) {
487 if (!HandleDtlsPacket(data, size)) {
488 LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
489 return;
490 }
491 } else {
492 // Not a DTLS packet; our handshake should be complete by now.
493 if (dtls_state_ != STATE_OPEN) {
494 LOG_J(LS_ERROR, this) << "Received non-DTLS packet before DTLS "
495 << "complete.";
496 return;
497 }
498
499 // And it had better be a SRTP packet.
500 if (!IsRtpPacket(data, size)) {
501 LOG_J(LS_ERROR, this) << "Received unexpected non-DTLS packet.";
502 return;
503 }
504
505 // Sanity check.
506 ASSERT(!srtp_ciphers_.empty());
507
508 // Signal this upwards as a bypass packet.
509 SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
510 }
511 break;
512 case STATE_CLOSED:
513 // This shouldn't be happening. Drop the packet
514 break;
515 }
516 }
517
OnReadyToSend(TransportChannel * channel)518 void DtlsTransportChannelWrapper::OnReadyToSend(TransportChannel* channel) {
519 if (writable()) {
520 SignalReadyToSend(this);
521 }
522 }
523
OnDtlsEvent(talk_base::StreamInterface * dtls,int sig,int err)524 void DtlsTransportChannelWrapper::OnDtlsEvent(talk_base::StreamInterface* dtls,
525 int sig, int err) {
526 ASSERT(talk_base::Thread::Current() == worker_thread_);
527 ASSERT(dtls == dtls_.get());
528 if (sig & talk_base::SE_OPEN) {
529 // This is the first time.
530 LOG_J(LS_INFO, this) << "DTLS handshake complete.";
531 if (dtls_->GetState() == talk_base::SS_OPEN) {
532 // The check for OPEN shouldn't be necessary but let's make
533 // sure we don't accidentally frob the state if it's closed.
534 dtls_state_ = STATE_OPEN;
535
536 set_readable(true);
537 set_writable(true);
538 }
539 }
540 if (sig & talk_base::SE_READ) {
541 char buf[kMaxDtlsPacketLen];
542 size_t read;
543 if (dtls_->Read(buf, sizeof(buf), &read, NULL) == talk_base::SR_SUCCESS) {
544 SignalReadPacket(this, buf, read, talk_base::CreatePacketTime(0), 0);
545 }
546 }
547 if (sig & talk_base::SE_CLOSE) {
548 ASSERT(sig == talk_base::SE_CLOSE); // SE_CLOSE should be by itself.
549 if (!err) {
550 LOG_J(LS_INFO, this) << "DTLS channel closed";
551 } else {
552 LOG_J(LS_INFO, this) << "DTLS channel error, code=" << err;
553 }
554
555 set_readable(false);
556 set_writable(false);
557 dtls_state_ = STATE_CLOSED;
558 }
559 }
560
MaybeStartDtls()561 bool DtlsTransportChannelWrapper::MaybeStartDtls() {
562 if (channel_->writable()) {
563 if (dtls_->StartSSLWithPeer()) {
564 LOG_J(LS_ERROR, this) << "Couldn't start DTLS handshake";
565 dtls_state_ = STATE_CLOSED;
566 return false;
567 }
568 LOG_J(LS_INFO, this)
569 << "DtlsTransportChannelWrapper: Started DTLS handshake";
570
571 dtls_state_ = STATE_STARTED;
572 }
573 return true;
574 }
575
576 // Called from OnReadPacket when a DTLS packet is received.
HandleDtlsPacket(const char * data,size_t size)577 bool DtlsTransportChannelWrapper::HandleDtlsPacket(const char* data,
578 size_t size) {
579 // Sanity check we're not passing junk that
580 // just looks like DTLS.
581 const uint8* tmp_data = reinterpret_cast<const uint8* >(data);
582 size_t tmp_size = size;
583 while (tmp_size > 0) {
584 if (tmp_size < kDtlsRecordHeaderLen)
585 return false; // Too short for the header
586
587 size_t record_len = (tmp_data[11] << 8) | (tmp_data[12]);
588 if ((record_len + kDtlsRecordHeaderLen) > tmp_size)
589 return false; // Body too short
590
591 tmp_data += record_len + kDtlsRecordHeaderLen;
592 tmp_size -= record_len + kDtlsRecordHeaderLen;
593 }
594
595 // Looks good. Pass to the SIC which ends up being passed to
596 // the DTLS stack.
597 return downward_->OnPacketReceived(data, size);
598 }
599
OnRequestSignaling(TransportChannelImpl * channel)600 void DtlsTransportChannelWrapper::OnRequestSignaling(
601 TransportChannelImpl* channel) {
602 ASSERT(channel == channel_);
603 SignalRequestSignaling(this);
604 }
605
OnCandidateReady(TransportChannelImpl * channel,const Candidate & c)606 void DtlsTransportChannelWrapper::OnCandidateReady(
607 TransportChannelImpl* channel, const Candidate& c) {
608 ASSERT(channel == channel_);
609 SignalCandidateReady(this, c);
610 }
611
OnCandidatesAllocationDone(TransportChannelImpl * channel)612 void DtlsTransportChannelWrapper::OnCandidatesAllocationDone(
613 TransportChannelImpl* channel) {
614 ASSERT(channel == channel_);
615 SignalCandidatesAllocationDone(this);
616 }
617
OnRoleConflict(TransportChannelImpl * channel)618 void DtlsTransportChannelWrapper::OnRoleConflict(
619 TransportChannelImpl* channel) {
620 ASSERT(channel == channel_);
621 SignalRoleConflict(this);
622 }
623
OnRouteChange(TransportChannel * channel,const Candidate & candidate)624 void DtlsTransportChannelWrapper::OnRouteChange(
625 TransportChannel* channel, const Candidate& candidate) {
626 ASSERT(channel == channel_);
627 SignalRouteChange(this, candidate);
628 }
629
OnConnectionRemoved(TransportChannelImpl * channel)630 void DtlsTransportChannelWrapper::OnConnectionRemoved(
631 TransportChannelImpl* channel) {
632 ASSERT(channel == channel_);
633 SignalConnectionRemoved(this);
634 }
635
636 } // namespace cricket
637