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/p2p/base/sessionmessages.h"
37#include "talk/p2p/base/sessionmanager.h"
38#include "talk/base/socketaddress.h"
39#include "talk/p2p/base/sessionclient.h"
40#include "talk/p2p/base/parsing.h"
41#include "talk/p2p/base/port.h"
42#include "talk/xmllite/xmlelement.h"
43#include "talk/xmpp/constants.h"
44
45namespace cricket {
46
47class P2PTransportChannel;
48class Transport;
49class TransportChannel;
50class TransportChannelProxy;
51class TransportChannelImpl;
52
53// Used for errors that will send back a specific error message to the
54// remote peer.  We add "type" to the errors because it's needed for
55// SignalErrorMessage.
56struct MessageError : ParseError {
57  buzz::QName type;
58
59  // if unset, assume type is a parse error
60  MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {}
61
62  void SetType(const buzz::QName type) {
63    this->type = type;
64  }
65};
66
67// Used for errors that may be returned by public session methods that
68// can fail.
69// TODO: Use this error in Session::Initiate and
70// Session::Accept.
71struct SessionError : WriteError {
72};
73
74// Bundles a Transport and ChannelMap together. ChannelMap is used to
75// create transport channels before receiving or sending a session
76// initiate, and for speculatively connecting channels.  Previously, a
77// session had one ChannelMap and transport.  Now, with multiple
78// transports per session, we need multiple ChannelMaps as well.
79class TransportProxy {
80 public:
81  TransportProxy(const std::string& content_name, Transport* transport)
82      : content_name_(content_name),
83        transport_(transport),
84        state_(STATE_INIT),
85        sent_candidates_(false) {}
86  ~TransportProxy();
87
88  std::string content_name() const { return content_name_; }
89  Transport* impl() const { return transport_; }
90  std::string type() const;
91  bool negotiated() const { return state_ == STATE_NEGOTIATED; }
92  const Candidates& sent_candidates() const { return sent_candidates_; }
93
94  TransportChannel* GetChannel(const std::string& name);
95  TransportChannel* CreateChannel(const std::string& name,
96                                  const std::string& content_type);
97  void DestroyChannel(const std::string& name);
98  void AddSentCandidates(const Candidates& candidates);
99  void ClearSentCandidates() { sent_candidates_.clear(); }
100  void SpeculativelyConnectChannels();
101  void CompleteNegotiation();
102
103 private:
104  enum TransportState {
105    STATE_INIT,
106    STATE_CONNECTING,
107    STATE_NEGOTIATED
108  };
109
110  typedef std::map<std::string, TransportChannelProxy*> ChannelMap;
111
112  TransportChannelProxy* GetProxy(const std::string& name);
113  TransportChannelImpl* GetOrCreateImpl(const std::string& name,
114                                        const std::string& content_type);
115  void SetProxyImpl(const std::string& name, TransportChannelProxy* proxy);
116
117  std::string content_name_;
118  Transport* transport_;
119  TransportState state_;
120  ChannelMap channels_;
121  Candidates sent_candidates_;
122};
123
124typedef std::map<std::string, TransportProxy*> TransportMap;
125
126// TODO: Consider simplifying the dependency from Voice/VideoChannel
127// on Session. Right now the Channel class requires a BaseSession, but it only
128// uses CreateChannel/DestroyChannel. Perhaps something like a
129// TransportChannelFactory could be hoisted up out of BaseSession, or maybe
130// the transports could be passed in directly.
131
132// A BaseSession manages general session state. This includes negotiation
133// of both the application-level and network-level protocols:  the former
134// defines what will be sent and the latter defines how it will be sent.  Each
135// network-level protocol is represented by a Transport object.  Each Transport
136// participates in the network-level negotiation.  The individual streams of
137// packets are represented by TransportChannels.  The application-level protocol
138// is represented by SessionDecription objects.
139class BaseSession : public sigslot::has_slots<>,
140                    public talk_base::MessageHandler {
141 public:
142  enum State {
143    STATE_INIT = 0,
144    STATE_SENTINITIATE,       // sent initiate, waiting for Accept or Reject
145    STATE_RECEIVEDINITIATE,   // received an initiate. Call Accept or Reject
146    STATE_SENTACCEPT,         // sent accept. begin connecting transport
147    STATE_RECEIVEDACCEPT,     // received accept. begin connecting transport
148    STATE_SENTMODIFY,         // sent modify, waiting for Accept or Reject
149    STATE_RECEIVEDMODIFY,     // received modify, call Accept or Reject
150    STATE_SENTREJECT,         // sent reject after receiving initiate
151    STATE_RECEIVEDREJECT,     // received reject after sending initiate
152    STATE_SENTREDIRECT,       // sent direct after receiving initiate
153    STATE_SENTTERMINATE,      // sent terminate (any time / either side)
154    STATE_RECEIVEDTERMINATE,  // received terminate (any time / either side)
155    STATE_INPROGRESS,         // session accepted and in progress
156    STATE_DEINIT,             // session is being destroyed
157  };
158
159  enum Error {
160    ERROR_NONE = 0,      // no error
161    ERROR_TIME = 1,      // no response to signaling
162    ERROR_RESPONSE = 2,  // error during signaling
163    ERROR_NETWORK = 3,   // network error, could not allocate network resources
164    ERROR_CONTENT = 4,   // channel errors in SetLocalContent/SetRemoteContent
165  };
166
167  explicit BaseSession(talk_base::Thread *signaling_thread);
168  virtual ~BaseSession();
169
170  // Updates the state, signaling if necessary.
171  void SetState(State state);
172
173  // Updates the error state, signaling if necessary.
174  virtual void SetError(Error error);
175
176  // Handles messages posted to us.
177  virtual void OnMessage(talk_base::Message *pmsg);
178
179  // Returns the current state of the session.  See the enum above for details.
180  // Each time the state changes, we will fire this signal.
181  State state() const { return state_; }
182  sigslot::signal2<BaseSession *, State> SignalState;
183
184  // Returns the last error in the session.  See the enum above for details.
185  // Each time the an error occurs, we will fire this signal.
186  Error error() const { return error_; }
187  sigslot::signal2<BaseSession *, Error> SignalError;
188
189  // Creates a new channel with the given names.  This method may be called
190  // immediately after creating the session.  However, the actual
191  // implementation may not be fixed until transport negotiation completes.
192  // This will usually be called from the worker thread, but that
193  // shouldn't be an issue since the main thread will be blocked in
194  // Send when doing so.
195  virtual TransportChannel* CreateChannel(const std::string& content_name,
196                                          const std::string& channel_name) = 0;
197
198  // Returns the channel with the given names.
199  virtual TransportChannel* GetChannel(const std::string& content_name,
200                                       const std::string& channel_name) = 0;
201
202  // Destroys the channel with the given names.
203  // This will usually be called from the worker thread, but that
204  // shouldn't be an issue since the main thread will be blocked in
205  // Send when doing so.
206  virtual void DestroyChannel(const std::string& content_name,
207                              const std::string& channel_name) = 0;
208
209  // Invoked when we notice that there is no matching channel on our peer.
210  sigslot::signal2<Session*, const std::string&> SignalChannelGone;
211
212  // Returns the application-level description given by our client.
213  // If we are the recipient, this will be NULL until we send an accept.
214  const SessionDescription* local_description() const {
215    return local_description_;
216  }
217  // Takes ownership of SessionDescription*
218  bool set_local_description(const SessionDescription* sdesc) {
219    if (sdesc != local_description_) {
220      delete local_description_;
221      local_description_ = sdesc;
222    }
223    return true;
224  }
225
226  // Returns the application-level description given by the other client.
227  // If we are the initiator, this will be NULL until we receive an accept.
228  const SessionDescription* remote_description() const {
229    return remote_description_;
230  }
231  // Takes ownership of SessionDescription*
232  bool set_remote_description(const SessionDescription* sdesc) {
233    if (sdesc != remote_description_) {
234      delete remote_description_;
235      remote_description_ = sdesc;
236    }
237    return true;
238  }
239
240  // When we receive an initiate, we create a session in the
241  // RECEIVEDINITIATE state and respond by accepting or rejecting.
242  // Takes ownership of session description.
243  virtual bool Accept(const SessionDescription* sdesc) = 0;
244  virtual bool Reject(const std::string& reason) = 0;
245  bool Terminate() {
246    return TerminateWithReason(STR_TERMINATE_SUCCESS);
247  }
248  virtual bool TerminateWithReason(const std::string& reason) = 0;
249
250  // The worker thread used by the session manager
251  virtual talk_base::Thread *worker_thread() = 0;
252
253  talk_base::Thread *signaling_thread() {
254    return signaling_thread_;
255  }
256
257  // Returns the JID of this client.
258  const std::string& local_name() const { return local_name_; }
259
260  // Returns the JID of the other peer in this session.
261  const std::string& remote_name() const { return remote_name_; }
262
263  // Set the JID of the other peer in this session.
264  // Typically the remote_name_ is set when the session is initiated.
265  // However, sometimes (e.g when a proxy is used) the peer name is
266  // known after the BaseSession has been initiated and it must be updated
267  // explicitly.
268  void set_remote_name(const std::string& name) { remote_name_ = name; }
269
270  const std::string& id() const { return sid_; }
271
272 protected:
273  State state_;
274  Error error_;
275  const SessionDescription* local_description_;
276  const SessionDescription* remote_description_;
277  std::string sid_;
278  // We don't use buzz::Jid because changing to buzz:Jid here has a
279  // cascading effect that requires an enormous number places to
280  // change to buzz::Jid as well.
281  std::string local_name_;
282  std::string remote_name_;
283  talk_base::Thread *signaling_thread_;
284};
285
286// A specific Session created by the SessionManager, using XMPP for protocol.
287class Session : public BaseSession {
288 public:
289  // Returns the manager that created and owns this session.
290  SessionManager* session_manager() const { return session_manager_; }
291
292  // the worker thread used by the session manager
293  talk_base::Thread *worker_thread() {
294    return session_manager_->worker_thread();
295  }
296
297  // Returns the XML namespace identifying the type of this session.
298  const std::string& content_type() const { return content_type_; }
299
300  // Returns the client that is handling the application data of this session.
301  SessionClient* client() const { return client_; }
302
303  SignalingProtocol current_protocol() const { return current_protocol_; }
304
305  void set_current_protocol(SignalingProtocol protocol) {
306    current_protocol_ = protocol;
307  }
308
309  // Indicates whether we initiated this session.
310  bool initiator() const { return initiator_; }
311
312  const SessionDescription* initiator_description() const {
313    if (initiator_) {
314      return local_description_;
315    } else {
316      return remote_description_;
317    }
318  }
319
320  // Fired whenever we receive a terminate message along with a reason
321  sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason;
322
323  void set_allow_local_ips(bool allow);
324
325  // Returns the transport that has been negotiated or NULL if
326  // negotiation is still in progress.
327  Transport* GetTransport(const std::string& content_name);
328
329  // Takes ownership of session description.
330  // TODO: Add an error argument to pass back to the caller.
331  bool Initiate(const std::string& to,
332                const SessionDescription* sdesc);
333
334  // When we receive an initiate, we create a session in the
335  // RECEIVEDINITIATE state and respond by accepting or rejecting.
336  // Takes ownership of session description.
337  // TODO: Add an error argument to pass back to the caller.
338  virtual bool Accept(const SessionDescription* sdesc);
339  virtual bool Reject(const std::string& reason);
340  virtual bool TerminateWithReason(const std::string& reason);
341
342  // The two clients in the session may also send one another arbitrary XML
343  // messages, which are called "info" messages.  Both of these functions take
344  // ownership of the XmlElements and delete them when done.
345  bool SendInfoMessage(const XmlElements& elems);
346  sigslot::signal2<Session*, const XmlElements&> SignalInfoMessage;
347
348  // Maps passed to serialization functions.
349  TransportParserMap GetTransportParsers();
350  ContentParserMap GetContentParsers();
351
352  // Creates a new channel with the given names.  This method may be called
353  // immediately after creating the session.  However, the actual
354  // implementation may not be fixed until transport negotiation completes.
355  virtual TransportChannel* CreateChannel(const std::string& content_name,
356                                          const std::string& channel_name);
357
358  // Returns the channel with the given names.
359  virtual TransportChannel* GetChannel(const std::string& content_name,
360                                       const std::string& channel_name);
361
362  // Destroys the channel with the given names.
363  virtual void DestroyChannel(const std::string& content_name,
364                              const std::string& channel_name);
365
366  // Updates the error state, signaling if necessary.
367  virtual void SetError(Error error);
368
369  // Handles messages posted to us.
370  virtual void OnMessage(talk_base::Message *pmsg);
371
372  // Fired when notification of media sources is received from the server.
373  // Passes a map whose keys are strings containing nick names for users
374  // in the session and whose values contain the SSRCs for each user.
375  sigslot::signal1<const StringToMediaSourcesMap&> SignalMediaSources;
376
377  // Sets the video streams to receive from the server.
378  bool SetVideoView(const VideoViewRequestVector& view_requests);
379
380 private:
381  // Creates or destroys a session.  (These are called only SessionManager.)
382  Session(SessionManager *session_manager,
383          const std::string& local_name, const std::string& initiator_name,
384          const std::string& sid, const std::string& content_type,
385          SessionClient* client);
386  ~Session();
387
388  // Get a TransportProxy by content_name or transport. NULL if not found.
389  TransportProxy* GetTransportProxy(const std::string& content_name);
390  TransportProxy* GetTransportProxy(const Transport* transport);
391  TransportProxy* GetFirstTransportProxy();
392  // TransportProxy is owned by session.  Return proxy just for convenience.
393  TransportProxy* GetOrCreateTransportProxy(const std::string& content_name);
394  // For each transport info, create a transport proxy.  Can fail for
395  // incompatible transport types.
396  bool CreateTransportProxies(const TransportInfos& tinfos,
397                              SessionError* error);
398  void SpeculativelyConnectAllTransportChannels();
399  bool OnRemoteCandidates(const TransportInfos& tinfos,
400                          ParseError* error);
401  // Returns a TransportInfo without candidates for each content name.
402  // Uses the transport_type_ of the session.
403  TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
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  void OnTransportConnecting(Transport* transport);
409
410  // Called when a transport changes its writable state.  We track this to make
411  // sure that the transport becomes writable within a reasonable amount of
412  // time.  If this does not occur, we signal an error.
413  void OnTransportWritable(Transport* transport);
414
415  // Called when a transport requests signaling.
416  void OnTransportRequestSignaling(Transport* transport);
417
418  // Called when a transport signals that it has a message to send.   Note that
419  // these messages are just the transport part of the stanza; they need to be
420  // wrapped in the appropriate session tags.
421  void OnTransportCandidatesReady(Transport* transport,
422                                  const Candidates& candidates);
423
424  // Called when a transport signals that it found an error in an incoming
425  // message.
426  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  // Called when we notice that one of our local channels has no peer, so it
434  // should be destroyed.
435  void OnTransportChannelGone(Transport* transport, const std::string& name);
436
437  // When the session needs to send signaling messages, it beings by requesting
438  // signaling.  The client should handle this by calling OnSignalingReady once
439  // it is ready to send the messages.
440  // (These are called only by SessionManager.)
441  sigslot::signal1<Session*> SignalRequestSignaling;
442  void OnSignalingReady();
443
444  // Send various kinds of session messages.
445  bool SendInitiateMessage(const SessionDescription* sdesc,
446                           SessionError* error);
447  bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error);
448  bool SendRejectMessage(const std::string& reason, SessionError* error);
449  bool SendTerminateMessage(const std::string& reason, SessionError* error);
450  bool SendTransportInfoMessage(const TransportInfo& tinfo,
451                                SessionError* error);
452  bool SendViewMessage(const SessionView& view, SessionError* error);
453  bool ResendAllTransportInfoMessages(SessionError* error);
454
455  // Both versions of SendMessage send a message of the given type to
456  // the other client.  Can pass either a set of elements or an
457  // "action", which must have a WriteSessionAction method to go along
458  // with it.  Sending with an action supports sending a "hybrid"
459  // message.  Sending with elements must be sent as Jingle or Gingle.
460
461  // When passing elems, must be either Jingle or Gingle protocol.
462  // Takes ownership of action_elems.
463  bool SendMessage(ActionType type, const XmlElements& action_elems,
464                   SessionError* error);
465  // When passing an action, may be Hybrid protocol.
466  template <typename Action>
467  bool SendMessage(ActionType type, const Action& action,
468                   SessionError* error);
469
470  // Helper methods to write the session message stanza.
471  template <typename Action>
472  bool WriteActionMessage(ActionType type, const Action& action,
473                          buzz::XmlElement* stanza, WriteError* error);
474  template <typename Action>
475  bool WriteActionMessage(SignalingProtocol protocol,
476                          ActionType type, const Action& action,
477                          buzz::XmlElement* stanza, WriteError* error);
478
479  // Sending messages in hybrid form requires being able to write them
480  // on a per-protocol basis with a common method signature, which all
481  // of these have.
482  bool WriteSessionAction(SignalingProtocol protocol,
483                          const SessionInitiate& init,
484                          XmlElements* elems, WriteError* error);
485  bool WriteSessionAction(SignalingProtocol protocol,
486                          const TransportInfo& tinfo,
487                          XmlElements* elems, WriteError* error);
488  bool WriteSessionAction(SignalingProtocol protocol,
489                          const SessionTerminate& term,
490                          XmlElements* elems, WriteError* error);
491
492  // Sends a message back to the other client indicating that we have received
493  // and accepted their message.
494  void SendAcknowledgementMessage(const buzz::XmlElement* stanza);
495
496  // Once signaling is ready, the session will use this signal to request the
497  // sending of each message.  When messages are received by the other client,
498  // they should be handed to OnIncomingMessage.
499  // (These are called only by SessionManager.)
500  sigslot::signal2<Session *, const buzz::XmlElement*> SignalOutgoingMessage;
501  void OnIncomingMessage(const SessionMessage& msg);
502
503  void OnFailedSend(const buzz::XmlElement* orig_stanza,
504                    const buzz::XmlElement* error_stanza);
505
506  // Invoked when an error is found in an incoming message.  This is translated
507  // into the appropriate XMPP response by SessionManager.
508  sigslot::signal6<BaseSession*,
509                   const buzz::XmlElement*,
510                   const buzz::QName&,
511                   const std::string&,
512                   const std::string&,
513                   const buzz::XmlElement*> SignalErrorMessage;
514
515  // Handlers for the various types of messages.  These functions may take
516  // pointers to the whole stanza or to just the session element.
517  bool OnInitiateMessage(const SessionMessage& msg, MessageError* error);
518  bool OnAcceptMessage(const SessionMessage& msg, MessageError* error);
519  bool OnRejectMessage(const SessionMessage& msg, MessageError* error);
520  bool OnInfoMessage(const SessionMessage& msg);
521  bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
522  bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
523  bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
524  bool OnNotifyMessage(const SessionMessage& msg, MessageError* error);
525  bool OnUpdateMessage(const SessionMessage& msg, MessageError* error);
526  bool OnRedirectError(const SessionRedirect& redirect, SessionError* error);
527
528  // Verifies that we are in the appropriate state to receive this message.
529  bool CheckState(State state, MessageError* error);
530
531  SessionManager *session_manager_;
532  bool initiator_;
533  std::string initiator_name_;
534  std::string content_type_;
535  SessionClient* client_;
536  std::string transport_type_;
537  TransportParser* transport_parser_;
538  // This is transport-specific but required so much by unit tests
539  // that it's much easier to put it here.
540  bool allow_local_ips_;
541  TransportMap transports_;
542  // Keeps track of what protocol we are speaking.
543  SignalingProtocol current_protocol_;
544
545  friend class SessionManager;  // For access to constructor, destructor,
546                                // and signaling related methods.
547};
548
549}  // namespace cricket
550
551#endif  // TALK_P2P_BASE_SESSION_H_
552