1/*
2 * libjingle
3 * Copyright 2013 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_
29#define TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_
30
31#include "talk/app/webrtc/dtlsidentitystore.h"
32#include "talk/app/webrtc/peerconnectioninterface.h"
33#include "talk/session/media/mediasession.h"
34#include "webrtc/p2p/base/transportdescriptionfactory.h"
35#include "webrtc/base/messagehandler.h"
36#include "webrtc/base/rtccertificate.h"
37
38namespace cricket {
39class ChannelManager;
40class TransportDescriptionFactory;
41}  // namespace cricket
42
43namespace webrtc {
44class CreateSessionDescriptionObserver;
45class MediaConstraintsInterface;
46class SessionDescriptionInterface;
47class WebRtcSession;
48
49// DTLS identity request callback class.
50class WebRtcIdentityRequestObserver : public DtlsIdentityRequestObserver,
51                                      public sigslot::has_slots<> {
52 public:
53  // DtlsIdentityRequestObserver overrides.
54  void OnFailure(int error) override;
55  void OnSuccess(const std::string& der_cert,
56                 const std::string& der_private_key) override;
57  void OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity> identity) override;
58
59  sigslot::signal1<int> SignalRequestFailed;
60  sigslot::signal1<const rtc::scoped_refptr<rtc::RTCCertificate>&>
61      SignalCertificateReady;
62};
63
64struct CreateSessionDescriptionRequest {
65  enum Type {
66    kOffer,
67    kAnswer,
68  };
69
70  CreateSessionDescriptionRequest(
71      Type type,
72      CreateSessionDescriptionObserver* observer,
73      const cricket::MediaSessionOptions& options)
74      : type(type),
75        observer(observer),
76        options(options) {}
77
78  Type type;
79  rtc::scoped_refptr<CreateSessionDescriptionObserver> observer;
80  cricket::MediaSessionOptions options;
81};
82
83// This class is used to create offer/answer session description with regards to
84// the async DTLS identity generation for WebRtcSession.
85// It queues the create offer/answer request until the DTLS identity
86// request has completed, i.e. when OnIdentityRequestFailed or OnIdentityReady
87// is called.
88class WebRtcSessionDescriptionFactory : public rtc::MessageHandler,
89                                        public sigslot::has_slots<> {
90 public:
91  // Construct with DTLS disabled.
92  WebRtcSessionDescriptionFactory(rtc::Thread* signaling_thread,
93                                  cricket::ChannelManager* channel_manager,
94                                  WebRtcSession* session,
95                                  const std::string& session_id);
96
97  // Construct with DTLS enabled using the specified |dtls_identity_store| to
98  // generate a certificate.
99  WebRtcSessionDescriptionFactory(
100      rtc::Thread* signaling_thread,
101      cricket::ChannelManager* channel_manager,
102      rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
103      WebRtcSession* session,
104      const std::string& session_id);
105
106  // Construct with DTLS enabled using the specified (already generated)
107  // |certificate|.
108  WebRtcSessionDescriptionFactory(
109      rtc::Thread* signaling_thread,
110      cricket::ChannelManager* channel_manager,
111      const rtc::scoped_refptr<rtc::RTCCertificate>& certificate,
112      WebRtcSession* session,
113      const std::string& session_id);
114  virtual ~WebRtcSessionDescriptionFactory();
115
116  static void CopyCandidatesFromSessionDescription(
117    const SessionDescriptionInterface* source_desc,
118    SessionDescriptionInterface* dest_desc);
119
120  void CreateOffer(
121      CreateSessionDescriptionObserver* observer,
122      const PeerConnectionInterface::RTCOfferAnswerOptions& options,
123      const cricket::MediaSessionOptions& session_options);
124  void CreateAnswer(CreateSessionDescriptionObserver* observer,
125                    const MediaConstraintsInterface* constraints,
126                    const cricket::MediaSessionOptions& session_options);
127
128  void SetSdesPolicy(cricket::SecurePolicy secure_policy);
129  cricket::SecurePolicy SdesPolicy() const;
130
131  sigslot::signal1<const rtc::scoped_refptr<rtc::RTCCertificate>&>
132      SignalCertificateReady;
133
134  // For testing.
135  bool waiting_for_certificate_for_testing() const {
136    return certificate_request_state_ == CERTIFICATE_WAITING;
137  }
138
139 private:
140  enum CertificateRequestState {
141    CERTIFICATE_NOT_NEEDED,
142    CERTIFICATE_WAITING,
143    CERTIFICATE_SUCCEEDED,
144    CERTIFICATE_FAILED,
145  };
146
147  WebRtcSessionDescriptionFactory(
148      rtc::Thread* signaling_thread,
149      cricket::ChannelManager* channel_manager,
150      rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
151      const rtc::scoped_refptr<WebRtcIdentityRequestObserver>&
152          identity_request_observer,
153      WebRtcSession* session,
154      const std::string& session_id,
155      bool dtls_enabled);
156
157  // MessageHandler implementation.
158  virtual void OnMessage(rtc::Message* msg);
159
160  void InternalCreateOffer(CreateSessionDescriptionRequest request);
161  void InternalCreateAnswer(CreateSessionDescriptionRequest request);
162  // Posts failure notifications for all pending session description requests.
163  void FailPendingRequests(const std::string& reason);
164  void PostCreateSessionDescriptionFailed(
165      CreateSessionDescriptionObserver* observer,
166      const std::string& error);
167  void PostCreateSessionDescriptionSucceeded(
168      CreateSessionDescriptionObserver* observer,
169      SessionDescriptionInterface* description);
170
171  void OnIdentityRequestFailed(int error);
172  void SetCertificate(
173      const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
174
175  std::queue<CreateSessionDescriptionRequest>
176      create_session_description_requests_;
177  rtc::Thread* const signaling_thread_;
178  cricket::TransportDescriptionFactory transport_desc_factory_;
179  cricket::MediaSessionDescriptionFactory session_desc_factory_;
180  uint64_t session_version_;
181  const rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store_;
182  const rtc::scoped_refptr<WebRtcIdentityRequestObserver>
183      identity_request_observer_;
184  // TODO(jiayl): remove the dependency on session once bug 2264 is fixed.
185  WebRtcSession* const session_;
186  const std::string session_id_;
187  CertificateRequestState certificate_request_state_;
188
189  RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSessionDescriptionFactory);
190};
191}  // namespace webrtc
192
193#endif  // TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_
194