1/*
2 * libjingle
3 * Copyright 2011, Google Inc.
4 * Copyright 2011, RTFM, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 *  1. Redistributions of source code must retain the above copyright notice,
10 *     this list of conditions and the following disclaimer.
11 *  2. Redistributions in binary form must reproduce the above copyright notice,
12 *     this list of conditions and the following disclaimer in the documentation
13 *     and/or other materials provided with the distribution.
14 *  3. The name of the author may not be used to endorse or promote products
15 *     derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef TALK_P2P_BASE_DTLSTRANSPORTCHANNEL_H_
30#define TALK_P2P_BASE_DTLSTRANSPORTCHANNEL_H_
31
32#include <string>
33#include <vector>
34
35#include "talk/p2p/base/transportchannelimpl.h"
36#include "webrtc/base/buffer.h"
37#include "webrtc/base/scoped_ptr.h"
38#include "webrtc/base/sslstreamadapter.h"
39#include "webrtc/base/stream.h"
40
41namespace cricket {
42
43// A bridge between a packet-oriented/channel-type interface on
44// the bottom and a StreamInterface on the top.
45class StreamInterfaceChannel : public rtc::StreamInterface,
46                               public sigslot::has_slots<> {
47 public:
48  StreamInterfaceChannel(rtc::Thread* owner, TransportChannel* channel)
49      : channel_(channel),
50        state_(rtc::SS_OPEN),
51        fifo_(kFifoSize, owner) {
52    fifo_.SignalEvent.connect(this, &StreamInterfaceChannel::OnEvent);
53  }
54
55  // Push in a packet; this gets pulled out from Read().
56  bool OnPacketReceived(const char* data, size_t size);
57
58  // Implementations of StreamInterface
59  virtual rtc::StreamState GetState() const { return state_; }
60  virtual void Close() { state_ = rtc::SS_CLOSED; }
61  virtual rtc::StreamResult Read(void* buffer, size_t buffer_len,
62                                       size_t* read, int* error);
63  virtual rtc::StreamResult Write(const void* data, size_t data_len,
64                                        size_t* written, int* error);
65
66 private:
67  static const size_t kFifoSize = 8192;
68
69  // Forward events
70  virtual void OnEvent(rtc::StreamInterface* stream, int sig, int err);
71
72  TransportChannel* channel_;  // owned by DtlsTransportChannelWrapper
73  rtc::StreamState state_;
74  rtc::FifoBuffer fifo_;
75
76  DISALLOW_COPY_AND_ASSIGN(StreamInterfaceChannel);
77};
78
79
80// This class provides a DTLS SSLStreamAdapter inside a TransportChannel-style
81// packet-based interface, wrapping an existing TransportChannel instance
82// (e.g a P2PTransportChannel)
83// Here's the way this works:
84//
85//   DtlsTransportChannelWrapper {
86//       SSLStreamAdapter* dtls_ {
87//           StreamInterfaceChannel downward_ {
88//               TransportChannelImpl* channel_;
89//           }
90//       }
91//   }
92//
93//   - Data which comes into DtlsTransportChannelWrapper from the underlying
94//     channel_ via OnReadPacket() is checked for whether it is DTLS
95//     or not, and if it is, is passed to DtlsTransportChannelWrapper::
96//     HandleDtlsPacket, which pushes it into to downward_.
97//     dtls_ is listening for events on downward_, so it immediately calls
98//     downward_->Read().
99//
100//   - Data written to DtlsTransportChannelWrapper is passed either to
101//      downward_ or directly to channel_, depending on whether DTLS is
102//     negotiated and whether the flags include PF_SRTP_BYPASS
103//
104//   - The SSLStreamAdapter writes to downward_->Write()
105//     which translates it into packet writes on channel_.
106class DtlsTransportChannelWrapper : public TransportChannelImpl {
107 public:
108    enum State {
109      STATE_NONE,      // No state or rejected.
110      STATE_OFFERED,   // Our identity has been set.
111      STATE_ACCEPTED,  // The other side sent a fingerprint.
112      STATE_STARTED,   // We are negotiating.
113      STATE_OPEN,      // Negotiation complete.
114      STATE_CLOSED     // Connection closed.
115    };
116
117  // The parameters here are:
118  // transport -- the DtlsTransport that created us
119  // channel -- the TransportChannel we are wrapping
120  DtlsTransportChannelWrapper(Transport* transport,
121                              TransportChannelImpl* channel);
122  virtual ~DtlsTransportChannelWrapper();
123
124  virtual void SetIceRole(IceRole role) {
125    channel_->SetIceRole(role);
126  }
127  virtual IceRole GetIceRole() const {
128    return channel_->GetIceRole();
129  }
130  virtual size_t GetConnectionCount() const {
131    return channel_->GetConnectionCount();
132  }
133  virtual bool SetLocalIdentity(rtc::SSLIdentity *identity);
134  virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const;
135
136  virtual bool SetRemoteFingerprint(const std::string& digest_alg,
137                                    const uint8* digest,
138                                    size_t digest_len);
139  virtual bool IsDtlsActive() const { return dtls_state_ != STATE_NONE; }
140
141  // Called to send a packet (via DTLS, if turned on).
142  virtual int SendPacket(const char* data, size_t size,
143                         const rtc::PacketOptions& options,
144                         int flags);
145
146  // TransportChannel calls that we forward to the wrapped transport.
147  virtual int SetOption(rtc::Socket::Option opt, int value) {
148    return channel_->SetOption(opt, value);
149  }
150  virtual int GetError() {
151    return channel_->GetError();
152  }
153  virtual bool GetStats(ConnectionInfos* infos) {
154    return channel_->GetStats(infos);
155  }
156  virtual const std::string SessionId() const {
157    return channel_->SessionId();
158  }
159
160  // Set up the ciphers to use for DTLS-SRTP. If this method is not called
161  // before DTLS starts, or |ciphers| is empty, SRTP keys won't be negotiated.
162  // This method should be called before SetupDtls.
163  virtual bool SetSrtpCiphers(const std::vector<std::string>& ciphers);
164
165  // Find out which DTLS-SRTP cipher was negotiated
166  virtual bool GetSrtpCipher(std::string* cipher);
167
168  virtual bool GetSslRole(rtc::SSLRole* role) const;
169  virtual bool SetSslRole(rtc::SSLRole role);
170
171  // Once DTLS has been established, this method retrieves the certificate in
172  // use by the remote peer, for use in external identity verification.
173  virtual bool GetRemoteCertificate(rtc::SSLCertificate** cert) const;
174
175  // Once DTLS has established (i.e., this channel is writable), this method
176  // extracts the keys negotiated during the DTLS handshake, for use in external
177  // encryption. DTLS-SRTP uses this to extract the needed SRTP keys.
178  // See the SSLStreamAdapter documentation for info on the specific parameters.
179  virtual bool ExportKeyingMaterial(const std::string& label,
180                                    const uint8* context,
181                                    size_t context_len,
182                                    bool use_context,
183                                    uint8* result,
184                                    size_t result_len) {
185    return (dtls_.get()) ? dtls_->ExportKeyingMaterial(label, context,
186                                                       context_len,
187                                                       use_context,
188                                                       result, result_len)
189        : false;
190  }
191
192  // TransportChannelImpl calls.
193  virtual Transport* GetTransport() {
194    return transport_;
195  }
196  virtual void SetIceTiebreaker(uint64 tiebreaker) {
197    channel_->SetIceTiebreaker(tiebreaker);
198  }
199  virtual bool GetIceProtocolType(IceProtocolType* type) const {
200    return channel_->GetIceProtocolType(type);
201  }
202  virtual void SetIceProtocolType(IceProtocolType type) {
203    channel_->SetIceProtocolType(type);
204  }
205  virtual void SetIceCredentials(const std::string& ice_ufrag,
206                                 const std::string& ice_pwd) {
207    channel_->SetIceCredentials(ice_ufrag, ice_pwd);
208  }
209  virtual void SetRemoteIceCredentials(const std::string& ice_ufrag,
210                                       const std::string& ice_pwd) {
211    channel_->SetRemoteIceCredentials(ice_ufrag, ice_pwd);
212  }
213  virtual void SetRemoteIceMode(IceMode mode) {
214    channel_->SetRemoteIceMode(mode);
215  }
216
217  virtual void Connect();
218  virtual void Reset();
219
220  virtual void OnSignalingReady() {
221    channel_->OnSignalingReady();
222  }
223  virtual void OnCandidate(const Candidate& candidate) {
224    channel_->OnCandidate(candidate);
225  }
226
227  // Needed by DtlsTransport.
228  TransportChannelImpl* channel() { return channel_; }
229
230 private:
231  void OnReadableState(TransportChannel* channel);
232  void OnWritableState(TransportChannel* channel);
233  void OnReadPacket(TransportChannel* channel, const char* data, size_t size,
234                    const rtc::PacketTime& packet_time, int flags);
235  void OnReadyToSend(TransportChannel* channel);
236  void OnDtlsEvent(rtc::StreamInterface* stream_, int sig, int err);
237  bool SetupDtls();
238  bool MaybeStartDtls();
239  bool HandleDtlsPacket(const char* data, size_t size);
240  void OnRequestSignaling(TransportChannelImpl* channel);
241  void OnCandidateReady(TransportChannelImpl* channel, const Candidate& c);
242  void OnCandidatesAllocationDone(TransportChannelImpl* channel);
243  void OnRoleConflict(TransportChannelImpl* channel);
244  void OnRouteChange(TransportChannel* channel, const Candidate& candidate);
245  void OnConnectionRemoved(TransportChannelImpl* channel);
246
247  Transport* transport_;  // The transport_ that created us.
248  rtc::Thread* worker_thread_;  // Everything should occur on this thread.
249  TransportChannelImpl* channel_;  // Underlying channel, owned by transport_.
250  rtc::scoped_ptr<rtc::SSLStreamAdapter> dtls_;  // The DTLS stream
251  StreamInterfaceChannel* downward_;  // Wrapper for channel_, owned by dtls_.
252  std::vector<std::string> srtp_ciphers_;  // SRTP ciphers to use with DTLS.
253  State dtls_state_;
254  rtc::SSLIdentity* local_identity_;
255  rtc::SSLRole ssl_role_;
256  rtc::Buffer remote_fingerprint_value_;
257  std::string remote_fingerprint_algorithm_;
258
259  DISALLOW_COPY_AND_ASSIGN(DtlsTransportChannelWrapper);
260};
261
262}  // namespace cricket
263
264#endif  // TALK_P2P_BASE_DTLSTRANSPORTCHANNEL_H_
265