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 
58 namespace talk_base {
59 class Thread;
60 }
61 
62 namespace buzz {
63 class QName;
64 class XmlElement;
65 }
66 
67 namespace cricket {
68 
69 struct ParseError;
70 struct WriteError;
71 class PortAllocator;
72 class SessionManager;
73 class Session;
74 class TransportChannel;
75 class TransportChannelImpl;
76 
77 typedef std::vector<buzz::XmlElement*> XmlElements;
78 typedef 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.
84 class 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 
~TransportParser()104   virtual ~TransportParser() {}
105 };
106 
107 class 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.
signaling_thread()117   talk_base::Thread* signaling_thread() { return signaling_thread_; }
118   // Returns the worker thread. The actual networking is done on this thread.
worker_thread()119   talk_base::Thread* worker_thread() { return worker_thread_; }
120 
121   // Returns the type of this transport.
type()122   const std::string& type() const { return type_; }
123 
124   // Returns the port allocator object for this transport.
port_allocator()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.
readable()130   bool readable() const { return readable_; }
writable()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.
connect_requested()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.
HasChannel(const std::string & name)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 
175   sigslot::signal1<Transport*> SignalCandidatesAllocationDone;
176   void OnRemoteCandidates(const std::vector<Candidate>& candidates);
177 
178   // If candidate is not acceptable, returns false and sets error.
179   // Call this before calling OnRemoteCandidates.
180   virtual bool VerifyCandidate(const Candidate& candidate,
181                                ParseError* error);
182 
183   // Signals when the best connection for a channel changes.
184   sigslot::signal3<Transport*, const std::string&,
185                    const Candidate&> SignalRouteChange;
186 
187   // A transport message has generated an transport-specific error.  The
188   // stanza that caused the error is available in session_msg.  If false is
189   // returned, the error is considered unrecoverable, and the session is
190   // terminated.
191   // TODO: Make OnTransportError take an abstract data type
192   // rather than an XmlElement.  It isn't needed yet, but it might be
193   // later for Jingle compliance.
OnTransportError(const buzz::XmlElement * error)194   virtual void OnTransportError(const buzz::XmlElement* error) {}
195   sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&,
196                    const std::string&, const std::string&,
197                    const buzz::XmlElement*>
198       SignalTransportError;
199 
200   sigslot::signal2<Transport*, const std::string&> SignalChannelGone;
201 
202   // (For testing purposes only.)  This indicates whether we will allow local
203   // IPs (e.g. 127.*) to be used as addresses for P2P.
allow_local_ips()204   bool allow_local_ips() const { return allow_local_ips_; }
set_allow_local_ips(bool value)205   void set_allow_local_ips(bool value) { allow_local_ips_ = value; }
206 
207  protected:
208   // These are called by Create/DestroyChannel above in order to create or
209   // destroy the appropriate type of channel.
210   virtual TransportChannelImpl* CreateTransportChannel(
211       const std::string& name, const std::string &content_type) = 0;
212   virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0;
213 
214   // Informs the subclass that we received the signaling ready message.
OnTransportSignalingReady()215   virtual void OnTransportSignalingReady() {}
216 
217  private:
218   struct ChannelMapEntry {
ChannelMapEntryChannelMapEntry219     ChannelMapEntry() : impl_(NULL), candidates_allocated_(false), ref_(0) {}
ChannelMapEntryChannelMapEntry220     explicit ChannelMapEntry(TransportChannelImpl *impl)
221         : impl_(impl),
222           candidates_allocated_(false),
223           ref_(0) {
224     }
225 
AddRefChannelMapEntry226     void AddRef() { ++ref_; }
DecRefChannelMapEntry227     void DecRef() {
228       ASSERT(ref_ > 0);
229       --ref_;
230     }
refChannelMapEntry231     int ref() const { return ref_; }
232 
getChannelMapEntry233     TransportChannelImpl* get() const { return impl_; }
set_candidates_allocatedChannelMapEntry234     void set_candidates_allocated(bool status) {
235       candidates_allocated_ = status;
236     }
candidates_allocatedChannelMapEntry237     bool candidates_allocated() const { return candidates_allocated_; }
238 
239   private:
240     TransportChannelImpl *impl_;
241     bool candidates_allocated_;
242     int ref_;
243   };
244 
245   typedef std::map<std::string, ChannelMapEntry> ChannelMap;
246 
247   // Called when the state of a channel changes.
248   void OnChannelReadableState(TransportChannel* channel);
249   void OnChannelWritableState(TransportChannel* channel);
250 
251   // Called when a channel requests signaling.
252   void OnChannelRequestSignaling(TransportChannelImpl* channel);
253 
254   // Called when a candidate is ready from remote peer.
255   void OnRemoteCandidate(const Candidate& candidate);
256   // Called when a candidate is ready from channel.
257   void OnChannelCandidateReady(TransportChannelImpl* channel,
258                                const Candidate& candidate);
259   void OnChannelRouteChange(TransportChannel* channel,
260                             const Candidate& remote_candidate);
261   void OnChannelCandidatesAllocationDone(TransportChannelImpl* channel);
262 
263   // Dispatches messages to the appropriate handler (below).
264   void OnMessage(talk_base::Message* msg);
265 
266   // These are versions of the above methods that are called only on a
267   // particular thread (s = signaling, w = worker).  The above methods post or
268   // send a message to invoke this version.
269   TransportChannelImpl* CreateChannel_w(const std::string& name,
270                                         const std::string& content_type);
271   void DestroyChannel_w(const std::string& name);
272   void ConnectChannels_w();
273   void ResetChannels_w();
274   void DestroyAllChannels_w();
275   void OnRemoteCandidate_w(const Candidate& candidate);
276   void OnChannelReadableState_s();
277   void OnChannelWritableState_s();
278   void OnChannelRequestSignaling_s(const std::string& name);
279   void OnConnecting_s();
280   void OnChannelRouteChange_s(const std::string& name,
281                               const Candidate& remote_candidate);
282 
283   // Helper function that invokes the given function on every channel.
284   typedef void (TransportChannelImpl::* TransportChannelFunc)();
285   void CallChannels_w(TransportChannelFunc func);
286 
287   // Computes the OR of the channel's read or write state (argument picks).
288   bool GetTransportState_s(bool read);
289 
290   void OnChannelCandidateReady_s();
291 
292   talk_base::Thread* signaling_thread_;
293   talk_base::Thread* worker_thread_;
294   std::string type_;
295   PortAllocator* allocator_;
296   bool destroyed_;
297   bool readable_;
298   bool writable_;
299   bool connect_requested_;
300 
301   ChannelMap channels_;
302   // Buffers the ready_candidates so that SignalCanidatesReady can
303   // provide them in multiples.
304   std::vector<Candidate> ready_candidates_;
305   // Protects changes to channels and messages
306   talk_base::CriticalSection crit_;
307   bool allow_local_ips_;
308 
309   DISALLOW_EVIL_CONSTRUCTORS(Transport);
310 };
311 
312 }  // namespace cricket
313 
314 #endif  // TALK_P2P_BASE_TRANSPORT_H_
315