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