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