1 /*
2  * libjingle
3  * Copyright 2011, 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 // This file contains classes used for handling signaling between
29 // two PeerConnections.
30 
31 #ifndef TALK_APP_WEBRTC_ROAPSIGNALING_H_
32 #define TALK_APP_WEBRTC_ROAPSIGNALING_H_
33 
34 #include <string>
35 
36 #include "talk/app/webrtc/jsep.h"
37 #include "talk/app/webrtc/roaperrorcodes.h"
38 #include "talk/app/webrtc/roapsession.h"
39 #include "talk/base/scoped_ptr.h"
40 #include "talk/base/scoped_ref_ptr.h"
41 #include "talk/base/sigslot.h"
42 
43 namespace cricket {
44 class ChannelManager;
45 class Candidate;
46 typedef std::vector<Candidate> Candidates;
47 }
48 
49 namespace talk_base {
50 class Thread;
51 }
52 
53 namespace webrtc {
54 class MediaStreamSignaling;
55 class StreamCollection;
56 class StreamCollectionInterface;
57 class MediaStreamInterface;
58 
59 // RoapSignaling is a class responsible for handling signaling
60 // between two PeerConnection objects.
61 //
62 // RoapSignaling is Thread-compatible and all non-const methods are
63 // expected to be called on the signaling thread.
64 //
65 // Note that before RoapSignaling can process an answer or create an
66 // offer OnIceComplete has to be called. The last request to create an offer
67 // or process an answer will be processed after OnIceComplete has been
68 // called.
69 //
70 // Call CreateOffer to negotiate new local streams to send.
71 // Call ProcessSignalingMessage when a new message has been received from the
72 // remote peer. This might result in one or more signals being triggered to
73 // indicate changes in the offer from the the remote peer or a detected error.
74 // RoapSignaling creates Offers and Answers asynchronous on the
75 // signaling thread.
76 //
77 // Example usage: Creating an offer with one audio track.
78 //
79 // class ProviderImpl : public JsepInterface {
80 //  ...
81 // };
82 //
83 // void OnSignalingMessage(const std::string& smessage) { ... }
84 //
85 // ProviderImpl impl;
86 // RoapSignaling pc(talk_base::Thread::Current(), &impl);
87 //
88 // // Connect the function OnSignalingMessage to the signal
89 // // SignalNewPeerConnectionMessage.
90 // pc.SignalNewPeerConnectionMessage.connect(&OnSignalingMessage);
91 //
92 // // Initialize RoapSignaling by providing the candidates for
93 // // this session.
94 // pc.OnCandidatesReady(candidates);
95 // // Create an offer with one stream with one audio track.
96 // AudioTrack audio;
97 // MediaStream local_stream1;
98 // local_stream1.AddTrack(&audio);
99 // StreamCollection local_streams;
100 // local_streams.AddStream(&local_stream1)
101 // pc.CreateOffer(&local_streams);
102 // // When the offer has been created, OnsignalingMessage is called
103 // // with the offer in a string. Provide this offer to the remote
104 // // PeerConnection. The remote PeerConnection will then respond with an answer
105 // // string. Provide this answer string to RoapSignaling.
106 // pc.ProcessSignalingMessage(remote_message, &local_streams);
107 
108 class RoapSignaling : public IceCandidateObserver {
109  public:
110   enum State {
111     // RoapSignaling is new. Ice has not started.
112     kNew,
113     // Ice has started. Awaiting the local candidates.
114     kInitializing,
115     // Ready to sent new offer or receive a new offer.
116     kIdle,
117     // An offer has been sent and expect an answer.
118     kWaitingForAnswer,
119     // An answer has been sent and expect an ok message.
120     kWaitingForOK,
121     // SendShutdown has been called. No more messages are processed.
122     kShutingDown,
123     // Shutdown message has been received or the remote peer has answered ok
124     // to a sent shutdown message.
125     kShutdownComplete,
126   };
127 
128   // Constructs a RoapSignaling instance.
129   // provider - Implementation of the JsepInterface interface.
130   RoapSignaling(MediaStreamSignaling* mediastream_signaling_,
131                 JsepInterface* provider);
132   virtual ~RoapSignaling();
133 
134   // Process a received offer/answer from the remote peer.
135   // local_streams must be the collection of streams the peerconnection
136   // currently would like to send.
137   void ProcessSignalingMessage(const std::string& message,
138                                StreamCollectionInterface* local_streams);
139 
140   // Creates an offer containing all tracks in local_streams.
141   // When the offer is ready it is signaled by SignalNewPeerConnectionMessage.
142   // When the remote peer is ready to receive media on a stream , the state of
143   // the local streams will change to kLive.
144   void CreateOffer(StreamCollectionInterface* local_streams);
145 
146   // Creates a ShutDown message to be sent to the remote peer.
147   // When the message is ready it is signaled by SignalNewPeerConnectionMessage.
148   // After calling this no more offers or answers to offers can be created.
149   void SendShutDown();
150 
151   // Implements IceCandidateObserver interface.
152   // OnIceComplete is called when all local candidates have been collected.
153   // This tell RoapSignaling that it is ready to respond to offers
154   // or create offer messages.
155   virtual void OnIceComplete();
156 
157   // Implements IceCandidateObserver interface.
158   // OnIceCandidate is called when a local candidate has been collected.
159   virtual void OnIceCandidate(const IceCandidateInterface* candidate);
160 
161   // Returns the current state.
GetState()162   State GetState() const { return state_; }
163 
164   // A new ROAP message is ready to be sent. The listener to this signal is
165   // supposed to deliver this message to the remote peer.
166   sigslot::signal1<const std::string&> SignalNewPeerConnectionMessage;
167 
168   // The signaling state has changed.
169   sigslot::signal1<State> SignalStateChange;
170 
171   // Remote PeerConnection sent an error message.
172   sigslot::signal1<RoapErrorCode> SignalErrorMessageReceived;
173 
174  private:
175   typedef std::list<talk_base::scoped_refptr<StreamCollectionInterface> >
176           StreamCollectionList;
177 
178   // Change the State and triggers the SignalStateChange signal.
179   void ChangeState(State new_state);
180 
181   // This is called by CreateOffer. Creates an offer based on the first stream
182   // collection in |queued_local_streams_|.
183   void InitializeSendingOffer();
184   // Serializes and sends |local_desc|
185   void SendOffer(const SessionDescriptionInterface* local_desc);
186 
187   // This is called by ProcessSignalingMessage when a remote offer
188   // has been received.
189   void InitializeSendingAnswer(StreamCollectionInterface* local_streams);
190   // Serializes and sends |local_desc_|.
191   void SendAnswer();
192 
193   // Notifies the |provider_| about the shutdown.
194   // This is either initiated by ProcessSignalingMessage when a remote shutdown
195   // message has been received or by a call to SendShutDown.
196   void DoShutDown();
197 
198   // Process session description from the remote peer.
199   bool ProcessRemoteDescription(const std::string& sdp,
200                                 JsepInterface::Action action);
201 
202   // Updates the state of local streams based on the answer_desc and the streams
203   // that have been negotiated in negotiated_streams.
204   void UpdateSendingLocalStreams(
205       const cricket::SessionDescription* answer_desc,
206       StreamCollectionInterface* negotiated_streams);
207 
208   MediaStreamSignaling* stream_signaling_;
209   JsepInterface* provider_;
210   State state_;
211 
212   // Flag indicating RoapSignaling was called with an offer while
213   // RoapSignaling is in kInitializing state.
214   bool received_pre_offer_;
215 
216   // LocalStreams queued for later use if CreateOffer
217   // is called while RoapSignaling is in kNew state or
218   // CreateOffer is called while RoapSignaling is currently sending
219   // an offer.
220   StreamCollectionList queued_local_streams_;
221 
222   // The local session description of the local MediaStreams that is being
223   // negotiated.
224   talk_base::scoped_ptr<SessionDescriptionInterface> local_desc_;
225 
226   // Local MediaStreams being negotiated.
227   talk_base::scoped_refptr<StreamCollection> local_streams_;
228 
229   // roap_session_ holds the ROAP-specific session state and is used for
230   // creating a parsing ROAP messages.
231   RoapSession roap_session_;
232 
233   DISALLOW_COPY_AND_ASSIGN(RoapSignaling);
234 };
235 
236 }  // namespace webrtc
237 
238 #endif  // TALK_APP_WEBRTC_ROAPSIGNALING_H_
239