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