• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004--2005, 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_P2P_BASE_SESSION_H_
29 #define TALK_P2P_BASE_SESSION_H_
30 
31 #include <list>
32 #include <map>
33 #include <string>
34 #include <vector>
35 
36 #include "talk/base/refcount.h"
37 #include "talk/base/scoped_ptr.h"
38 #include "talk/base/scoped_ref_ptr.h"
39 #include "talk/base/socketaddress.h"
40 #include "talk/p2p/base/parsing.h"
41 #include "talk/p2p/base/port.h"
42 #include "talk/p2p/base/sessionclient.h"
43 #include "talk/p2p/base/sessionmanager.h"
44 #include "talk/p2p/base/sessionmessages.h"
45 #include "talk/p2p/base/transport.h"
46 #include "talk/xmllite/xmlelement.h"
47 #include "talk/xmpp/constants.h"
48 
49 namespace cricket {
50 
51 class BaseSession;
52 class P2PTransportChannel;
53 class Transport;
54 class TransportChannel;
55 class TransportChannelProxy;
56 class TransportChannelImpl;
57 
58 typedef talk_base::RefCountedObject<talk_base::scoped_ptr<Transport> >
59 TransportWrapper;
60 
61 // Used for errors that will send back a specific error message to the
62 // remote peer.  We add "type" to the errors because it's needed for
63 // SignalErrorMessage.
64 struct MessageError : ParseError {
65   buzz::QName type;
66 
67   // if unset, assume type is a parse error
MessageErrorMessageError68   MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {}
69 
SetTypeMessageError70   void SetType(const buzz::QName type) {
71     this->type = type;
72   }
73 };
74 
75 // Used for errors that may be returned by public session methods that
76 // can fail.
77 // TODO: Use this error in Session::Initiate and
78 // Session::Accept.
79 struct SessionError : WriteError {
80 };
81 
82 // Bundles a Transport and ChannelMap together. ChannelMap is used to
83 // create transport channels before receiving or sending a session
84 // initiate, and for speculatively connecting channels.  Previously, a
85 // session had one ChannelMap and transport.  Now, with multiple
86 // transports per session, we need multiple ChannelMaps as well.
87 
88 typedef std::map<int, TransportChannelProxy*> ChannelMap;
89 
90 class TransportProxy : public sigslot::has_slots<>,
91                        public CandidateTranslator {
92  public:
TransportProxy(talk_base::Thread * worker_thread,const std::string & sid,const std::string & content_name,TransportWrapper * transport)93   TransportProxy(
94       talk_base::Thread* worker_thread,
95       const std::string& sid,
96       const std::string& content_name,
97       TransportWrapper* transport)
98       : worker_thread_(worker_thread),
99         sid_(sid),
100         content_name_(content_name),
101         transport_(transport),
102         connecting_(false),
103         negotiated_(false),
104         sent_candidates_(false),
105         candidates_allocated_(false),
106         local_description_set_(false),
107         remote_description_set_(false) {
108     transport_->get()->SignalCandidatesReady.connect(
109         this, &TransportProxy::OnTransportCandidatesReady);
110   }
111   ~TransportProxy();
112 
content_name()113   std::string content_name() const { return content_name_; }
114   // TODO(juberti): It's not good form to expose the object you're wrapping,
115   // since callers can mutate it. Can we make this return a const Transport*?
impl()116   Transport* impl() const { return transport_->get(); }
117 
118   std::string type() const;
negotiated()119   bool negotiated() const { return negotiated_; }
sent_candidates()120   const Candidates& sent_candidates() const { return sent_candidates_; }
unsent_candidates()121   const Candidates& unsent_candidates() const { return unsent_candidates_; }
candidates_allocated()122   bool candidates_allocated() const { return candidates_allocated_; }
set_candidates_allocated(bool allocated)123   void set_candidates_allocated(bool allocated) {
124     candidates_allocated_ = allocated;
125   }
126 
127   TransportChannel* GetChannel(int component);
128   TransportChannel* CreateChannel(const std::string& channel_name,
129                                   int component);
130   bool HasChannel(int component);
131   void DestroyChannel(int component);
132 
133   void AddSentCandidates(const Candidates& candidates);
134   void AddUnsentCandidates(const Candidates& candidates);
ClearSentCandidates()135   void ClearSentCandidates() { sent_candidates_.clear(); }
ClearUnsentCandidates()136   void ClearUnsentCandidates() { unsent_candidates_.clear(); }
137 
138   // Start the connection process for any channels, creating impls if needed.
139   void ConnectChannels();
140   // Hook up impls to the proxy channels. Doesn't change connect state.
141   void CompleteNegotiation();
142 
143   // Mux this proxy onto the specified proxy's transport.
144   bool SetupMux(TransportProxy* proxy);
145 
146   // Simple functions that thunk down to the same functions on Transport.
147   void SetIceRole(IceRole role);
148   void SetIdentity(talk_base::SSLIdentity* identity);
149   bool SetLocalTransportDescription(const TransportDescription& description,
150                                     ContentAction action,
151                                     std::string* error_desc);
152   bool SetRemoteTransportDescription(const TransportDescription& description,
153                                      ContentAction action,
154                                      std::string* error_desc);
155   void OnSignalingReady();
156   bool OnRemoteCandidates(const Candidates& candidates, std::string* error);
157 
158   // CandidateTranslator methods.
159   virtual bool GetChannelNameFromComponent(
160       int component, std::string* channel_name) const;
161   virtual bool GetComponentFromChannelName(
162       const std::string& channel_name, int* component) const;
163 
164   // Called when a transport signals that it has new candidates.
OnTransportCandidatesReady(cricket::Transport * transport,const Candidates & candidates)165   void OnTransportCandidatesReady(cricket::Transport* transport,
166                                   const Candidates& candidates) {
167     SignalCandidatesReady(this, candidates);
168   }
169 
local_description_set()170   bool local_description_set() const {
171     return local_description_set_;
172   }
remote_description_set()173   bool remote_description_set() const {
174     return remote_description_set_;
175   }
176 
177   // Handles sending of ready candidates and receiving of remote candidates.
178   sigslot::signal2<TransportProxy*,
179                          const std::vector<Candidate>&> SignalCandidatesReady;
180 
181  private:
182   TransportChannelProxy* GetChannelProxy(int component) const;
183   TransportChannelProxy* GetChannelProxyByName(const std::string& name) const;
184 
185   TransportChannelImpl* GetOrCreateChannelProxyImpl(int component);
186   TransportChannelImpl* GetOrCreateChannelProxyImpl_w(int component);
187 
188   // Manipulators of transportchannelimpl in channel proxy.
189   void SetupChannelProxy(int component,
190                            TransportChannelProxy* proxy);
191   void SetupChannelProxy_w(int component,
192                              TransportChannelProxy* proxy);
193   void ReplaceChannelProxyImpl(TransportChannelProxy* proxy,
194                                TransportChannelImpl* impl);
195   void ReplaceChannelProxyImpl_w(TransportChannelProxy* proxy,
196                                  TransportChannelImpl* impl);
197 
198   talk_base::Thread* worker_thread_;
199   std::string sid_;
200   std::string content_name_;
201   talk_base::scoped_refptr<TransportWrapper> transport_;
202   bool connecting_;
203   bool negotiated_;
204   ChannelMap channels_;
205   Candidates sent_candidates_;
206   Candidates unsent_candidates_;
207   bool candidates_allocated_;
208   bool local_description_set_;
209   bool remote_description_set_;
210 };
211 
212 typedef std::map<std::string, TransportProxy*> TransportMap;
213 
214 // Statistics for all the transports of this session.
215 typedef std::map<std::string, TransportStats> TransportStatsMap;
216 typedef std::map<std::string, std::string> ProxyTransportMap;
217 
218 struct SessionStats {
219   ProxyTransportMap proxy_to_transport;
220   TransportStatsMap transport_stats;
221 };
222 
223 // A BaseSession manages general session state. This includes negotiation
224 // of both the application-level and network-level protocols:  the former
225 // defines what will be sent and the latter defines how it will be sent.  Each
226 // network-level protocol is represented by a Transport object.  Each Transport
227 // participates in the network-level negotiation.  The individual streams of
228 // packets are represented by TransportChannels.  The application-level protocol
229 // is represented by SessionDecription objects.
230 class BaseSession : public sigslot::has_slots<>,
231                     public talk_base::MessageHandler {
232  public:
233   enum {
234     MSG_TIMEOUT = 0,
235     MSG_ERROR,
236     MSG_STATE,
237   };
238 
239   enum State {
240     STATE_INIT = 0,
241     STATE_SENTINITIATE,       // sent initiate, waiting for Accept or Reject
242     STATE_RECEIVEDINITIATE,   // received an initiate. Call Accept or Reject
243     STATE_SENTPRACCEPT,       // sent provisional Accept
244     STATE_SENTACCEPT,         // sent accept. begin connecting transport
245     STATE_RECEIVEDPRACCEPT,   // received provisional Accept, waiting for Accept
246     STATE_RECEIVEDACCEPT,     // received accept. begin connecting transport
247     STATE_SENTMODIFY,         // sent modify, waiting for Accept or Reject
248     STATE_RECEIVEDMODIFY,     // received modify, call Accept or Reject
249     STATE_SENTREJECT,         // sent reject after receiving initiate
250     STATE_RECEIVEDREJECT,     // received reject after sending initiate
251     STATE_SENTREDIRECT,       // sent direct after receiving initiate
252     STATE_SENTTERMINATE,      // sent terminate (any time / either side)
253     STATE_RECEIVEDTERMINATE,  // received terminate (any time / either side)
254     STATE_INPROGRESS,         // session accepted and in progress
255     STATE_DEINIT,             // session is being destroyed
256   };
257 
258   enum Error {
259     ERROR_NONE = 0,       // no error
260     ERROR_TIME = 1,       // no response to signaling
261     ERROR_RESPONSE = 2,   // error during signaling
262     ERROR_NETWORK = 3,    // network error, could not allocate network resources
263     ERROR_CONTENT = 4,    // channel errors in SetLocalContent/SetRemoteContent
264     ERROR_TRANSPORT = 5,  // transport error of some kind
265   };
266 
267   // Convert State to a readable string.
268   static std::string StateToString(State state);
269 
270   BaseSession(talk_base::Thread* signaling_thread,
271               talk_base::Thread* worker_thread,
272               PortAllocator* port_allocator,
273               const std::string& sid,
274               const std::string& content_type,
275               bool initiator);
276   virtual ~BaseSession();
277 
signaling_thread()278   talk_base::Thread* signaling_thread() { return signaling_thread_; }
worker_thread()279   talk_base::Thread* worker_thread() { return worker_thread_; }
port_allocator()280   PortAllocator* port_allocator() { return port_allocator_; }
281 
282   // The ID of this session.
id()283   const std::string& id() const { return sid_; }
284 
285   // TODO(juberti): This data is largely redundant, as it can now be obtained
286   // from local/remote_description(). Remove these functions and members.
287   // Returns the XML namespace identifying the type of this session.
content_type()288   const std::string& content_type() const { return content_type_; }
289   // Returns the XML namespace identifying the transport used for this session.
transport_type()290   const std::string& transport_type() const { return transport_type_; }
291 
292   // Indicates whether we initiated this session.
initiator()293   bool initiator() const { return initiator_; }
294 
295   // Returns the application-level description given by our client.
296   // If we are the recipient, this will be NULL until we send an accept.
local_description()297   const SessionDescription* local_description() const {
298     return local_description_;
299   }
300   // Returns the application-level description given by the other client.
301   // If we are the initiator, this will be NULL until we receive an accept.
remote_description()302   const SessionDescription* remote_description() const {
303     return remote_description_;
304   }
remote_description()305   SessionDescription* remote_description() {
306     return remote_description_;
307   }
308 
309   // Takes ownership of SessionDescription*
set_local_description(const SessionDescription * sdesc)310   bool set_local_description(const SessionDescription* sdesc) {
311     if (sdesc != local_description_) {
312       delete local_description_;
313       local_description_ = sdesc;
314     }
315     return true;
316   }
317 
318   // Takes ownership of SessionDescription*
set_remote_description(SessionDescription * sdesc)319   bool set_remote_description(SessionDescription* sdesc) {
320     if (sdesc != remote_description_) {
321       delete remote_description_;
322       remote_description_ = sdesc;
323     }
324     return true;
325   }
326 
initiator_description()327   const SessionDescription* initiator_description() const {
328     if (initiator_) {
329       return local_description_;
330     } else {
331       return remote_description_;
332     }
333   }
334 
335   // Returns the current state of the session.  See the enum above for details.
336   // Each time the state changes, we will fire this signal.
state()337   State state() const { return state_; }
338   sigslot::signal2<BaseSession* , State> SignalState;
339 
340   // Returns the last error in the session.  See the enum above for details.
341   // Each time the an error occurs, we will fire this signal.
error()342   Error error() const { return error_; }
error_desc()343   const std::string& error_desc() const { return error_desc_; }
344   sigslot::signal2<BaseSession* , Error> SignalError;
345 
346   // Updates the state, signaling if necessary.
347   virtual void SetState(State state);
348 
349   // Updates the error state, signaling if necessary.
350   // TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
351   virtual void SetError(Error error, const std::string& error_desc);
352 
353   // Fired when the remote description is updated, with the updated
354   // contents.
355   sigslot::signal2<BaseSession* , const ContentInfos&>
356       SignalRemoteDescriptionUpdate;
357 
358   // Fired when SetState is called (regardless if there's a state change), which
359   // indicates the session description might have be updated.
360   sigslot::signal2<BaseSession*, ContentAction> SignalNewLocalDescription;
361 
362   // Fired when SetState is called (regardless if there's a state change), which
363   // indicates the session description might have be updated.
364   sigslot::signal2<BaseSession*, ContentAction> SignalNewRemoteDescription;
365 
366   // Returns the transport that has been negotiated or NULL if
367   // negotiation is still in progress.
368   virtual Transport* GetTransport(const std::string& content_name);
369 
370   // Creates a new channel with the given names.  This method may be called
371   // immediately after creating the session.  However, the actual
372   // implementation may not be fixed until transport negotiation completes.
373   // This will usually be called from the worker thread, but that
374   // shouldn't be an issue since the main thread will be blocked in
375   // Send when doing so.
376   virtual TransportChannel* CreateChannel(const std::string& content_name,
377                                           const std::string& channel_name,
378                                           int component);
379 
380   // Returns the channel with the given names.
381   virtual TransportChannel* GetChannel(const std::string& content_name,
382                                        int component);
383 
384   // Destroys the channel with the given names.
385   // This will usually be called from the worker thread, but that
386   // shouldn't be an issue since the main thread will be blocked in
387   // Send when doing so.
388   virtual void DestroyChannel(const std::string& content_name,
389                               int component);
390 
391   // Returns stats for all channels of all transports.
392   // This avoids exposing the internal structures used to track them.
393   virtual bool GetStats(SessionStats* stats);
394 
identity()395   talk_base::SSLIdentity* identity() { return identity_; }
396 
397  protected:
398   // Specifies the identity to use in this session.
399   bool SetIdentity(talk_base::SSLIdentity* identity);
400 
401   bool PushdownTransportDescription(ContentSource source,
402                                     ContentAction action,
403                                     std::string* error_desc);
set_initiator(bool initiator)404   void set_initiator(bool initiator) { initiator_ = initiator; }
405 
transport_proxies()406   const TransportMap& transport_proxies() const { return transports_; }
407   // Get a TransportProxy by content_name or transport. NULL if not found.
408   TransportProxy* GetTransportProxy(const std::string& content_name);
409   TransportProxy* GetTransportProxy(const Transport* transport);
410   TransportProxy* GetFirstTransportProxy();
411   void DestroyTransportProxy(const std::string& content_name);
412   // TransportProxy is owned by session.  Return proxy just for convenience.
413   TransportProxy* GetOrCreateTransportProxy(const std::string& content_name);
414   // Creates the actual transport object. Overridable for testing.
415   virtual Transport* CreateTransport(const std::string& content_name);
416 
417   void OnSignalingReady();
418   void SpeculativelyConnectAllTransportChannels();
419   // Helper method to provide remote candidates to the transport.
420   bool OnRemoteCandidates(const std::string& content_name,
421                           const Candidates& candidates,
422                           std::string* error);
423 
424   // This method will mux transport channels by content_name.
425   // First content is used for muxing.
426   bool MaybeEnableMuxingSupport();
427 
428   // Called when a transport requests signaling.
OnTransportRequestSignaling(Transport * transport)429   virtual void OnTransportRequestSignaling(Transport* transport) {
430   }
431 
432   // Called when the first channel of a transport begins connecting.  We use
433   // this to start a timer, to make sure that the connection completes in a
434   // reasonable amount of time.
OnTransportConnecting(Transport * transport)435   virtual void OnTransportConnecting(Transport* transport) {
436   }
437 
438   // Called when a transport changes its writable state.  We track this to make
439   // sure that the transport becomes writable within a reasonable amount of
440   // time.  If this does not occur, we signal an error.
OnTransportWritable(Transport * transport)441   virtual void OnTransportWritable(Transport* transport) {
442   }
OnTransportReadable(Transport * transport)443   virtual void OnTransportReadable(Transport* transport) {
444   }
445 
446   // Called when a transport has found its steady-state connections.
OnTransportCompleted(Transport * transport)447   virtual void OnTransportCompleted(Transport* transport) {
448   }
449 
450   // Called when a transport has failed permanently.
OnTransportFailed(Transport * transport)451   virtual void OnTransportFailed(Transport* transport) {
452   }
453 
454   // Called when a transport signals that it has new candidates.
OnTransportProxyCandidatesReady(TransportProxy * proxy,const Candidates & candidates)455   virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy,
456                                                const Candidates& candidates) {
457   }
458 
459   // Called when a transport signals that it found an error in an incoming
460   // message.
OnTransportSendError(Transport * transport,const buzz::XmlElement * stanza,const buzz::QName & name,const std::string & type,const std::string & text,const buzz::XmlElement * extra_info)461   virtual void OnTransportSendError(Transport* transport,
462                                     const buzz::XmlElement* stanza,
463                                     const buzz::QName& name,
464                                     const std::string& type,
465                                     const std::string& text,
466                                     const buzz::XmlElement* extra_info) {
467   }
468 
OnTransportRouteChange(Transport * transport,int component,const cricket::Candidate & remote_candidate)469   virtual void OnTransportRouteChange(
470       Transport* transport,
471       int component,
472       const cricket::Candidate& remote_candidate) {
473   }
474 
475   virtual void OnTransportCandidatesAllocationDone(Transport* transport);
476 
477   // Called when all transport channels allocated required candidates.
478   // This method should be used as an indication of candidates gathering process
479   // is completed and application can now send local candidates list to remote.
OnCandidatesAllocationDone()480   virtual void OnCandidatesAllocationDone() {
481   }
482 
483   // Handles the ice role change callback from Transport. This must be
484   // propagated to all the transports.
485   virtual void OnRoleConflict();
486 
487   // Handles messages posted to us.
488   virtual void OnMessage(talk_base::Message *pmsg);
489 
490  protected:
491   State state_;
492   Error error_;
493   std::string error_desc_;
494 
495  private:
496   // Helper methods to push local and remote transport descriptions.
497   bool PushdownLocalTransportDescription(
498       const SessionDescription* sdesc, ContentAction action,
499       std::string* error_desc);
500   bool PushdownRemoteTransportDescription(
501       const SessionDescription* sdesc, ContentAction action,
502       std::string* error_desc);
503 
504   bool IsCandidateAllocationDone() const;
505   void MaybeCandidateAllocationDone();
506 
507   // This method will delete the Transport and TransportChannelImpls and
508   // replace those with the selected Transport objects. Selection is done
509   // based on the content_name and in this case first MediaContent information
510   // is used for mux.
511   bool SetSelectedProxy(const std::string& content_name,
512                         const ContentGroup* muxed_group);
513   // Log session state.
514   void LogState(State old_state, State new_state);
515 
516   // Returns true and the TransportInfo of the given |content_name|
517   // from |description|. Returns false if it's not available.
518   bool GetTransportDescription(const SessionDescription* description,
519                                const std::string& content_name,
520                                TransportDescription* info);
521 
522   // Fires the new description signal according to the current state.
523   void SignalNewDescription();
524 
525   // Gets the ContentAction and ContentSource according to the session state.
526   bool GetContentAction(ContentAction* action, ContentSource* source);
527 
528   talk_base::Thread* signaling_thread_;
529   talk_base::Thread* worker_thread_;
530   PortAllocator* port_allocator_;
531   std::string sid_;
532   std::string content_type_;
533   std::string transport_type_;
534   bool initiator_;
535   talk_base::SSLIdentity* identity_;
536   const SessionDescription* local_description_;
537   SessionDescription* remote_description_;
538   uint64 ice_tiebreaker_;
539   // This flag will be set to true after the first role switch. This flag
540   // will enable us to stop any role switch during the call.
541   bool role_switch_;
542   TransportMap transports_;
543 };
544 
545 // A specific Session created by the SessionManager, using XMPP for protocol.
546 class Session : public BaseSession {
547  public:
548   // Returns the manager that created and owns this session.
session_manager()549   SessionManager* session_manager() const { return session_manager_; }
550 
551   // Returns the client that is handling the application data of this session.
client()552   SessionClient* client() const { return client_; }
553 
554     // Returns the JID of this client.
local_name()555   const std::string& local_name() const { return local_name_; }
556 
557   // Returns the JID of the other peer in this session.
remote_name()558   const std::string& remote_name() const { return remote_name_; }
559 
560   // Set the JID of the other peer in this session.
561   // Typically the remote_name_ is set when the session is initiated.
562   // However, sometimes (e.g when a proxy is used) the peer name is
563   // known after the BaseSession has been initiated and it must be updated
564   // explicitly.
set_remote_name(const std::string & name)565   void set_remote_name(const std::string& name) { remote_name_ = name; }
566 
567   // Set the JID of the initiator of this session. Allows for the overriding
568   // of the initiator to be a third-party, eg. the MUC JID when creating p2p
569   // sessions.
set_initiator_name(const std::string & name)570   void set_initiator_name(const std::string& name) { initiator_name_ = name; }
571 
572   // Indicates the JID of the entity who initiated this session.
573   // In special cases, may be different than both local_name and remote_name.
initiator_name()574   const std::string& initiator_name() const { return initiator_name_; }
575 
current_protocol()576   SignalingProtocol current_protocol() const { return current_protocol_; }
577 
set_current_protocol(SignalingProtocol protocol)578   void set_current_protocol(SignalingProtocol protocol) {
579     current_protocol_ = protocol;
580   }
581 
582   // Updates the error state, signaling if necessary.
583   virtual void SetError(Error error, const std::string& error_desc);
584 
585   // When the session needs to send signaling messages, it beings by requesting
586   // signaling.  The client should handle this by calling OnSignalingReady once
587   // it is ready to send the messages.
588   // (These are called only by SessionManager.)
589   sigslot::signal1<Session*> SignalRequestSignaling;
OnSignalingReady()590   void OnSignalingReady() { BaseSession::OnSignalingReady(); }
591 
592   // Takes ownership of session description.
593   // TODO: Add an error argument to pass back to the caller.
594   bool Initiate(const std::string& to,
595                 const SessionDescription* sdesc);
596 
597   // When we receive an initiate, we create a session in the
598   // RECEIVEDINITIATE state and respond by accepting or rejecting.
599   // Takes ownership of session description.
600   // TODO: Add an error argument to pass back to the caller.
601   bool Accept(const SessionDescription* sdesc);
602   bool Reject(const std::string& reason);
Terminate()603   bool Terminate() {
604     return TerminateWithReason(STR_TERMINATE_SUCCESS);
605   }
606   bool TerminateWithReason(const std::string& reason);
607   // Fired whenever we receive a terminate message along with a reason
608   sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason;
609 
610   // The two clients in the session may also send one another
611   // arbitrary XML messages, which are called "info" messages. Sending
612   // takes ownership of the given elements.  The signal does not; the
613   // parent element will be deleted after the signal.
614   bool SendInfoMessage(const XmlElements& elems,
615                        const std::string& remote_name);
616   bool SendDescriptionInfoMessage(const ContentInfos& contents);
617   sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage;
618 
619  private:
620   // Creates or destroys a session.  (These are called only SessionManager.)
621   Session(SessionManager *session_manager,
622           const std::string& local_name, const std::string& initiator_name,
623           const std::string& sid, const std::string& content_type,
624           SessionClient* client);
625   ~Session();
626   // For each transport info, create a transport proxy.  Can fail for
627   // incompatible transport types.
628   bool CreateTransportProxies(const TransportInfos& tinfos,
629                               SessionError* error);
630   bool OnRemoteCandidates(const TransportInfos& tinfos,
631                           ParseError* error);
632   // Returns a TransportInfo without candidates for each content name.
633   // Uses the transport_type_ of the session.
634   TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
635 
636     // Maps passed to serialization functions.
637   TransportParserMap GetTransportParsers();
638   ContentParserMap GetContentParsers();
639   CandidateTranslatorMap GetCandidateTranslators();
640 
641   virtual void OnTransportRequestSignaling(Transport* transport);
642   virtual void OnTransportConnecting(Transport* transport);
643   virtual void OnTransportWritable(Transport* transport);
644   virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy,
645                                                const Candidates& candidates);
646   virtual void OnTransportSendError(Transport* transport,
647                                     const buzz::XmlElement* stanza,
648                                     const buzz::QName& name,
649                                     const std::string& type,
650                                     const std::string& text,
651                                     const buzz::XmlElement* extra_info);
652   virtual void OnMessage(talk_base::Message *pmsg);
653 
654   // Send various kinds of session messages.
655   bool SendInitiateMessage(const SessionDescription* sdesc,
656                            SessionError* error);
657   bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error);
658   bool SendRejectMessage(const std::string& reason, SessionError* error);
659   bool SendTerminateMessage(const std::string& reason, SessionError* error);
660   bool SendTransportInfoMessage(const TransportInfo& tinfo,
661                                 SessionError* error);
662   bool SendTransportInfoMessage(const TransportProxy* transproxy,
663                                 const Candidates& candidates,
664                                 SessionError* error);
665 
666   bool ResendAllTransportInfoMessages(SessionError* error);
667   bool SendAllUnsentTransportInfoMessages(SessionError* error);
668 
669   // All versions of SendMessage send a message of the given type to
670   // the other client.  Can pass either a set of elements or an
671   // "action", which must have a WriteSessionAction method to go along
672   // with it.  Sending with an action supports sending a "hybrid"
673   // message.  Sending with elements must be sent as Jingle or Gingle.
674 
675   // When passing elems, must be either Jingle or Gingle protocol.
676   // Takes ownership of action_elems.
677   bool SendMessage(ActionType type, const XmlElements& action_elems,
678                    SessionError* error);
679   // Sends a messge, but overrides the remote name.
680   bool SendMessage(ActionType type, const XmlElements& action_elems,
681                    const std::string& remote_name,
682                    SessionError* error);
683   // When passing an action, may be Hybrid protocol.
684   template <typename Action>
685   bool SendMessage(ActionType type, const Action& action,
686                    SessionError* error);
687 
688   // Helper methods to write the session message stanza.
689   template <typename Action>
690   bool WriteActionMessage(ActionType type, const Action& action,
691                           buzz::XmlElement* stanza, WriteError* error);
692   template <typename Action>
693   bool WriteActionMessage(SignalingProtocol protocol,
694                           ActionType type, const Action& action,
695                           buzz::XmlElement* stanza, WriteError* error);
696 
697   // Sending messages in hybrid form requires being able to write them
698   // on a per-protocol basis with a common method signature, which all
699   // of these have.
700   bool WriteSessionAction(SignalingProtocol protocol,
701                           const SessionInitiate& init,
702                           XmlElements* elems, WriteError* error);
703   bool WriteSessionAction(SignalingProtocol protocol,
704                           const TransportInfo& tinfo,
705                           XmlElements* elems, WriteError* error);
706   bool WriteSessionAction(SignalingProtocol protocol,
707                           const SessionTerminate& term,
708                           XmlElements* elems, WriteError* error);
709 
710   // Sends a message back to the other client indicating that we have received
711   // and accepted their message.
712   void SendAcknowledgementMessage(const buzz::XmlElement* stanza);
713 
714   // Once signaling is ready, the session will use this signal to request the
715   // sending of each message.  When messages are received by the other client,
716   // they should be handed to OnIncomingMessage.
717   // (These are called only by SessionManager.)
718   sigslot::signal2<Session* , const buzz::XmlElement*> SignalOutgoingMessage;
719   void OnIncomingMessage(const SessionMessage& msg);
720 
721   void OnIncomingResponse(const buzz::XmlElement* orig_stanza,
722                           const buzz::XmlElement* response_stanza,
723                           const SessionMessage& msg);
724   void OnInitiateAcked();
725   void OnFailedSend(const buzz::XmlElement* orig_stanza,
726                     const buzz::XmlElement* error_stanza);
727 
728   // Invoked when an error is found in an incoming message.  This is translated
729   // into the appropriate XMPP response by SessionManager.
730   sigslot::signal6<BaseSession*,
731                    const buzz::XmlElement*,
732                    const buzz::QName&,
733                    const std::string&,
734                    const std::string&,
735                    const buzz::XmlElement*> SignalErrorMessage;
736 
737   // Handlers for the various types of messages.  These functions may take
738   // pointers to the whole stanza or to just the session element.
739   bool OnInitiateMessage(const SessionMessage& msg, MessageError* error);
740   bool OnAcceptMessage(const SessionMessage& msg, MessageError* error);
741   bool OnRejectMessage(const SessionMessage& msg, MessageError* error);
742   bool OnInfoMessage(const SessionMessage& msg);
743   bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
744   bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
745   bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
746   bool OnDescriptionInfoMessage(const SessionMessage& msg, MessageError* error);
747   bool OnRedirectError(const SessionRedirect& redirect, SessionError* error);
748 
749   // Verifies that we are in the appropriate state to receive this message.
750   bool CheckState(State state, MessageError* error);
751 
752   SessionManager* session_manager_;
753   bool initiate_acked_;
754   std::string local_name_;
755   std::string initiator_name_;
756   std::string remote_name_;
757   SessionClient* client_;
758   TransportParser* transport_parser_;
759   // Keeps track of what protocol we are speaking.
760   SignalingProtocol current_protocol_;
761 
762   friend class SessionManager;  // For access to constructor, destructor,
763                                 // and signaling related methods.
764 };
765 
766 }  // namespace cricket
767 
768 #endif  // TALK_P2P_BASE_SESSION_H_
769