10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2012, Google, Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifndef TALK_P2P_BASE_DTLSTRANSPORT_H_
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define TALK_P2P_BASE_DTLSTRANSPORT_H_
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/dtlstransportchannel.h"
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/transport.h"
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgnamespace rtc {
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass SSLIdentity;
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass PortAllocator;
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Base should be a descendant of cricket::Transport
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate<class Base>
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass DtlsTransport : public Base {
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public:
462a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  DtlsTransport(rtc::Thread* signaling_thread,
472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                rtc::Thread* worker_thread,
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                const std::string& content_name,
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                PortAllocator* allocator,
502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                rtc::SSLIdentity* identity)
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      : Base(signaling_thread, worker_thread, content_name, allocator),
523e32030ec396a850c18e817b611f092fdd08e102jiayl@webrtc.org        identity_(identity),
532a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        secure_role_(rtc::SSL_CLIENT) {
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~DtlsTransport() {
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Base::DestroyAllChannels();
585aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org  }
592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  virtual void SetIdentity_w(rtc::SSLIdentity* identity) {
605aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org    identity_ = identity;
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
622a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  virtual bool GetIdentity_w(rtc::SSLIdentity** identity) {
6362fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    if (!identity_)
6462fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org      return false;
6562fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org
6662fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    *identity = identity_->GetReference();
6762fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org    return true;
6862fe97f10a7a3200c9724851f6a18537ed270cddwu@webrtc.org  }
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
70f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* channel,
71f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                                std::string* error_desc) {
722a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SSLFingerprint* local_fp =
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        Base::local_description()->identity_fingerprint.get();
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (local_fp) {
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Sanity check local fingerprint.
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (identity_) {
782a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        rtc::scoped_ptr<rtc::SSLFingerprint> local_fp_tmp(
792a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org            rtc::SSLFingerprint::Create(local_fp->algorithm,
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                              identity_));
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ASSERT(local_fp_tmp.get() != NULL);
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!(*local_fp_tmp == *local_fp)) {
83f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          std::ostringstream desc;
84f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          desc << "Local fingerprint does not match identity. Expected: ";
85f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          desc << local_fp_tmp->ToString();
86f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          desc << " Got: " << local_fp->ToString();
87f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          return BadTransportDescription(desc.str(), error_desc);
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
90f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org        return BadTransportDescription(
91f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org            "Local fingerprint provided but no identity available.",
92f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org            error_desc);
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      identity_ = NULL;
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
98f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    if (!channel->SetLocalIdentity(identity_)) {
99f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      return BadTransportDescription("Failed to set local identity.",
100f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                     error_desc);
101f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    }
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Apply the description in the base class.
104f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    return Base::ApplyLocalTransportDescription_w(channel, error_desc);
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
107f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org  virtual bool NegotiateTransportDescription_w(ContentAction local_role,
108f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                               std::string* error_desc) {
109818ab78dd700fc7ed846f781326db971caa6495fmallinath@webrtc.org    if (!Base::local_description() || !Base::remote_description()) {
110f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      const std::string msg = "Local and Remote description must be set before "
111f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                              "transport descriptions are negotiated";
112f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      return BadTransportDescription(msg, error_desc);
113818ab78dd700fc7ed846f781326db971caa6495fmallinath@webrtc.org    }
114818ab78dd700fc7ed846f781326db971caa6495fmallinath@webrtc.org
1152a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SSLFingerprint* local_fp =
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        Base::local_description()->identity_fingerprint.get();
1172a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SSLFingerprint* remote_fp =
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        Base::remote_description()->identity_fingerprint.get();
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (remote_fp && local_fp) {
1212a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp));
122a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
123a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // From RFC 4145, section-4.1, The following are the values that the
124a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // 'setup' attribute can take in an offer/answer exchange:
125a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //       Offer      Answer
126a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //      ________________
127a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //      active     passive / holdconn
128a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //      passive    active / holdconn
129a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //      actpass    active / passive / holdconn
130a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //      holdconn   holdconn
131a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      //
132a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // Set the role that is most conformant with RFC 5763, Section 5, bullet 1
133a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // The endpoint MUST use the setup attribute defined in [RFC4145].
134a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // The endpoint that is the offerer MUST use the setup attribute
135a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // value of setup:actpass and be prepared to receive a client_hello
136a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // before it receives the answer.  The answerer MUST use either a
137a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // setup attribute value of setup:active or setup:passive.  Note that
138a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // if the answerer uses setup:passive, then the DTLS handshake will
139a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // not begin until the answerer is received, which adds additional
140a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // latency. setup:active allows the answer and the DTLS handshake to
141a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // occur in parallel.  Thus, setup:active is RECOMMENDED.  Whichever
142a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // party is active MUST initiate a DTLS handshake by sending a
143a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // ClientHello over each flow (host/port quartet).
144a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // IOW - actpass and passive modes should be treated as server and
145a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      // active as client.
146a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      ConnectionRole local_connection_role =
147a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          Base::local_description()->connection_role;
148a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      ConnectionRole remote_connection_role =
149a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          Base::remote_description()->connection_role;
150a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
151a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      bool is_remote_server = false;
152a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      if (local_role == CA_OFFER) {
153a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        if (local_connection_role != CONNECTIONROLE_ACTPASS) {
154f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          return BadTransportDescription(
155f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              "Offerer must use actpass value for setup attribute.",
156f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              error_desc);
157a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        }
158a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
159a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
160a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org            remote_connection_role == CONNECTIONROLE_PASSIVE ||
161a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org            remote_connection_role == CONNECTIONROLE_NONE) {
162a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
163a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        } else {
164f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          const std::string msg =
165f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              "Answerer must use either active or passive value "
166f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              "for setup attribute.";
167f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          return BadTransportDescription(msg, error_desc);
168a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        }
169a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        // If remote is NONE or ACTIVE it will act as client.
170a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      } else {
171a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
172a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org            remote_connection_role != CONNECTIONROLE_NONE) {
173f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          return BadTransportDescription(
174f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              "Offerer must use actpass value for setup attribute.",
175f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              error_desc);
176a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        }
177a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
178a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        if (local_connection_role == CONNECTIONROLE_ACTIVE ||
179a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org            local_connection_role == CONNECTIONROLE_PASSIVE) {
180a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org          is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
181a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        } else {
182f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          const std::string msg =
183f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              "Answerer must use either active or passive value "
184f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org              "for setup attribute.";
185f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          return BadTransportDescription(msg, error_desc);
186a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        }
187a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
188a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        // If local is passive, local will act as server.
189a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      }
190a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
1912a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      secure_role_ = is_remote_server ? rtc::SSL_CLIENT :
1922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                                        rtc::SSL_SERVER;
193a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (local_fp && (local_role == CA_ANSWER)) {
195f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      return BadTransportDescription(
196f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          "Local fingerprint supplied when caller didn't offer DTLS.",
197f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org          error_desc);
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // We are not doing DTLS
2002a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      remote_fingerprint_.reset(new rtc::SSLFingerprint(
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          "", NULL, 0));
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Now run the negotiation for the base class.
205f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    return Base::NegotiateTransportDescription_w(local_role, error_desc);
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual DtlsTransportChannelWrapper* CreateTransportChannel(int component) {
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return new DtlsTransportChannelWrapper(
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, Base::CreateTransportChannel(component));
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual void DestroyTransportChannel(TransportChannelImpl* channel) {
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Kind of ugly, but this lets us do the exact inverse of the create.
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    DtlsTransportChannelWrapper* dtls_channel =
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        static_cast<DtlsTransportChannelWrapper*>(channel);
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportChannelImpl* base_channel = dtls_channel->channel();
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete dtls_channel;
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Base::DestroyTransportChannel(base_channel);
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2222a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  virtual bool GetSslRole_w(rtc::SSLRole* ssl_role) const {
223a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    ASSERT(ssl_role != NULL);
224a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    *ssl_role = secure_role_;
225a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    return true;
226a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  }
227a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private:
229a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  virtual bool ApplyNegotiatedTransportDescription_w(
230f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      TransportChannelImpl* channel,
231f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      std::string* error_desc) {
232a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    // Set ssl role. Role must be set before fingerprint is applied, which
233a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    // initiates DTLS setup.
234a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    if (!channel->SetSslRole(secure_role_)) {
235f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      return BadTransportDescription("Failed to set ssl role for the channel.",
236f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                     error_desc);
237a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    }
238a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    // Apply remote fingerprint.
239a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    if (!channel->SetRemoteFingerprint(
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        remote_fingerprint_->algorithm,
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        reinterpret_cast<const uint8 *>(remote_fingerprint_->
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                    digest.data()),
243a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        remote_fingerprint_->digest.length())) {
244f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org      return BadTransportDescription("Failed to apply remote fingerprint.",
245f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org                                     error_desc);
246a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org    }
247f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org    return Base::ApplyNegotiatedTransportDescription_w(channel, error_desc);
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::SSLIdentity* identity_;
2512a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::SSLRole secure_role_;
2522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::scoped_ptr<rtc::SSLFingerprint> remote_fingerprint_;
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // TALK_P2P_BASE_DTLSTRANSPORT_H_
258