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// A Transport manages a set of named channels of the same type.
29//
30// Subclasses choose the appropriate class to instantiate for each channel;
31// however, this base class keeps track of the channels by name, watches their
32// state changes (in order to update the manager's state), and forwards
33// requests to begin connecting or to reset to each of the channels.
34//
35// On Threading:  Transport performs work on both the signaling and worker
36// threads.  For subclasses, the rule is that all signaling related calls will
37// be made on the signaling thread and all channel related calls (including
38// signaling for a channel) will be made on the worker thread.  When
39// information needs to be sent between the two threads, this class should do
40// the work (e.g., OnRemoteCandidate).
41//
42// Note: Subclasses must call DestroyChannels() in their own constructors.
43// It is not possible to do so here because the subclass constructor will
44// already have run.
45
46#ifndef TALK_P2P_BASE_TRANSPORT_H_
47#define TALK_P2P_BASE_TRANSPORT_H_
48
49#include <string>
50#include <map>
51#include <vector>
52#include "talk/base/criticalsection.h"
53#include "talk/base/messagequeue.h"
54#include "talk/base/sigslot.h"
55#include "talk/p2p/base/candidate.h"
56#include "talk/p2p/base/constants.h"
57
58namespace talk_base {
59class Thread;
60}
61
62namespace buzz {
63class QName;
64class XmlElement;
65}
66
67namespace cricket {
68
69struct ParseError;
70struct WriteError;
71class PortAllocator;
72class SessionManager;
73class Session;
74class TransportChannel;
75class TransportChannelImpl;
76
77typedef std::vector<buzz::XmlElement*> XmlElements;
78typedef std::vector<Candidate> Candidates;
79
80// Used to parse and serialize (write) transport candidates.  For
81// convenience of old code, Transports will implement TransportParser.
82// Parse/Write seems better than Serialize/Deserialize or
83// Create/Translate.
84class TransportParser {
85 public:
86  virtual bool ParseCandidates(SignalingProtocol protocol,
87                               const buzz::XmlElement* elem,
88                               Candidates* candidates,
89                               ParseError* error) = 0;
90  virtual bool WriteCandidates(SignalingProtocol protocol,
91                               const Candidates& candidates,
92                               XmlElements* candidate_elems,
93                               WriteError* error) = 0;
94
95  // Helper function to parse an element describing an address.  This
96  // retrieves the IP and port from the given element and verifies
97  // that they look like plausible values.
98  bool ParseAddress(const buzz::XmlElement* elem,
99                    const buzz::QName& address_name,
100                    const buzz::QName& port_name,
101                    talk_base::SocketAddress* address,
102                    ParseError* error);
103
104  virtual ~TransportParser() {}
105};
106
107class Transport : public talk_base::MessageHandler,
108                  public sigslot::has_slots<> {
109 public:
110  Transport(talk_base::Thread* signaling_thread,
111            talk_base::Thread* worker_thread,
112            const std::string& type,
113            PortAllocator* allocator);
114  virtual ~Transport();
115
116  // Returns the signaling thread. The app talks to Transport on this thread.
117  talk_base::Thread* signaling_thread() { return signaling_thread_; }
118  // Returns the worker thread. The actual networking is done on this thread.
119  talk_base::Thread* worker_thread() { return worker_thread_; }
120
121  // Returns the type of this transport.
122  const std::string& type() const { return type_; }
123
124  // Returns the port allocator object for this transport.
125  PortAllocator* port_allocator() { return allocator_; }
126
127  // Returns the readable and states of this manager.  These bits are the ORs
128  // of the corresponding bits on the managed channels.  Each time one of these
129  // states changes, a signal is raised.
130  bool readable() const { return readable_; }
131  bool writable() const { return writable_; }
132  sigslot::signal1<Transport*> SignalReadableState;
133  sigslot::signal1<Transport*> SignalWritableState;
134
135  // Returns whether the client has requested the channels to connect.
136  bool connect_requested() const { return connect_requested_; }
137
138  // Create, destroy, and lookup the channels of this type by their names.
139  TransportChannelImpl* CreateChannel(const std::string& name,
140                                      const std::string& content_type);
141  // Note: GetChannel may lead to race conditions, since the mutex is not held
142  // after the pointer is returned.
143  TransportChannelImpl* GetChannel(const std::string& name);
144  // Note: HasChannel does not lead to race conditions, unlike GetChannel.
145  bool HasChannel(const std::string& name) {
146    return (NULL != GetChannel(name));
147  }
148  bool HasChannels();
149  void DestroyChannel(const std::string& name);
150
151  // Tells all current and future channels to start connecting.  When the first
152  // channel begins connecting, the following signal is raised.
153  void ConnectChannels();
154  sigslot::signal1<Transport*> SignalConnecting;
155
156  // Resets all of the channels back to their initial state.  They are no
157  // longer connecting.
158  void ResetChannels();
159
160  // Destroys every channel created so far.
161  void DestroyAllChannels();
162
163  // Before any stanza is sent, the manager will request signaling.  Once
164  // signaling is available, the client should call OnSignalingReady.  Once
165  // this occurs, the transport (or its channels) can send any waiting stanzas.
166  // OnSignalingReady invokes OnTransportSignalingReady and then forwards this
167  // signal to each channel.
168  sigslot::signal1<Transport*> SignalRequestSignaling;
169  void OnSignalingReady();
170
171  // Handles sending of ready candidates and receiving of remote candidates.
172  sigslot::signal2<Transport*,
173                   const std::vector<Candidate>&> SignalCandidatesReady;
174  void OnRemoteCandidates(const std::vector<Candidate>& candidates);
175
176  // If candidate is not acceptable, returns false and sets error.
177  // Call this before calling OnRemoteCandidates.
178  virtual bool VerifyCandidate(const Candidate& candidate,
179                               ParseError* error);
180
181  // A transport message has generated an transport-specific error.  The
182  // stanza that caused the error is available in session_msg.  If false is
183  // returned, the error is considered unrecoverable, and the session is
184  // terminated.
185  // TODO: Make OnTransportError take an abstract data type
186  // rather than an XmlElement.  It isn't needed yet, but it might be
187  // later for Jingle compliance.
188  virtual void OnTransportError(const buzz::XmlElement* error) {}
189  sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&,
190                   const std::string&, const std::string&,
191                   const buzz::XmlElement*>
192      SignalTransportError;
193
194  sigslot::signal2<Transport*, const std::string&> SignalChannelGone;
195
196  // (For testing purposes only.)  This indicates whether we will allow local
197  // IPs (e.g. 127.*) to be used as addresses for P2P.
198  bool allow_local_ips() const { return allow_local_ips_; }
199  void set_allow_local_ips(bool value) { allow_local_ips_ = value; }
200
201 protected:
202  // These are called by Create/DestroyChannel above in order to create or
203  // destroy the appropriate type of channel.
204  virtual TransportChannelImpl* CreateTransportChannel(
205      const std::string& name, const std::string &content_type) = 0;
206  virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0;
207
208  // Informs the subclass that we received the signaling ready message.
209  virtual void OnTransportSignalingReady() {}
210
211 private:
212  typedef std::map<std::string, TransportChannelImpl*> ChannelMap;
213
214  // Called when the state of a channel changes.
215  void OnChannelReadableState(TransportChannel* channel);
216  void OnChannelWritableState(TransportChannel* channel);
217
218  // Called when a channel requests signaling.
219  void OnChannelRequestSignaling();
220
221  // Called when a candidate is ready from remote peer.
222  void OnRemoteCandidate(const Candidate& candidate);
223  // Called when a candidate is ready from channel.
224  void OnChannelCandidateReady(TransportChannelImpl* channel,
225                               const Candidate& candidate);
226
227  // Dispatches messages to the appropriate handler (below).
228  void OnMessage(talk_base::Message* msg);
229
230  // These are versions of the above methods that are called only on a
231  // particular thread (s = signaling, w = worker).  The above methods post or
232  // send a message to invoke this version.
233  TransportChannelImpl* CreateChannel_w(const std::string& name,
234                                        const std::string& content_type);
235  void DestroyChannel_w(const std::string& name);
236  void ConnectChannels_w();
237  void ResetChannels_w();
238  void DestroyAllChannels_w();
239  void OnRemoteCandidate_w(const Candidate& candidate);
240  void OnChannelReadableState_s();
241  void OnChannelWritableState_s();
242  void OnChannelRequestSignaling_s();
243  void OnConnecting_s();
244
245  // Helper function that invokes the given function on every channel.
246  typedef void (TransportChannelImpl::* TransportChannelFunc)();
247  void CallChannels_w(TransportChannelFunc func);
248
249  // Computes the OR of the channel's read or write state (argument picks).
250  bool GetTransportState_s(bool read);
251
252  void OnChannelCandidateReady_s();
253
254  talk_base::Thread* signaling_thread_;
255  talk_base::Thread* worker_thread_;
256  std::string type_;
257  PortAllocator* allocator_;
258  bool destroyed_;
259  bool readable_;
260  bool writable_;
261  bool connect_requested_;
262  ChannelMap channels_;
263  // Buffers the ready_candidates so that SignalCanidatesReady can
264  // provide them in multiples.
265  std::vector<Candidate> ready_candidates_;
266  // Protects changes to channels and messages
267  talk_base::CriticalSection crit_;
268  bool allow_local_ips_;
269
270  DISALLOW_EVIL_CONSTRUCTORS(Transport);
271};
272
273}  // namespace cricket
274
275#endif  // TALK_P2P_BASE_TRANSPORT_H_
276