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 #include "talk/p2p/base/sessiondescription.h" 58 #include "talk/p2p/base/transportinfo.h" 59 60 namespace talk_base { 61 class Thread; 62 } 63 64 namespace buzz { 65 class QName; 66 class XmlElement; 67 } 68 69 namespace cricket { 70 71 struct ParseError; 72 struct WriteError; 73 class CandidateTranslator; 74 class PortAllocator; 75 class SessionManager; 76 class Session; 77 class TransportChannel; 78 class TransportChannelImpl; 79 80 typedef std::vector<buzz::XmlElement*> XmlElements; 81 typedef std::vector<Candidate> Candidates; 82 83 // Used to parse and serialize (write) transport candidates. For 84 // convenience of old code, Transports will implement TransportParser. 85 // Parse/Write seems better than Serialize/Deserialize or 86 // Create/Translate. 87 class TransportParser { 88 public: 89 // The incoming Translator value may be null, in which case 90 // ParseCandidates should return false if there are candidates to 91 // parse (indicating a failure to parse). If the Translator is null 92 // and there are no candidates to parse, then return true, 93 // indicating a successful parse of 0 candidates. 94 95 // Parse or write a transport description, including ICE credentials and 96 // any DTLS fingerprint. Since only Jingle has transport descriptions, these 97 // functions are only used when serializing to Jingle. 98 virtual bool ParseTransportDescription(const buzz::XmlElement* elem, 99 const CandidateTranslator* translator, 100 TransportDescription* tdesc, 101 ParseError* error) = 0; 102 virtual bool WriteTransportDescription(const TransportDescription& tdesc, 103 const CandidateTranslator* translator, 104 buzz::XmlElement** tdesc_elem, 105 WriteError* error) = 0; 106 107 108 // Parse a single candidate. This must be used when parsing Gingle 109 // candidates, since there is no enclosing transport description. 110 virtual bool ParseGingleCandidate(const buzz::XmlElement* elem, 111 const CandidateTranslator* translator, 112 Candidate* candidates, 113 ParseError* error) = 0; 114 virtual bool WriteGingleCandidate(const Candidate& candidate, 115 const CandidateTranslator* translator, 116 buzz::XmlElement** candidate_elem, 117 WriteError* error) = 0; 118 119 // Helper function to parse an element describing an address. This 120 // retrieves the IP and port from the given element and verifies 121 // that they look like plausible values. 122 bool ParseAddress(const buzz::XmlElement* elem, 123 const buzz::QName& address_name, 124 const buzz::QName& port_name, 125 talk_base::SocketAddress* address, 126 ParseError* error); 127 128 virtual ~TransportParser() {} 129 }; 130 131 // For "writable" and "readable", we need to differentiate between 132 // none, all, and some. 133 enum TransportState { 134 TRANSPORT_STATE_NONE = 0, 135 TRANSPORT_STATE_SOME, 136 TRANSPORT_STATE_ALL 137 }; 138 139 // Stats that we can return about the connections for a transport channel. 140 // TODO(hta): Rename to ConnectionStats 141 struct ConnectionInfo { 142 ConnectionInfo() 143 : best_connection(false), 144 writable(false), 145 readable(false), 146 timeout(false), 147 new_connection(false), 148 rtt(0), 149 sent_total_bytes(0), 150 sent_bytes_second(0), 151 recv_total_bytes(0), 152 recv_bytes_second(0), 153 key(NULL) {} 154 155 bool best_connection; // Is this the best connection we have? 156 bool writable; // Has this connection received a STUN response? 157 bool readable; // Has this connection received a STUN request? 158 bool timeout; // Has this connection timed out? 159 bool new_connection; // Is this a newly created connection? 160 size_t rtt; // The STUN RTT for this connection. 161 size_t sent_total_bytes; // Total bytes sent on this connection. 162 size_t sent_bytes_second; // Bps over the last measurement interval. 163 size_t recv_total_bytes; // Total bytes received on this connection. 164 size_t recv_bytes_second; // Bps over the last measurement interval. 165 Candidate local_candidate; // The local candidate for this connection. 166 Candidate remote_candidate; // The remote candidate for this connection. 167 void* key; // A static value that identifies this conn. 168 }; 169 170 // Information about all the connections of a channel. 171 typedef std::vector<ConnectionInfo> ConnectionInfos; 172 173 // Information about a specific channel 174 struct TransportChannelStats { 175 int component; 176 ConnectionInfos connection_infos; 177 }; 178 179 // Information about all the channels of a transport. 180 // TODO(hta): Consider if a simple vector is as good as a map. 181 typedef std::vector<TransportChannelStats> TransportChannelStatsList; 182 183 // Information about the stats of a transport. 184 struct TransportStats { 185 std::string content_name; 186 TransportChannelStatsList channel_stats; 187 }; 188 189 class Transport : public talk_base::MessageHandler, 190 public sigslot::has_slots<> { 191 public: 192 Transport(talk_base::Thread* signaling_thread, 193 talk_base::Thread* worker_thread, 194 const std::string& content_name, 195 const std::string& type, 196 PortAllocator* allocator); 197 virtual ~Transport(); 198 199 // Returns the signaling thread. The app talks to Transport on this thread. 200 talk_base::Thread* signaling_thread() { return signaling_thread_; } 201 // Returns the worker thread. The actual networking is done on this thread. 202 talk_base::Thread* worker_thread() { return worker_thread_; } 203 204 // Returns the content_name of this transport. 205 const std::string& content_name() const { return content_name_; } 206 // Returns the type of this transport. 207 const std::string& type() const { return type_; } 208 209 // Returns the port allocator object for this transport. 210 PortAllocator* port_allocator() { return allocator_; } 211 212 // Returns the readable and states of this manager. These bits are the ORs 213 // of the corresponding bits on the managed channels. Each time one of these 214 // states changes, a signal is raised. 215 // TODO: Replace uses of readable() and writable() with 216 // any_channels_readable() and any_channels_writable(). 217 bool readable() const { return any_channels_readable(); } 218 bool writable() const { return any_channels_writable(); } 219 bool was_writable() const { return was_writable_; } 220 bool any_channels_readable() const { 221 return (readable_ == TRANSPORT_STATE_SOME || 222 readable_ == TRANSPORT_STATE_ALL); 223 } 224 bool any_channels_writable() const { 225 return (writable_ == TRANSPORT_STATE_SOME || 226 writable_ == TRANSPORT_STATE_ALL); 227 } 228 bool all_channels_readable() const { 229 return (readable_ == TRANSPORT_STATE_ALL); 230 } 231 bool all_channels_writable() const { 232 return (writable_ == TRANSPORT_STATE_ALL); 233 } 234 sigslot::signal1<Transport*> SignalReadableState; 235 sigslot::signal1<Transport*> SignalWritableState; 236 237 // Returns whether the client has requested the channels to connect. 238 bool connect_requested() const { return connect_requested_; } 239 240 void SetIceRole(IceRole role); 241 IceRole ice_role() const { return ice_role_; } 242 243 void SetIceTiebreaker(uint64 IceTiebreaker) { tiebreaker_ = IceTiebreaker; } 244 uint64 IceTiebreaker() { return tiebreaker_; } 245 246 // Must be called before applying local session description. 247 void SetIdentity(talk_base::SSLIdentity* identity); 248 249 TransportProtocol protocol() const { return protocol_; } 250 251 // Create, destroy, and lookup the channels of this type by their components. 252 TransportChannelImpl* CreateChannel(int component); 253 // Note: GetChannel may lead to race conditions, since the mutex is not held 254 // after the pointer is returned. 255 TransportChannelImpl* GetChannel(int component); 256 // Note: HasChannel does not lead to race conditions, unlike GetChannel. 257 bool HasChannel(int component) { 258 return (NULL != GetChannel(component)); 259 } 260 bool HasChannels(); 261 void DestroyChannel(int component); 262 263 // Set the local TransportDescription to be used by TransportChannels. 264 // This should be called before ConnectChannels(). 265 bool SetLocalTransportDescription(const TransportDescription& description, 266 ContentAction action); 267 268 // Set the remote TransportDescription to be used by TransportChannels. 269 bool SetRemoteTransportDescription(const TransportDescription& description, 270 ContentAction action); 271 272 // Tells all current and future channels to start connecting. When the first 273 // channel begins connecting, the following signal is raised. 274 void ConnectChannels(); 275 sigslot::signal1<Transport*> SignalConnecting; 276 277 // Resets all of the channels back to their initial state. They are no 278 // longer connecting. 279 void ResetChannels(); 280 281 // Destroys every channel created so far. 282 void DestroyAllChannels(); 283 284 bool GetStats(TransportStats* stats); 285 286 // Before any stanza is sent, the manager will request signaling. Once 287 // signaling is available, the client should call OnSignalingReady. Once 288 // this occurs, the transport (or its channels) can send any waiting stanzas. 289 // OnSignalingReady invokes OnTransportSignalingReady and then forwards this 290 // signal to each channel. 291 sigslot::signal1<Transport*> SignalRequestSignaling; 292 void OnSignalingReady(); 293 294 // Handles sending of ready candidates and receiving of remote candidates. 295 sigslot::signal2<Transport*, 296 const std::vector<Candidate>&> SignalCandidatesReady; 297 298 sigslot::signal1<Transport*> SignalCandidatesAllocationDone; 299 void OnRemoteCandidates(const std::vector<Candidate>& candidates); 300 301 // If candidate is not acceptable, returns false and sets error. 302 // Call this before calling OnRemoteCandidates. 303 virtual bool VerifyCandidate(const Candidate& candidate, 304 std::string* error); 305 306 // Signals when the best connection for a channel changes. 307 sigslot::signal3<Transport*, 308 int, // component 309 const Candidate&> SignalRouteChange; 310 311 // A transport message has generated an transport-specific error. The 312 // stanza that caused the error is available in session_msg. If false is 313 // returned, the error is considered unrecoverable, and the session is 314 // terminated. 315 // TODO(juberti): Remove these obsolete functions once Session no longer 316 // references them. 317 virtual void OnTransportError(const buzz::XmlElement* error) {} 318 sigslot::signal6<Transport*, const buzz::XmlElement*, const buzz::QName&, 319 const std::string&, const std::string&, 320 const buzz::XmlElement*> 321 SignalTransportError; 322 323 // Forwards the signal from TransportChannel to BaseSession. 324 sigslot::signal0<> SignalRoleConflict; 325 326 protected: 327 // These are called by Create/DestroyChannel above in order to create or 328 // destroy the appropriate type of channel. 329 virtual TransportChannelImpl* CreateTransportChannel(int component) = 0; 330 virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0; 331 332 // Informs the subclass that we received the signaling ready message. 333 virtual void OnTransportSignalingReady() {} 334 335 // The current local transport description, for use by derived classes 336 // when performing transport description negotiation. 337 const TransportDescription* local_description() const { 338 return local_description_.get(); 339 } 340 341 // The current remote transport description, for use by derived classes 342 // when performing transport description negotiation. 343 const TransportDescription* remote_description() const { 344 return remote_description_.get(); 345 } 346 347 virtual void SetIdentity_w(talk_base::SSLIdentity* identity) {} 348 349 // Pushes down the transport parameters from the local description, such 350 // as the ICE ufrag and pwd. 351 // Derived classes can override, but must call the base as well. 352 virtual bool ApplyLocalTransportDescription_w(TransportChannelImpl* 353 channel); 354 355 // Pushes down remote ice credentials from the remote description to the 356 // transport channel. 357 virtual bool ApplyRemoteTransportDescription_w(TransportChannelImpl* ch); 358 359 // Negotiates the transport parameters based on the current local and remote 360 // transport description, such at the version of ICE to use, and whether DTLS 361 // should be activated. 362 // Derived classes can negotiate their specific parameters here, but must call 363 // the base as well. 364 virtual bool NegotiateTransportDescription_w(ContentAction local_role); 365 366 // Pushes down the transport parameters obtained via negotiation. 367 // Derived classes can set their specific parameters here, but must call the 368 // base as well. 369 virtual void ApplyNegotiatedTransportDescription_w( 370 TransportChannelImpl* channel); 371 372 private: 373 struct ChannelMapEntry { 374 ChannelMapEntry() : impl_(NULL), candidates_allocated_(false), ref_(0) {} 375 explicit ChannelMapEntry(TransportChannelImpl *impl) 376 : impl_(impl), 377 candidates_allocated_(false), 378 ref_(0) { 379 } 380 381 void AddRef() { ++ref_; } 382 void DecRef() { 383 ASSERT(ref_ > 0); 384 --ref_; 385 } 386 int ref() const { return ref_; } 387 388 TransportChannelImpl* get() const { return impl_; } 389 TransportChannelImpl* operator->() const { return impl_; } 390 void set_candidates_allocated(bool status) { 391 candidates_allocated_ = status; 392 } 393 bool candidates_allocated() const { return candidates_allocated_; } 394 395 private: 396 TransportChannelImpl *impl_; 397 bool candidates_allocated_; 398 int ref_; 399 }; 400 401 // Candidate component => ChannelMapEntry 402 typedef std::map<int, ChannelMapEntry> ChannelMap; 403 404 // Called when the state of a channel changes. 405 void OnChannelReadableState(TransportChannel* channel); 406 void OnChannelWritableState(TransportChannel* channel); 407 408 // Called when a channel requests signaling. 409 void OnChannelRequestSignaling(TransportChannelImpl* channel); 410 411 // Called when a candidate is ready from remote peer. 412 void OnRemoteCandidate(const Candidate& candidate); 413 // Called when a candidate is ready from channel. 414 void OnChannelCandidateReady(TransportChannelImpl* channel, 415 const Candidate& candidate); 416 void OnChannelRouteChange(TransportChannel* channel, 417 const Candidate& remote_candidate); 418 void OnChannelCandidatesAllocationDone(TransportChannelImpl* channel); 419 // Called when there is ICE role change. 420 void OnRoleConflict(TransportChannelImpl* channel); 421 422 // Dispatches messages to the appropriate handler (below). 423 void OnMessage(talk_base::Message* msg); 424 425 // These are versions of the above methods that are called only on a 426 // particular thread (s = signaling, w = worker). The above methods post or 427 // send a message to invoke this version. 428 TransportChannelImpl* CreateChannel_w(int component); 429 void DestroyChannel_w(int component); 430 void ConnectChannels_w(); 431 void ResetChannels_w(); 432 void DestroyAllChannels_w(); 433 void OnRemoteCandidate_w(const Candidate& candidate); 434 void OnChannelReadableState_s(); 435 void OnChannelWritableState_s(); 436 void OnChannelRequestSignaling_s(int component); 437 void OnConnecting_s(); 438 void OnChannelRouteChange_s(const TransportChannel* channel, 439 const Candidate& remote_candidate); 440 void OnChannelCandidatesAllocationDone_s(); 441 442 // Helper function that invokes the given function on every channel. 443 typedef void (TransportChannelImpl::* TransportChannelFunc)(); 444 void CallChannels_w(TransportChannelFunc func); 445 446 // Computes the OR of the channel's read or write state (argument picks). 447 TransportState GetTransportState_s(bool read); 448 449 void OnChannelCandidateReady_s(); 450 451 void SetIceRole_w(IceRole role); 452 void SetRemoteIceMode_w(IceMode mode); 453 bool SetLocalTransportDescription_w(const TransportDescription& desc, 454 ContentAction action); 455 bool SetRemoteTransportDescription_w(const TransportDescription& desc, 456 ContentAction action); 457 bool GetStats_w(TransportStats* infos); 458 459 talk_base::Thread* signaling_thread_; 460 talk_base::Thread* worker_thread_; 461 std::string content_name_; 462 std::string type_; 463 PortAllocator* allocator_; 464 bool destroyed_; 465 TransportState readable_; 466 TransportState writable_; 467 bool was_writable_; 468 bool connect_requested_; 469 IceRole ice_role_; 470 uint64 tiebreaker_; 471 TransportProtocol protocol_; 472 IceMode remote_ice_mode_; 473 talk_base::scoped_ptr<TransportDescription> local_description_; 474 talk_base::scoped_ptr<TransportDescription> remote_description_; 475 476 ChannelMap channels_; 477 // Buffers the ready_candidates so that SignalCanidatesReady can 478 // provide them in multiples. 479 std::vector<Candidate> ready_candidates_; 480 // Protects changes to channels and messages 481 talk_base::CriticalSection crit_; 482 483 DISALLOW_EVIL_CONSTRUCTORS(Transport); 484 }; 485 486 // Extract a TransportProtocol from a TransportDescription. 487 TransportProtocol TransportProtocolFromDescription( 488 const TransportDescription* desc); 489 490 } // namespace cricket 491 492 #endif // TALK_P2P_BASE_TRANSPORT_H_ 493