10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2011, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2011, RTFM, Inc.
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/dtlstransportchannel.h"
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
31cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/p2p/base/common.h"
322a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/buffer.h"
332a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/dscp.h"
342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/messagequeue.h"
352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/sslstreamadapter.h"
36cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stream.h"
372a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/thread.h"
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const size_t kDtlsRecordHeaderLen = 13;
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const size_t kMaxDtlsPacketLen = 2048;
4419f7dc99c2237edcf92563a6a099fb063edf5e8fjiayl@webrtc.orgstatic const size_t kMinRtpPacketLen = 12;
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool IsDtlsPacket(const char* data, size_t len) {
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* u = reinterpret_cast<const uint8*>(data);
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5019f7dc99c2237edcf92563a6a099fb063edf5e8fjiayl@webrtc.orgstatic bool IsRtpPacket(const char* data, size_t len) {
5119f7dc99c2237edcf92563a6a099fb063edf5e8fjiayl@webrtc.org  const uint8* u = reinterpret_cast<const uint8*>(data);
5219f7dc99c2237edcf92563a6a099fb063edf5e8fjiayl@webrtc.org  return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
5319f7dc99c2237edcf92563a6a099fb063edf5e8fjiayl@webrtc.org}
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
552a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgrtc::StreamResult StreamInterfaceChannel::Read(void* buffer,
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                     size_t buffer_len,
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                     size_t* read,
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                     int* error) {
592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (state_ == rtc::SS_CLOSED)
602a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    return rtc::SR_EOS;
612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (state_ == rtc::SS_OPENING)
622a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    return rtc::SR_BLOCK;
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return fifo_.Read(buffer, buffer_len, read, error);
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgrtc::StreamResult StreamInterfaceChannel::Write(const void* data,
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                      size_t data_len,
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                      size_t* written,
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                      int* error) {
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Always succeeds, since this is an unreliable transport anyway.
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: Should this block if channel_'s temporarily unwritable?
732a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::PacketOptions packet_options;
74f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  channel_->SendPacket(static_cast<const char*>(data), data_len,
75f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org                       packet_options);
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (written) {
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *written = data_len;
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
792a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  return rtc::SR_SUCCESS;
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool StreamInterfaceChannel::OnPacketReceived(const char* data, size_t size) {
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We force a read event here to ensure that we don't overflow our FIFO.
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Under high packet rate this can occur if we wait for the FIFO to post its
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // own SE_READ.
862a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  bool ret = (fifo_.WriteAll(data, size, NULL, NULL) == rtc::SR_SUCCESS);
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    SignalEvent(this, rtc::SE_READ, 0);
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
932a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid StreamInterfaceChannel::OnEvent(rtc::StreamInterface* stream,
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     int sig, int err) {
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalEvent(this, sig, err);
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgDtlsTransportChannelWrapper::DtlsTransportChannelWrapper(
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                           Transport* transport,
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                           TransportChannelImpl* channel)
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : TransportChannelImpl(channel->content_name(), channel->component()),
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      transport_(transport),
1032a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      worker_thread_(rtc::Thread::Current()),
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      channel_(channel),
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      downward_(NULL),
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtls_state_(STATE_NONE),
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      local_identity_(NULL),
1082a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      ssl_role_(rtc::SSL_CLIENT) {
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalReadableState.connect(this,
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnReadableState);
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalWritableState.connect(this,
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnWritableState);
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalReadPacket.connect(this,
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnReadPacket);
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalReadyToSend.connect(this,
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnReadyToSend);
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalRequestSignaling.connect(this,
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnRequestSignaling);
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalCandidateReady.connect(this,
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnCandidateReady);
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalCandidatesAllocationDone.connect(this,
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnCandidatesAllocationDone);
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalRoleConflict.connect(this,
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnRoleConflict);
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->SignalRouteChange.connect(this,
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &DtlsTransportChannelWrapper::OnRouteChange);
127f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  channel_->SignalConnectionRemoved.connect(this,
128f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      &DtlsTransportChannelWrapper::OnConnectionRemoved);
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgDtlsTransportChannelWrapper::~DtlsTransportChannelWrapper() {
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::Connect() {
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We should only get a single call to Connect.
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(dtls_state_ == STATE_NONE ||
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         dtls_state_ == STATE_OFFERED ||
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         dtls_state_ == STATE_ACCEPTED);
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->Connect();
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::Reset() {
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  channel_->Reset();
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_writable(false);
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_readable(false);
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Re-call SetupDtls()
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!SetupDtls()) {
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_J(LS_ERROR, this) << "Error re-initializing DTLS";
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    dtls_state_ = STATE_CLOSED;
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  dtls_state_ = STATE_ACCEPTED;
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
157e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.orgbool DtlsTransportChannelWrapper::SetLocalIdentity(
1582a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SSLIdentity* identity) {
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (dtls_state_ != STATE_NONE) {
160f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org    if (identity == local_identity_) {
161f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org      // This may happen during renegotiation.
162f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org      LOG_J(LS_INFO, this) << "Ignoring identical DTLS identity";
163f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org      return true;
164f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org    } else {
165f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org      LOG_J(LS_ERROR, this) << "Can't change DTLS local identity in this state";
166f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org      return false;
167f72f5a64fe04356b56ddfb84c6ed488d61ced7c4buildbot@webrtc.org    }
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (identity) {
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    local_identity_ = identity;
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    dtls_state_ = STATE_OFFERED;
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_J(LS_INFO, this) << "NULL DTLS identity supplied. Not doing DTLS";
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
18062fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.orgbool DtlsTransportChannelWrapper::GetLocalIdentity(
1812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SSLIdentity** identity) const {
18262fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  if (!local_identity_)
18362fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    return false;
18462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
18562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  *identity = local_identity_->GetReference();
18662fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  return true;
18762fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org}
18862fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
1892a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool DtlsTransportChannelWrapper::SetSslRole(rtc::SSLRole role) {
190a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  if (dtls_state_ == STATE_OPEN) {
191a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    if (ssl_role_ != role) {
192a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      LOG(LS_ERROR) << "SSL Role can't be reversed after the session is setup.";
193a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      return false;
194a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    }
195a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    return true;
196a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  }
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
198a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  ssl_role_ = role;
199a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  return true;
200a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org}
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2022a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool DtlsTransportChannelWrapper::GetSslRole(rtc::SSLRole* role) const {
203a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  *role = ssl_role_;
204a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  return true;
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
207e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.orgbool DtlsTransportChannelWrapper::SetRemoteFingerprint(
208e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    const std::string& digest_alg,
209e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    const uint8* digest,
210e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    size_t digest_len) {
211e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org
2122a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::Buffer remote_fingerprint_value(digest, digest_len);
213e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org
214b9a6b71b8a8db9a3a8e8888448529f9b4624ab32jiayl@webrtc.org  if (dtls_state_ != STATE_NONE &&
215b9a6b71b8a8db9a3a8e8888448529f9b4624ab32jiayl@webrtc.org      remote_fingerprint_value_ == remote_fingerprint_value &&
216b9a6b71b8a8db9a3a8e8888448529f9b4624ab32jiayl@webrtc.org      !digest_alg.empty()) {
217b9a6b71b8a8db9a3a8e8888448529f9b4624ab32jiayl@webrtc.org    // This may happen during renegotiation.
218b9a6b71b8a8db9a3a8e8888448529f9b4624ab32jiayl@webrtc.org    LOG_J(LS_INFO, this) << "Ignoring identical remote DTLS fingerprint";
219e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org    return true;
220e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  }
221e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Allow SetRemoteFingerprint with a NULL digest even if SetLocalIdentity
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // hasn't been called.
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (dtls_state_ > STATE_OFFERED ||
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (dtls_state_ == STATE_NONE && !digest_alg.empty())) {
226a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    LOG_J(LS_ERROR, this) << "Can't set DTLS remote settings in this state.";
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (digest_alg.empty()) {
231a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    LOG_J(LS_INFO, this) << "Other side didn't support DTLS.";
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    dtls_state_ = STATE_NONE;
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // At this point we know we are doing DTLS
237e560834da4ee5a5f38a96a8cb9290c5ce1096989mallinath@webrtc.org  remote_fingerprint_value.TransferTo(&remote_fingerprint_value_);
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_fingerprint_algorithm_ = digest_alg;
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!SetupDtls()) {
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    dtls_state_ = STATE_CLOSED;
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  dtls_state_ = STATE_ACCEPTED;
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
24962fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.orgbool DtlsTransportChannelWrapper::GetRemoteCertificate(
2502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SSLCertificate** cert) const {
25162fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  if (!dtls_)
25262fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    return false;
25362fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
25462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  return dtls_->GetPeerCertificate(cert);
25562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org}
25662fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool DtlsTransportChannelWrapper::SetupDtls() {
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StreamInterfaceChannel* downward =
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      new StreamInterfaceChannel(worker_thread_, channel_);
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  dtls_.reset(rtc::SSLStreamAdapter::Create(downward));
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!dtls_) {
263a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    LOG_J(LS_ERROR, this) << "Failed to create DTLS adapter.";
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete downward;
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  downward_ = downward;
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  dtls_->SetIdentity(local_identity_->GetReference());
2712a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  dtls_->SetMode(rtc::SSL_MODE_DTLS);
272a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  dtls_->SetServerRole(ssl_role_);
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  dtls_->SignalEvent.connect(this, &DtlsTransportChannelWrapper::OnDtlsEvent);
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!dtls_->SetPeerCertificateDigest(
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          remote_fingerprint_algorithm_,
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          reinterpret_cast<unsigned char *>(remote_fingerprint_value_.data()),
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          remote_fingerprint_value_.length())) {
278a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    LOG_J(LS_ERROR, this) << "Couldn't set DTLS certificate digest.";
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Set up DTLS-SRTP, if it's been enabled.
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!srtp_ciphers_.empty()) {
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!dtls_->SetDtlsSrtpCiphers(srtp_ciphers_)) {
285a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      LOG_J(LS_ERROR, this) << "Couldn't set DTLS-SRTP ciphers.";
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
289a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    LOG_J(LS_INFO, this) << "Not using DTLS.";
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
292a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  LOG_J(LS_INFO, this) << "DTLS setup complete.";
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2968841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.orgbool DtlsTransportChannelWrapper::SetSrtpCiphers(
2978841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    const std::vector<std::string>& ciphers) {
2988841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org  if (srtp_ciphers_ == ciphers)
2998841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    return true;
3008841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org
30152e2af0918cd38cdde42d9d77b7c32685a3e1e50buildbot@webrtc.org  if (dtls_state_ == STATE_STARTED) {
30252e2af0918cd38cdde42d9d77b7c32685a3e1e50buildbot@webrtc.org    LOG(LS_WARNING) << "Ignoring new SRTP ciphers while DTLS is negotiating";
30352e2af0918cd38cdde42d9d77b7c32685a3e1e50buildbot@webrtc.org    return true;
30452e2af0918cd38cdde42d9d77b7c32685a3e1e50buildbot@webrtc.org  }
30552e2af0918cd38cdde42d9d77b7c32685a3e1e50buildbot@webrtc.org
3068841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org  if (dtls_state_ == STATE_OPEN) {
3078841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    // We don't support DTLS renegotiation currently. If new set of srtp ciphers
3088841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    // are different than what's being used currently, we will not use it.
3098841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    // So for now, let's be happy (or sad) with a warning message.
3108841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    std::string current_srtp_cipher;
3118841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    if (!dtls_->GetDtlsSrtpCipher(&current_srtp_cipher)) {
3128841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org      LOG(LS_ERROR) << "Failed to get the current SRTP cipher for DTLS channel";
3138841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org      return false;
3148841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    }
3158841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    const std::vector<std::string>::const_iterator iter =
3168841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org        std::find(ciphers.begin(), ciphers.end(), current_srtp_cipher);
3178841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    if (iter == ciphers.end()) {
3188841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org      std::string requested_str;
3198841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org      for (size_t i = 0; i < ciphers.size(); ++i) {
3208841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org        requested_str.append(" ");
3218841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org        requested_str.append(ciphers[i]);
3228841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org        requested_str.append(" ");
3238841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org      }
3248841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org      LOG(LS_WARNING) << "Ignoring new set of SRTP ciphers, as DTLS "
3258841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org                      << "renegotiation is not supported currently "
3268841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org                      << "current cipher = " << current_srtp_cipher << " and "
3278841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org                      << "requested = " << "[" << requested_str << "]";
3288841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    }
3298841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org    return true;
3308841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org  }
3318841d7bf4010478a4b3978ff2d181d9504b2bbe3mallinath@webrtc.org
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (dtls_state_ != STATE_NONE &&
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtls_state_ != STATE_OFFERED &&
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtls_state_ != STATE_ACCEPTED) {
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  srtp_ciphers_ = ciphers;
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool DtlsTransportChannelWrapper::GetSrtpCipher(std::string* cipher) {
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (dtls_state_ != STATE_OPEN) {
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return dtls_->GetDtlsSrtpCipher(cipher);
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Called from upper layers to send a media packet.
353f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.orgint DtlsTransportChannelWrapper::SendPacket(
354f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    const char* data, size_t size,
3552a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketOptions& options, int flags) {
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int result = -1;
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (dtls_state_) {
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_OFFERED:
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // We don't know if we are doing DTLS yet, so we can't send a packet.
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // TODO(ekr@rtfm.com): assert here?
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      result = -1;
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_STARTED:
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_ACCEPTED:
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Can't send data until the connection is active
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      result = -1;
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_OPEN:
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (flags & PF_SRTP_BYPASS) {
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ASSERT(!srtp_ciphers_.empty());
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!IsRtpPacket(data, size)) {
375ac12b50104a35b42ff49d847bd4c01782d0434afjiayl@webrtc.org          result = -1;
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          break;
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
379f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org        result = channel_->SendPacket(data, size, options);
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        result = (dtls_->WriteAll(data, size, NULL, NULL) ==
3822a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org          rtc::SR_SUCCESS) ? static_cast<int>(size) : -1;
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Not doing DTLS.
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_NONE:
387f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org      result = channel_->SendPacket(data, size, options);
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_CLOSED:  // Can't send anything when we're closed.
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return -1;
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return result;
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The state transition logic here is as follows:
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// (1) If we're not doing DTLS-SRTP, then the state is just the
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     state of the underlying impl()
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// (2) If we're doing DTLS-SRTP:
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     - Prior to the DTLS handshake, the state is neither readable or
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//       writable
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     - When the impl goes writable for the first time we
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//       start the DTLS handshake
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//     - Once the DTLS handshake completes, the state is that of the
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//       impl again
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnReadableState(TransportChannel* channel) {
4082a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  ASSERT(rtc::Thread::Current() == worker_thread_);
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_J(LS_VERBOSE, this)
411a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      << "DTLSTransportChannelWrapper: channel readable state changed.";
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (dtls_state_ == STATE_NONE || dtls_state_ == STATE_OPEN) {
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    set_readable(channel_->readable());
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Note: SignalReadableState fired by set_readable.
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnWritableState(TransportChannel* channel) {
4202a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  ASSERT(rtc::Thread::Current() == worker_thread_);
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_J(LS_VERBOSE, this)
423a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      << "DTLSTransportChannelWrapper: channel writable state changed.";
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (dtls_state_) {
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_NONE:
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_OPEN:
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      set_writable(channel_->writable());
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Note: SignalWritableState fired by set_writable.
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_OFFERED:
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Do nothing
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_ACCEPTED:
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!MaybeStartDtls()) {
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // This should never happen:
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Because we are operating in a nonblocking mode and all
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // incoming packets come in via OnReadPacket(), which rejects
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // packets in this state, the incoming queue must be empty. We
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // ignore write errors, thus any errors must be because of
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // configuration and therefore are our fault.
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Note that in non-debug configurations, failure in
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // MaybeStartDtls() changes the state to STATE_CLOSED.
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ASSERT(false);
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_STARTED:
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Do nothing
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_CLOSED:
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Should not happen. Do nothing
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
460f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid DtlsTransportChannelWrapper::OnReadPacket(
461f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    TransportChannel* channel, const char* data, size_t size,
4622a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketTime& packet_time, int flags) {
4632a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  ASSERT(rtc::Thread::Current() == worker_thread_);
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(flags == 0);
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (dtls_state_) {
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_NONE:
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // We are not doing DTLS
470f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org      SignalReadPacket(this, data, size, packet_time, 0);
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_OFFERED:
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Currently drop the packet, but we might in future
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // decide to take this as evidence that the other
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // side is ready to do DTLS and start the handshake
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // on our end
478a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      LOG_J(LS_WARNING, this) << "Received packet before we know if we are "
479a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org                              << "doing DTLS or not; dropping.";
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_ACCEPTED:
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Drop packets received before DTLS has actually started
484a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      LOG_J(LS_INFO, this) << "Dropping packet received before DTLS started.";
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_STARTED:
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_OPEN:
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // We should only get DTLS or SRTP packets; STUN's already been demuxed.
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Is this potentially a DTLS packet?
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (IsDtlsPacket(data, size)) {
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!HandleDtlsPacket(data, size)) {
493a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return;
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Not a DTLS packet; our handshake should be complete by now.
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (dtls_state_ != STATE_OPEN) {
499a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          LOG_J(LS_ERROR, this) << "Received non-DTLS packet before DTLS "
500a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org                                << "complete.";
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return;
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // And it had better be a SRTP packet.
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!IsRtpPacket(data, size)) {
506a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          LOG_J(LS_ERROR, this) << "Received unexpected non-DTLS packet.";
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return;
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Sanity check.
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ASSERT(!srtp_ciphers_.empty());
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Signal this upwards as a bypass packet.
514f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org        SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case STATE_CLOSED:
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // This shouldn't be happening. Drop the packet
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnReadyToSend(TransportChannel* channel) {
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (writable()) {
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalReadyToSend(this);
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5292a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid DtlsTransportChannelWrapper::OnDtlsEvent(rtc::StreamInterface* dtls,
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                              int sig, int err) {
5312a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  ASSERT(rtc::Thread::Current() == worker_thread_);
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(dtls == dtls_.get());
5332a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (sig & rtc::SE_OPEN) {
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // This is the first time.
535a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    LOG_J(LS_INFO, this) << "DTLS handshake complete.";
5362a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (dtls_->GetState() == rtc::SS_OPEN) {
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // The check for OPEN shouldn't be necessary but let's make
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // sure we don't accidentally frob the state if it's closed.
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtls_state_ = STATE_OPEN;
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      set_readable(true);
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      set_writable(true);
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5452a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (sig & rtc::SE_READ) {
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    char buf[kMaxDtlsPacketLen];
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    size_t read;
5482a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (dtls_->Read(buf, sizeof(buf), &read, NULL) == rtc::SR_SUCCESS) {
5492a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      SignalReadPacket(this, buf, read, rtc::CreatePacketTime(0), 0);
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (sig & rtc::SE_CLOSE) {
5532a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    ASSERT(sig == rtc::SE_CLOSE);  // SE_CLOSE should be by itself.
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!err) {
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_J(LS_INFO, this) << "DTLS channel closed";
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_J(LS_INFO, this) << "DTLS channel error, code=" << err;
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    set_readable(false);
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    set_writable(false);
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    dtls_state_ = STATE_CLOSED;
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool DtlsTransportChannelWrapper::MaybeStartDtls() {
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (channel_->writable()) {
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (dtls_->StartSSLWithPeer()) {
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_J(LS_ERROR, this) << "Couldn't start DTLS handshake";
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtls_state_ = STATE_CLOSED;
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG_J(LS_INFO, this)
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      << "DtlsTransportChannelWrapper: Started DTLS handshake";
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    dtls_state_ = STATE_STARTED;
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Called from OnReadPacket when a DTLS packet is received.
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool DtlsTransportChannelWrapper::HandleDtlsPacket(const char* data,
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                   size_t size) {
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sanity check we're not passing junk that
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // just looks like DTLS.
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* tmp_data = reinterpret_cast<const uint8* >(data);
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t tmp_size = size;
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (tmp_size > 0) {
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (tmp_size < kDtlsRecordHeaderLen)
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;  // Too short for the header
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    size_t record_len = (tmp_data[11] << 8) | (tmp_data[12]);
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((record_len + kDtlsRecordHeaderLen) > tmp_size)
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;  // Body too short
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tmp_data += record_len + kDtlsRecordHeaderLen;
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tmp_size -= record_len + kDtlsRecordHeaderLen;
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Looks good. Pass to the SIC which ends up being passed to
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // the DTLS stack.
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return downward_->OnPacketReceived(data, size);
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnRequestSignaling(
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelImpl* channel) {
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalRequestSignaling(this);
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnCandidateReady(
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelImpl* channel, const Candidate& c) {
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalCandidateReady(this, c);
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnCandidatesAllocationDone(
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelImpl* channel) {
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalCandidatesAllocationDone(this);
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnRoleConflict(
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelImpl* channel) {
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalRoleConflict(this);
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid DtlsTransportChannelWrapper::OnRouteChange(
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannel* channel, const Candidate& candidate) {
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(channel == channel_);
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalRouteChange(this, candidate);
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
635f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.orgvoid DtlsTransportChannelWrapper::OnConnectionRemoved(
636f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    TransportChannelImpl* channel) {
637f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  ASSERT(channel == channel_);
638f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  SignalConnectionRemoved(this);
639f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org}
640f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
642