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 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. OnTransportError(const buzz::XmlElement * error)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. allow_local_ips()198 bool allow_local_ips() const { return allow_local_ips_; } set_allow_local_ips(bool value)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. OnTransportSignalingReady()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