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