15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2012, Google, Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifndef TALK_P2P_BASE_DTLSTRANSPORT_H_
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define TALK_P2P_BASE_DTLSTRANSPORT_H_
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/dtlstransportchannel.h"
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/transport.h"
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base {
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass SSLIdentity;
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace cricket {
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PortAllocator;
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Base should be a descendant of cricket::Transport
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtemplate<class Base>
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass DtlsTransport : public Base {
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public:
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DtlsTransport(talk_base::Thread* signaling_thread,
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                talk_base::Thread* worker_thread,
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                const std::string& content_name,
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                PortAllocator* allocator,
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                talk_base::SSLIdentity* identity)
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      : Base(signaling_thread, worker_thread, content_name, allocator),
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        identity_(identity) {
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ~DtlsTransport() {
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Base::DestroyAllChannels();
577bf94f9c4ab08aa82f78018d8ba363b5b60b05edwu@webrtc.org  }
587bf94f9c4ab08aa82f78018d8ba363b5b60b05edwu@webrtc.org  virtual void SetIdentity_w(talk_base::SSLIdentity* identity) {
597bf94f9c4ab08aa82f78018d8ba363b5b60b05edwu@webrtc.org    identity_ = identity;
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6159a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org  virtual bool GetIdentity_w(talk_base::SSLIdentity** identity) {
6259a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org    if (!identity_)
6359a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org      return false;
6459a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org
6559a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org    *identity = identity_->GetReference();
6659a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org    return true;
6759a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org  }
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl*
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                channel) {
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::SSLFingerprint* local_fp =
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        Base::local_description()->identity_fingerprint.get();
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (local_fp) {
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Sanity check local fingerprint.
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (identity_) {
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        talk_base::scoped_ptr<talk_base::SSLFingerprint> local_fp_tmp(
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            talk_base::SSLFingerprint::Create(local_fp->algorithm,
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                              identity_));
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ASSERT(local_fp_tmp.get() != NULL);
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        if (!(*local_fp_tmp == *local_fp)) {
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          LOG(LS_WARNING) << "Local fingerprint does not match identity";
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          return false;
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        }
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else {
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(LS_WARNING)
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            << "Local fingerprint provided but no identity available";
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        return false;
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      identity_ = NULL;
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!channel->SetLocalIdentity(identity_))
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Apply the description in the base class.
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return Base::ApplyLocalTransportDescription_w(channel);
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  virtual bool NegotiateTransportDescription_w(ContentAction local_role) {
102c7b37163b72221c0fdee4817c208b1e5be01ac05sergeyu@chromium.org    if (!Base::local_description() || !Base::remote_description()) {
103c7b37163b72221c0fdee4817c208b1e5be01ac05sergeyu@chromium.org      LOG(LS_INFO) << "Local and Remote description must be set before "
104c7b37163b72221c0fdee4817c208b1e5be01ac05sergeyu@chromium.org                   << "transport descriptions are negotiated";
105c7b37163b72221c0fdee4817c208b1e5be01ac05sergeyu@chromium.org      return false;
106c7b37163b72221c0fdee4817c208b1e5be01ac05sergeyu@chromium.org    }
107c7b37163b72221c0fdee4817c208b1e5be01ac05sergeyu@chromium.org
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::SSLFingerprint* local_fp =
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        Base::local_description()->identity_fingerprint.get();
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::SSLFingerprint* remote_fp =
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        Base::remote_description()->identity_fingerprint.get();
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (remote_fp && local_fp) {
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      remote_fingerprint_.reset(new talk_base::SSLFingerprint(*remote_fp));
115b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
116b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // From RFC 4145, section-4.1, The following are the values that the
117b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // 'setup' attribute can take in an offer/answer exchange:
118b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //       Offer      Answer
119b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //      ________________
120b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //      active     passive / holdconn
121b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //      passive    active / holdconn
122b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //      actpass    active / passive / holdconn
123b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //      holdconn   holdconn
124b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      //
125b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
126b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // The endpoint MUST use the setup attribute defined in [RFC4145].
127b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // The endpoint that is the offerer MUST use the setup attribute
128b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // value of setup:actpass and be prepared to receive a client_hello
129b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // before it receives the answer.  The answerer MUST use either a
130b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // setup attribute value of setup:active or setup:passive.  Note that
131b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // if the answerer uses setup:passive, then the DTLS handshake will
132b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // not begin until the answerer is received, which adds additional
133b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // latency. setup:active allows the answer and the DTLS handshake to
134b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // occur in parallel.  Thus, setup:active is RECOMMENDED.  Whichever
135b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // party is active MUST initiate a DTLS handshake by sending a
136b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // ClientHello over each flow (host/port quartet).
137b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // IOW - actpass and passive modes should be treated as server and
138b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      // active as client.
139b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      ConnectionRole local_connection_role =
140b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          Base::local_description()->connection_role;
141b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      ConnectionRole remote_connection_role =
142b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          Base::remote_description()->connection_role;
143b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
144b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      bool is_remote_server = false;
145b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      if (local_role == CA_OFFER) {
146b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        if (local_connection_role != CONNECTIONROLE_ACTPASS) {
147b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          LOG(LS_ERROR) << "Offerer must use actpass value for setup attribute";
148b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          return false;
149b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        }
150b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
151b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
152b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org            remote_connection_role == CONNECTIONROLE_PASSIVE ||
153b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org            remote_connection_role == CONNECTIONROLE_NONE) {
154b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
155b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        } else {
156b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          LOG(LS_ERROR) << "Answerer must use either active or passive value "
157b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org                        << "for setup attribute";
158b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          return false;
159b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        }
160b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        // If remote is NONE or ACTIVE it will act as client.
161b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      } else {
162b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
163b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org            remote_connection_role != CONNECTIONROLE_NONE) {
164b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          LOG(LS_ERROR) << "Offerer must use actpass value for setup attribute";
165b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          return false;
166b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        }
167b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
168b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        if (local_connection_role == CONNECTIONROLE_ACTIVE ||
169b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org            local_connection_role == CONNECTIONROLE_PASSIVE) {
170b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
171b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        } else {
172b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          LOG(LS_ERROR) << "Answerer must use either active or passive value "
173b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org                        << "for setup attribute";
174b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org          return false;
175b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        }
176b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
177b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        // If local is passive, local will act as server.
178b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      }
179b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
180b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      secure_role_ = is_remote_server ? talk_base::SSL_CLIENT :
181b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org                                        talk_base::SSL_SERVER;
182b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else if (local_fp && (local_role == CA_ANSWER)) {
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR)
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          << "Local fingerprint supplied when caller didn't offer DTLS";
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // We are not doing DTLS
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      remote_fingerprint_.reset(new talk_base::SSLFingerprint(
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          "", NULL, 0));
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Now run the negotiation for the base class.
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return Base::NegotiateTransportDescription_w(local_role);
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  virtual DtlsTransportChannelWrapper* CreateTransportChannel(int component) {
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return new DtlsTransportChannelWrapper(
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        this, Base::CreateTransportChannel(component));
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  virtual void DestroyTransportChannel(TransportChannelImpl* channel) {
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Kind of ugly, but this lets us do the exact inverse of the create.
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    DtlsTransportChannelWrapper* dtls_channel =
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<DtlsTransportChannelWrapper*>(channel);
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    TransportChannelImpl* base_channel = dtls_channel->channel();
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete dtls_channel;
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Base::DestroyTransportChannel(base_channel);
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
211b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org  virtual bool GetSslRole_w(talk_base::SSLRole* ssl_role) const {
212b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    ASSERT(ssl_role != NULL);
213b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    *ssl_role = secure_role_;
214b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    return true;
215b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org  }
216b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private:
218b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org  virtual bool ApplyNegotiatedTransportDescription_w(
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      TransportChannelImpl* channel) {
220b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    // Set ssl role. Role must be set before fingerprint is applied, which
221b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    // initiates DTLS setup.
222b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    if (!channel->SetSslRole(secure_role_)) {
223b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      LOG(LS_INFO) << "Failed to set ssl role for the channel.";
224b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      return false;
225b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    }
226b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    // Apply remote fingerprint.
227b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    if (!channel->SetRemoteFingerprint(
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        remote_fingerprint_->algorithm,
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        reinterpret_cast<const uint8 *>(remote_fingerprint_->
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    digest.data()),
231b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org        remote_fingerprint_->digest.length())) {
232b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org      return false;
233b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    }
234b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org    return Base::ApplyNegotiatedTransportDescription_w(channel);
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::SSLIdentity* identity_;
238b17e4d000599d5caf286d9599cc5244410e1f313sergeyu@chromium.org  talk_base::SSLRole secure_role_;
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_ptr<talk_base::SSLFingerprint> remote_fingerprint_;
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace cricket
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif  // TALK_P2P_BASE_DTLSTRANSPORT_H_
245