blob: 329ae2a285c72ae09b01a643496e397875187743 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_P2P_BASE_SESSION_H_
12#define WEBRTC_P2P_BASE_SESSION_H_
13
14#include <list>
15#include <map>
16#include <string>
17#include <vector>
18
pthatcher@webrtc.orgaacc2342014-12-18 20:31:29 +000019#include "webrtc/p2p/base/candidate.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000020#include "webrtc/p2p/base/port.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021#include "webrtc/p2p/base/transport.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000022#include "webrtc/base/refcount.h"
23#include "webrtc/base/scoped_ptr.h"
24#include "webrtc/base/scoped_ref_ptr.h"
25#include "webrtc/base/socketaddress.h"
26
27namespace cricket {
28
29class BaseSession;
30class P2PTransportChannel;
31class Transport;
32class TransportChannel;
bjornv@webrtc.org520a69e2015-02-04 12:45:44 +000033class TransportChannelProxy;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000034class TransportChannelImpl;
35
bjornv@webrtc.org520a69e2015-02-04 12:45:44 +000036typedef rtc::RefCountedObject<rtc::scoped_ptr<Transport> >
37TransportWrapper;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000038
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000039// Bundles a Transport and ChannelMap together. ChannelMap is used to
40// create transport channels before receiving or sending a session
41// initiate, and for speculatively connecting channels. Previously, a
42// session had one ChannelMap and transport. Now, with multiple
43// transports per session, we need multiple ChannelMaps as well.
44
bjornv@webrtc.org520a69e2015-02-04 12:45:44 +000045typedef std::map<int, TransportChannelProxy*> ChannelMap;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000046
pthatcher@webrtc.org990a00c2015-03-13 18:20:33 +000047class TransportProxy : public sigslot::has_slots<> {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000048 public:
49 TransportProxy(
50 rtc::Thread* worker_thread,
51 const std::string& sid,
52 const std::string& content_name,
53 TransportWrapper* transport)
54 : worker_thread_(worker_thread),
55 sid_(sid),
56 content_name_(content_name),
57 transport_(transport),
58 connecting_(false),
59 negotiated_(false),
60 sent_candidates_(false),
61 candidates_allocated_(false),
62 local_description_set_(false),
63 remote_description_set_(false) {
64 transport_->get()->SignalCandidatesReady.connect(
65 this, &TransportProxy::OnTransportCandidatesReady);
66 }
67 ~TransportProxy();
68
69 const std::string& content_name() const { return content_name_; }
70 // TODO(juberti): It's not good form to expose the object you're wrapping,
71 // since callers can mutate it. Can we make this return a const Transport*?
72 Transport* impl() const { return transport_->get(); }
73
74 const std::string& type() const;
75 bool negotiated() const { return negotiated_; }
76 const Candidates& sent_candidates() const { return sent_candidates_; }
77 const Candidates& unsent_candidates() const { return unsent_candidates_; }
78 bool candidates_allocated() const { return candidates_allocated_; }
79 void set_candidates_allocated(bool allocated) {
80 candidates_allocated_ = allocated;
81 }
82
83 TransportChannel* GetChannel(int component);
84 TransportChannel* CreateChannel(const std::string& channel_name,
85 int component);
86 bool HasChannel(int component);
87 void DestroyChannel(int component);
88
89 void AddSentCandidates(const Candidates& candidates);
90 void AddUnsentCandidates(const Candidates& candidates);
91 void ClearSentCandidates() { sent_candidates_.clear(); }
92 void ClearUnsentCandidates() { unsent_candidates_.clear(); }
93
94 // Start the connection process for any channels, creating impls if needed.
95 void ConnectChannels();
96 // Hook up impls to the proxy channels. Doesn't change connect state.
97 void CompleteNegotiation();
98
99 // Mux this proxy onto the specified proxy's transport.
100 bool SetupMux(TransportProxy* proxy);
101
102 // Simple functions that thunk down to the same functions on Transport.
103 void SetIceRole(IceRole role);
104 void SetIdentity(rtc::SSLIdentity* identity);
105 bool SetLocalTransportDescription(const TransportDescription& description,
106 ContentAction action,
107 std::string* error_desc);
108 bool SetRemoteTransportDescription(const TransportDescription& description,
109 ContentAction action,
110 std::string* error_desc);
111 void OnSignalingReady();
112 bool OnRemoteCandidates(const Candidates& candidates, std::string* error);
113
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000114 // Called when a transport signals that it has new candidates.
115 void OnTransportCandidatesReady(cricket::Transport* transport,
116 const Candidates& candidates) {
117 SignalCandidatesReady(this, candidates);
118 }
119
120 bool local_description_set() const {
121 return local_description_set_;
122 }
123 bool remote_description_set() const {
124 return remote_description_set_;
125 }
126
127 // Handles sending of ready candidates and receiving of remote candidates.
128 sigslot::signal2<TransportProxy*,
129 const std::vector<Candidate>&> SignalCandidatesReady;
130
131 private:
132 TransportChannelProxy* GetChannelProxy(int component) const;
133 TransportChannelProxy* GetChannelProxyByName(const std::string& name) const;
134
decurtis@webrtc.org357469d2015-01-15 22:53:49 +0000135 // Creates a new channel on the Transport which causes the reference
136 // count to increment.
137 void CreateChannelImpl(int component);
138 void CreateChannelImpl_w(int component);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000139
140 // Manipulators of transportchannelimpl in channel proxy.
decurtis@webrtc.org357469d2015-01-15 22:53:49 +0000141 void SetChannelImplFromTransport(TransportChannelProxy* proxy, int component);
142 void SetChannelImplFromTransport_w(TransportChannelProxy* proxy,
143 int component);
144 void ReplaceChannelImpl(TransportChannelProxy* proxy,
145 TransportChannelImpl* impl);
146 void ReplaceChannelImpl_w(TransportChannelProxy* proxy,
147 TransportChannelImpl* impl);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000148
149 rtc::Thread* const worker_thread_;
150 const std::string sid_;
151 const std::string content_name_;
152 rtc::scoped_refptr<TransportWrapper> transport_;
153 bool connecting_;
154 bool negotiated_;
155 ChannelMap channels_;
156 Candidates sent_candidates_;
157 Candidates unsent_candidates_;
158 bool candidates_allocated_;
159 bool local_description_set_;
160 bool remote_description_set_;
161};
162
163typedef std::map<std::string, TransportProxy*> TransportMap;
164
165// Statistics for all the transports of this session.
166typedef std::map<std::string, TransportStats> TransportStatsMap;
167typedef std::map<std::string, std::string> ProxyTransportMap;
168
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +0000169// TODO(pthatcher): Think of a better name for this. We already have
170// a TransportStats in transport.h. Perhaps TransportsStats?
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000171struct SessionStats {
172 ProxyTransportMap proxy_to_transport;
173 TransportStatsMap transport_stats;
174};
175
176// A BaseSession manages general session state. This includes negotiation
177// of both the application-level and network-level protocols: the former
178// defines what will be sent and the latter defines how it will be sent. Each
179// network-level protocol is represented by a Transport object. Each Transport
180// participates in the network-level negotiation. The individual streams of
181// packets are represented by TransportChannels. The application-level protocol
182// is represented by SessionDecription objects.
183class BaseSession : public sigslot::has_slots<>,
184 public rtc::MessageHandler {
185 public:
186 enum {
187 MSG_TIMEOUT = 0,
188 MSG_ERROR,
189 MSG_STATE,
190 };
191
192 enum State {
193 STATE_INIT = 0,
194 STATE_SENTINITIATE, // sent initiate, waiting for Accept or Reject
195 STATE_RECEIVEDINITIATE, // received an initiate. Call Accept or Reject
196 STATE_SENTPRACCEPT, // sent provisional Accept
197 STATE_SENTACCEPT, // sent accept. begin connecting transport
198 STATE_RECEIVEDPRACCEPT, // received provisional Accept, waiting for Accept
199 STATE_RECEIVEDACCEPT, // received accept. begin connecting transport
200 STATE_SENTMODIFY, // sent modify, waiting for Accept or Reject
201 STATE_RECEIVEDMODIFY, // received modify, call Accept or Reject
202 STATE_SENTREJECT, // sent reject after receiving initiate
203 STATE_RECEIVEDREJECT, // received reject after sending initiate
204 STATE_SENTREDIRECT, // sent direct after receiving initiate
205 STATE_SENTTERMINATE, // sent terminate (any time / either side)
206 STATE_RECEIVEDTERMINATE, // received terminate (any time / either side)
207 STATE_INPROGRESS, // session accepted and in progress
208 STATE_DEINIT, // session is being destroyed
209 };
210
211 enum Error {
212 ERROR_NONE = 0, // no error
213 ERROR_TIME = 1, // no response to signaling
214 ERROR_RESPONSE = 2, // error during signaling
215 ERROR_NETWORK = 3, // network error, could not allocate network resources
216 ERROR_CONTENT = 4, // channel errors in SetLocalContent/SetRemoteContent
217 ERROR_TRANSPORT = 5, // transport error of some kind
218 };
219
220 // Convert State to a readable string.
221 static std::string StateToString(State state);
222
223 BaseSession(rtc::Thread* signaling_thread,
224 rtc::Thread* worker_thread,
225 PortAllocator* port_allocator,
226 const std::string& sid,
227 const std::string& content_type,
228 bool initiator);
229 virtual ~BaseSession();
230
231 // These are const to allow them to be called from const methods.
232 rtc::Thread* signaling_thread() const { return signaling_thread_; }
233 rtc::Thread* worker_thread() const { return worker_thread_; }
234 PortAllocator* port_allocator() const { return port_allocator_; }
235
236 // The ID of this session.
237 const std::string& id() const { return sid_; }
238
239 // TODO(juberti): This data is largely redundant, as it can now be obtained
240 // from local/remote_description(). Remove these functions and members.
241 // Returns the XML namespace identifying the type of this session.
242 const std::string& content_type() const { return content_type_; }
243 // Returns the XML namespace identifying the transport used for this session.
244 const std::string& transport_type() const { return transport_type_; }
245
246 // Indicates whether we initiated this session.
247 bool initiator() const { return initiator_; }
248
249 // Returns the application-level description given by our client.
250 // If we are the recipient, this will be NULL until we send an accept.
251 const SessionDescription* local_description() const;
252
253 // Returns the application-level description given by the other client.
254 // If we are the initiator, this will be NULL until we receive an accept.
255 const SessionDescription* remote_description() const;
256
257 SessionDescription* remote_description();
258
259 // Takes ownership of SessionDescription*
260 void set_local_description(const SessionDescription* sdesc);
261
262 // Takes ownership of SessionDescription*
263 void set_remote_description(SessionDescription* sdesc);
264
265 const SessionDescription* initiator_description() const;
266
267 // Returns the current state of the session. See the enum above for details.
268 // Each time the state changes, we will fire this signal.
269 State state() const { return state_; }
270 sigslot::signal2<BaseSession* , State> SignalState;
271
272 // Returns the last error in the session. See the enum above for details.
273 // Each time the an error occurs, we will fire this signal.
274 Error error() const { return error_; }
275 const std::string& error_desc() const { return error_desc_; }
276 sigslot::signal2<BaseSession* , Error> SignalError;
277
278 // Updates the state, signaling if necessary.
279 virtual void SetState(State state);
280
281 // Updates the error state, signaling if necessary.
282 // TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
283 virtual void SetError(Error error, const std::string& error_desc);
284
285 // Fired when the remote description is updated, with the updated
286 // contents.
287 sigslot::signal2<BaseSession* , const ContentInfos&>
288 SignalRemoteDescriptionUpdate;
289
290 // Fired when SetState is called (regardless if there's a state change), which
291 // indicates the session description might have be updated.
292 sigslot::signal2<BaseSession*, ContentAction> SignalNewLocalDescription;
293
294 // Fired when SetState is called (regardless if there's a state change), which
295 // indicates the session description might have be updated.
296 sigslot::signal2<BaseSession*, ContentAction> SignalNewRemoteDescription;
297
298 // Returns the transport that has been negotiated or NULL if
299 // negotiation is still in progress.
300 virtual Transport* GetTransport(const std::string& content_name);
301
302 // Creates a new channel with the given names. This method may be called
303 // immediately after creating the session. However, the actual
304 // implementation may not be fixed until transport negotiation completes.
305 // This will usually be called from the worker thread, but that
306 // shouldn't be an issue since the main thread will be blocked in
307 // Send when doing so.
308 virtual TransportChannel* CreateChannel(const std::string& content_name,
309 const std::string& channel_name,
310 int component);
311
312 // Returns the channel with the given names.
313 virtual TransportChannel* GetChannel(const std::string& content_name,
314 int component);
315
316 // Destroys the channel with the given names.
317 // This will usually be called from the worker thread, but that
318 // shouldn't be an issue since the main thread will be blocked in
319 // Send when doing so.
320 virtual void DestroyChannel(const std::string& content_name,
321 int component);
322
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000323 rtc::SSLIdentity* identity() { return identity_; }
324
325 protected:
326 // Specifies the identity to use in this session.
327 bool SetIdentity(rtc::SSLIdentity* identity);
328
329 bool PushdownTransportDescription(ContentSource source,
330 ContentAction action,
331 std::string* error_desc);
332 void set_initiator(bool initiator) { initiator_ = initiator; }
333
334 const TransportMap& transport_proxies() const { return transports_; }
335 // Get a TransportProxy by content_name or transport. NULL if not found.
336 TransportProxy* GetTransportProxy(const std::string& content_name);
337 TransportProxy* GetTransportProxy(const Transport* transport);
338 TransportProxy* GetFirstTransportProxy();
339 void DestroyTransportProxy(const std::string& content_name);
340 // TransportProxy is owned by session. Return proxy just for convenience.
341 TransportProxy* GetOrCreateTransportProxy(const std::string& content_name);
342 // Creates the actual transport object. Overridable for testing.
343 virtual Transport* CreateTransport(const std::string& content_name);
344
345 void OnSignalingReady();
346 void SpeculativelyConnectAllTransportChannels();
347 // Helper method to provide remote candidates to the transport.
348 bool OnRemoteCandidates(const std::string& content_name,
349 const Candidates& candidates,
350 std::string* error);
351
352 // This method will mux transport channels by content_name.
353 // First content is used for muxing.
354 bool MaybeEnableMuxingSupport();
355
356 // Called when a transport requests signaling.
357 virtual void OnTransportRequestSignaling(Transport* transport) {
358 }
359
360 // Called when the first channel of a transport begins connecting. We use
361 // this to start a timer, to make sure that the connection completes in a
362 // reasonable amount of time.
363 virtual void OnTransportConnecting(Transport* transport) {
364 }
365
366 // Called when a transport changes its writable state. We track this to make
367 // sure that the transport becomes writable within a reasonable amount of
368 // time. If this does not occur, we signal an error.
369 virtual void OnTransportWritable(Transport* transport) {
370 }
371 virtual void OnTransportReadable(Transport* transport) {
372 }
373
374 // Called when a transport has found its steady-state connections.
375 virtual void OnTransportCompleted(Transport* transport) {
376 }
377
378 // Called when a transport has failed permanently.
379 virtual void OnTransportFailed(Transport* transport) {
380 }
381
382 // Called when a transport signals that it has new candidates.
383 virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy,
384 const Candidates& candidates) {
385 }
386
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000387 virtual void OnTransportRouteChange(
388 Transport* transport,
389 int component,
390 const cricket::Candidate& remote_candidate) {
391 }
392
393 virtual void OnTransportCandidatesAllocationDone(Transport* transport);
394
395 // Called when all transport channels allocated required candidates.
396 // This method should be used as an indication of candidates gathering process
397 // is completed and application can now send local candidates list to remote.
398 virtual void OnCandidatesAllocationDone() {
399 }
400
401 // Handles the ice role change callback from Transport. This must be
402 // propagated to all the transports.
403 virtual void OnRoleConflict();
404
405 // Handles messages posted to us.
406 virtual void OnMessage(rtc::Message *pmsg);
407
408 protected:
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000409 bool IsCandidateAllocationDone() const;
410
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000411 State state_;
412 Error error_;
413 std::string error_desc_;
414
415 private:
416 // Helper methods to push local and remote transport descriptions.
417 bool PushdownLocalTransportDescription(
418 const SessionDescription* sdesc, ContentAction action,
419 std::string* error_desc);
420 bool PushdownRemoteTransportDescription(
421 const SessionDescription* sdesc, ContentAction action,
422 std::string* error_desc);
423
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000424 void MaybeCandidateAllocationDone();
425
426 // This method will delete the Transport and TransportChannelImpls and
427 // replace those with the selected Transport objects. Selection is done
428 // based on the content_name and in this case first MediaContent information
429 // is used for mux.
430 bool SetSelectedProxy(const std::string& content_name,
431 const ContentGroup* muxed_group);
432 // Log session state.
433 void LogState(State old_state, State new_state);
434
435 // Returns true and the TransportInfo of the given |content_name|
436 // from |description|. Returns false if it's not available.
437 static bool GetTransportDescription(const SessionDescription* description,
438 const std::string& content_name,
439 TransportDescription* info);
440
441 // Fires the new description signal according to the current state.
442 void SignalNewDescription();
443
444 // Gets the ContentAction and ContentSource according to the session state.
445 bool GetContentAction(ContentAction* action, ContentSource* source);
446
447 rtc::Thread* const signaling_thread_;
448 rtc::Thread* const worker_thread_;
449 PortAllocator* const port_allocator_;
450 const std::string sid_;
451 const std::string content_type_;
452 const std::string transport_type_;
453 bool initiator_;
454 rtc::SSLIdentity* identity_;
455 rtc::scoped_ptr<const SessionDescription> local_description_;
456 rtc::scoped_ptr<SessionDescription> remote_description_;
457 uint64 ice_tiebreaker_;
458 // This flag will be set to true after the first role switch. This flag
459 // will enable us to stop any role switch during the call.
460 bool role_switch_;
461 TransportMap transports_;
462};
463
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000464} // namespace cricket
465
466#endif // WEBRTC_P2P_BASE_SESSION_H_