1/*
2 * libjingle
3 * Copyright 2004--2008, 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 __TUNNELSESSIONCLIENT_H__
29#define __TUNNELSESSIONCLIENT_H__
30
31#include <vector>
32
33#include "talk/p2p/base/constants.h"
34#include "talk/p2p/base/pseudotcp.h"
35#include "talk/p2p/base/session.h"
36#include "talk/p2p/base/sessionclient.h"
37#include "talk/p2p/base/sessiondescription.h"
38#include "talk/p2p/base/sessionmanager.h"
39#include "webrtc/libjingle/xmllite/qname.h"
40#include "talk/xmpp/constants.h"
41#include "webrtc/base/criticalsection.h"
42#include "webrtc/base/stream.h"
43
44namespace cricket {
45
46class TunnelSession;
47class TunnelStream;
48
49enum TunnelSessionRole { INITIATOR, RESPONDER };
50
51///////////////////////////////////////////////////////////////////////////////
52// TunnelSessionClient
53///////////////////////////////////////////////////////////////////////////////
54
55// Base class is still abstract
56class TunnelSessionClientBase
57  : public SessionClient, public rtc::MessageHandler {
58public:
59  TunnelSessionClientBase(const buzz::Jid& jid, SessionManager* manager,
60                          const std::string &ns);
61  virtual ~TunnelSessionClientBase();
62
63  const buzz::Jid& jid() const { return jid_; }
64  SessionManager* session_manager() const { return session_manager_; }
65
66  void OnSessionCreate(Session* session, bool received);
67  void OnSessionDestroy(Session* session);
68
69  // This can be called on any thread.  The stream interface is
70  // thread-safe, but notifications must be registered on the creating
71  // thread.
72  rtc::StreamInterface* CreateTunnel(const buzz::Jid& to,
73                                           const std::string& description);
74
75  rtc::StreamInterface* AcceptTunnel(Session* session);
76  void DeclineTunnel(Session* session);
77
78  // Invoked on an incoming tunnel
79  virtual void OnIncomingTunnel(const buzz::Jid &jid, Session *session) = 0;
80
81  // Invoked on an outgoing session request
82  virtual SessionDescription* CreateOffer(
83      const buzz::Jid &jid, const std::string &description) = 0;
84  // Invoked on a session request accept to create
85  // the local-side session description
86  virtual SessionDescription* CreateAnswer(
87      const SessionDescription* offer) = 0;
88
89protected:
90
91  void OnMessage(rtc::Message* pmsg);
92
93  // helper method to instantiate TunnelSession. By overriding this,
94  // subclasses of TunnelSessionClient are able to instantiate
95  // subclasses of TunnelSession instead.
96  virtual TunnelSession* MakeTunnelSession(Session* session,
97                                           rtc::Thread* stream_thread,
98                                           TunnelSessionRole role);
99
100  buzz::Jid jid_;
101  SessionManager* session_manager_;
102  std::vector<TunnelSession*> sessions_;
103  std::string namespace_;
104  bool shutdown_;
105};
106
107class TunnelSessionClient
108  : public TunnelSessionClientBase, public sigslot::has_slots<>  {
109public:
110  TunnelSessionClient(const buzz::Jid& jid, SessionManager* manager);
111  TunnelSessionClient(const buzz::Jid& jid, SessionManager* manager,
112                      const std::string &ns);
113  virtual ~TunnelSessionClient();
114
115  virtual bool ParseContent(SignalingProtocol protocol,
116                            const buzz::XmlElement* elem,
117                            ContentDescription** content,
118                            ParseError* error);
119  virtual bool WriteContent(SignalingProtocol protocol,
120                            const ContentDescription* content,
121                            buzz::XmlElement** elem,
122                            WriteError* error);
123
124  // Signal arguments are this, initiator, description, session
125  sigslot::signal4<TunnelSessionClient*, buzz::Jid, std::string, Session*>
126    SignalIncomingTunnel;
127
128  virtual void OnIncomingTunnel(const buzz::Jid &jid,
129                                Session *session);
130  virtual SessionDescription* CreateOffer(
131      const buzz::Jid &jid, const std::string &description);
132  virtual SessionDescription* CreateAnswer(
133      const SessionDescription* offer);
134};
135
136///////////////////////////////////////////////////////////////////////////////
137// TunnelSession
138// Note: The lifetime of TunnelSession is complicated.  It needs to survive
139// until the following three conditions are true:
140// 1) TunnelStream has called Close (tracked via non-null stream_)
141// 2) PseudoTcp has completed (tracked via non-null tcp_)
142// 3) Session has been destroyed (tracked via non-null session_)
143// This is accomplished by calling CheckDestroy after these indicators change.
144///////////////////////////////////////////////////////////////////////////////
145///////////////////////////////////////////////////////////////////////////////
146// TunnelStream
147// Note: Because TunnelStream provides a stream interface, its lifetime is
148// controlled by the owner of the stream pointer.  As a result, we must support
149// both the TunnelSession disappearing before TunnelStream, and vice versa.
150///////////////////////////////////////////////////////////////////////////////
151
152class PseudoTcpChannel;
153
154class TunnelSession : public sigslot::has_slots<> {
155 public:
156  // Signalling thread methods
157  TunnelSession(TunnelSessionClientBase* client, Session* session,
158                rtc::Thread* stream_thread);
159
160  virtual rtc::StreamInterface* GetStream();
161  bool HasSession(Session* session);
162  Session* ReleaseSession(bool channel_exists);
163
164 protected:
165  virtual ~TunnelSession();
166
167  virtual void OnSessionState(BaseSession* session, BaseSession::State state);
168  virtual void OnInitiate();
169  virtual void OnAccept();
170  virtual void OnTerminate();
171  virtual void OnChannelClosed(PseudoTcpChannel* channel);
172
173  TunnelSessionClientBase* client_;
174  Session* session_;
175  PseudoTcpChannel* channel_;
176};
177
178///////////////////////////////////////////////////////////////////////////////
179
180} // namespace cricket
181
182#endif // __TUNNELSESSIONCLIENT_H__
183