1 /* 2 * Copyright 2019 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef P2P_BASE_CONNECTION_H_ 12 #define P2P_BASE_CONNECTION_H_ 13 14 #include <memory> 15 #include <string> 16 #include <vector> 17 18 #include "absl/strings/string_view.h" 19 #include "absl/types/optional.h" 20 #include "api/candidate.h" 21 #include "api/transport/stun.h" 22 #include "logging/rtc_event_log/ice_logger.h" 23 #include "p2p/base/candidate_pair_interface.h" 24 #include "p2p/base/connection_info.h" 25 #include "p2p/base/p2p_transport_channel_ice_field_trials.h" 26 #include "p2p/base/stun_request.h" 27 #include "p2p/base/transport_description.h" 28 #include "rtc_base/async_packet_socket.h" 29 #include "rtc_base/network.h" 30 #include "rtc_base/numerics/event_based_exponential_moving_average.h" 31 #include "rtc_base/rate_tracker.h" 32 #include "rtc_base/weak_ptr.h" 33 34 namespace cricket { 35 36 // Version number for GOOG_PING, this is added to have the option of 37 // adding other flavors in the future. 38 constexpr int kGoogPingVersion = 1; 39 40 // Connection and Port has circular dependencies. 41 // So we use forward declaration rather than include. 42 class Port; 43 44 // Forward declaration so that a ConnectionRequest can contain a Connection. 45 class Connection; 46 47 struct CandidatePair final : public CandidatePairInterface { 48 ~CandidatePair() override = default; 49 local_candidatefinal50 const Candidate& local_candidate() const override { return local; } remote_candidatefinal51 const Candidate& remote_candidate() const override { return remote; } 52 53 Candidate local; 54 Candidate remote; 55 }; 56 57 // Represents a communication link between a port on the local client and a 58 // port on the remote client. 59 class Connection : public CandidatePairInterface { 60 public: 61 struct SentPing { SentPingSentPing62 SentPing(absl::string_view id, int64_t sent_time, uint32_t nomination) 63 : id(id), sent_time(sent_time), nomination(nomination) {} 64 65 std::string id; 66 int64_t sent_time; 67 uint32_t nomination; 68 }; 69 70 ~Connection() override; 71 72 // A unique ID assigned when the connection is created. id()73 uint32_t id() const { return id_; } 74 75 webrtc::TaskQueueBase* network_thread() const; 76 77 // Implementation of virtual methods in CandidatePairInterface. 78 // Returns the description of the local port 79 const Candidate& local_candidate() const override; 80 // Returns the description of the remote port to which we communicate. 81 const Candidate& remote_candidate() const override; 82 83 // Return local network for this connection. 84 virtual const rtc::Network* network() const; 85 // Return generation for this connection. 86 virtual int generation() const; 87 88 // Returns the pair priority. 89 virtual uint64_t priority() const; 90 91 enum WriteState { 92 STATE_WRITABLE = 0, // we have received ping responses recently 93 STATE_WRITE_UNRELIABLE = 1, // we have had a few ping failures 94 STATE_WRITE_INIT = 2, // we have yet to receive a ping response 95 STATE_WRITE_TIMEOUT = 3, // we have had a large number of ping failures 96 }; 97 98 WriteState write_state() const; 99 bool writable() const; 100 bool receiving() const; 101 port()102 const Port* port() const { 103 RTC_DCHECK_RUN_ON(network_thread_); 104 return port_.get(); 105 } 106 107 // Determines whether the connection has finished connecting. This can only 108 // be false for TCP connections. 109 bool connected() const; 110 bool weak() const; 111 bool active() const; 112 113 // A connection is dead if it can be safely deleted. 114 bool dead(int64_t now) const; 115 116 // Estimate of the round-trip time over this connection. 117 int rtt() const; 118 119 int unwritable_timeout() const; 120 void set_unwritable_timeout(const absl::optional<int>& value_ms); 121 int unwritable_min_checks() const; 122 void set_unwritable_min_checks(const absl::optional<int>& value); 123 int inactive_timeout() const; 124 void set_inactive_timeout(const absl::optional<int>& value); 125 126 // Gets the `ConnectionInfo` stats, where `best_connection` has not been 127 // populated (default value false). 128 ConnectionInfo stats(); 129 130 sigslot::signal1<Connection*> SignalStateChange; 131 132 // Sent when the connection has decided that it is no longer of value. It 133 // will delete itself immediately after this call. 134 sigslot::signal1<Connection*> SignalDestroyed; 135 136 // The connection can send and receive packets asynchronously. This matches 137 // the interface of AsyncPacketSocket, which may use UDP or TCP under the 138 // covers. 139 virtual int Send(const void* data, 140 size_t size, 141 const rtc::PacketOptions& options) = 0; 142 143 // Error if Send() returns < 0 144 virtual int GetError() = 0; 145 146 sigslot::signal4<Connection*, const char*, size_t, int64_t> SignalReadPacket; 147 148 sigslot::signal1<Connection*> SignalReadyToSend; 149 150 // Called when a packet is received on this connection. 151 void OnReadPacket(const char* data, size_t size, int64_t packet_time_us); 152 153 // Called when the socket is currently able to send. 154 void OnReadyToSend(); 155 156 // Called when a connection is determined to be no longer useful to us. We 157 // still keep it around in case the other side wants to use it. But we can 158 // safely stop pinging on it and we can allow it to time out if the other 159 // side stops using it as well. 160 bool pruned() const; 161 void Prune(); 162 163 bool use_candidate_attr() const; 164 void set_use_candidate_attr(bool enable); 165 166 void set_nomination(uint32_t value); 167 168 uint32_t remote_nomination() const; 169 // One or several pairs may be nominated based on if Regular or Aggressive 170 // Nomination is used. https://tools.ietf.org/html/rfc5245#section-8 171 // `nominated` is defined both for the controlling or controlled agent based 172 // on if a nomination has been pinged or acknowledged. The controlled agent 173 // gets its `remote_nomination_` set when pinged by the controlling agent with 174 // a nomination value. The controlling agent gets its `acked_nomination_` set 175 // when receiving a response to a nominating ping. 176 bool nominated() const; 177 178 int receiving_timeout() const; 179 void set_receiving_timeout(absl::optional<int> receiving_timeout_ms); 180 181 // Deletes a `Connection` instance is by calling the `DestroyConnection` 182 // method in `Port`. 183 // Note: When the function returns, the object has been deleted. 184 void Destroy(); 185 186 // Signals object destruction, releases outstanding references and performs 187 // final logging. 188 // The function will return `true` when shutdown was performed, signals 189 // emitted and outstanding references released. If the function returns 190 // `false`, `Shutdown()` has previously been called. 191 bool Shutdown(); 192 193 // Prunes the connection and sets its state to STATE_FAILED, 194 // It will not be used or send pings although it can still receive packets. 195 void FailAndPrune(); 196 197 // Checks that the state of this connection is up-to-date. The argument is 198 // the current time, which is compared against various timeouts. 199 void UpdateState(int64_t now); 200 201 void UpdateLocalIceParameters(int component, 202 absl::string_view username_fragment, 203 absl::string_view password); 204 205 // Called when this connection should try checking writability again. 206 int64_t last_ping_sent() const; 207 void Ping(int64_t now); 208 void ReceivedPingResponse( 209 int rtt, 210 absl::string_view request_id, 211 const absl::optional<uint32_t>& nomination = absl::nullopt); 212 std::unique_ptr<IceMessage> BuildPingRequest() RTC_RUN_ON(network_thread_); 213 214 int64_t last_ping_response_received() const; 215 const absl::optional<std::string>& last_ping_id_received() const; 216 217 // Used to check if any STUN ping response has been received. 218 int rtt_samples() const; 219 220 // Called whenever a valid ping is received on this connection. This is 221 // public because the connection intercepts the first ping for us. 222 int64_t last_ping_received() const; 223 224 void ReceivedPing( 225 const absl::optional<std::string>& request_id = absl::nullopt); 226 // Handles the binding request; sends a response if this is a valid request. 227 void HandleStunBindingOrGoogPingRequest(IceMessage* msg); 228 // Handles the piggyback acknowledgement of the lastest connectivity check 229 // that the remote peer has received, if it is indicated in the incoming 230 // connectivity check from the peer. 231 void HandlePiggybackCheckAcknowledgementIfAny(StunMessage* msg); 232 // Timestamp when data was last sent (or attempted to be sent). 233 int64_t last_send_data() const; 234 int64_t last_data_received() const; 235 236 // Debugging description of this connection 237 std::string ToDebugId() const; 238 std::string ToString() const; 239 std::string ToSensitiveString() const; 240 // Structured description of this candidate pair. 241 const webrtc::IceCandidatePairDescription& ToLogDescription(); 242 void set_ice_event_log(webrtc::IceEventLog* ice_event_log); 243 244 // Prints pings_since_last_response_ into a string. 245 void PrintPingsSinceLastResponse(std::string* pings, size_t max); 246 247 // `set_selected` is only used for logging in ToString above. The flag is 248 // set true by P2PTransportChannel for its selected candidate pair. 249 // TODO(tommi): Remove `selected()` once not referenced downstream. 250 bool selected() const; 251 void set_selected(bool selected); 252 253 // This signal will be fired if this connection is nominated by the 254 // controlling side. 255 sigslot::signal1<Connection*> SignalNominated; 256 257 IceCandidatePairState state() const; 258 259 int num_pings_sent() const; 260 261 uint32_t ComputeNetworkCost() const; 262 263 // Update the ICE password and/or generation of the remote candidate if the 264 // ufrag in `params` matches the candidate's ufrag, and the 265 // candidate's password and/or ufrag has not been set. 266 void MaybeSetRemoteIceParametersAndGeneration(const IceParameters& params, 267 int generation); 268 269 // If `remote_candidate_` is peer reflexive and is equivalent to 270 // `new_candidate` except the type, update `remote_candidate_` to 271 // `new_candidate`. 272 void MaybeUpdatePeerReflexiveCandidate(const Candidate& new_candidate); 273 274 // Returns the last received time of any data, stun request, or stun 275 // response in milliseconds 276 int64_t last_received() const; 277 // Returns the last time when the connection changed its receiving state. 278 int64_t receiving_unchanged_since() const; 279 280 // Constructs the prflx priority as described in 281 // https://datatracker.ietf.org/doc/html/rfc5245#section-4.1.2.1 282 uint32_t prflx_priority() const; 283 284 bool stable(int64_t now) const; 285 286 // Check if we sent `val` pings without receving a response. 287 bool TooManyOutstandingPings(const absl::optional<int>& val) const; 288 289 // Called by Port when the network cost changes. 290 void SetLocalCandidateNetworkCost(uint16_t cost); 291 292 void SetIceFieldTrials(const IceFieldTrials* field_trials); GetRttEstimate()293 const rtc::EventBasedExponentialMovingAverage& GetRttEstimate() const { 294 return rtt_estimate_; 295 } 296 297 // Reset the connection to a state of a newly connected. 298 // - STATE_WRITE_INIT 299 // - receving = false 300 // - throw away all pending request 301 // - reset RttEstimate 302 // 303 // Keep the following unchanged: 304 // - connected 305 // - remote_candidate 306 // - statistics 307 // 308 // Does not trigger SignalStateChange 309 void ForgetLearnedState(); 310 311 void SendStunBindingResponse(const StunMessage* message); 312 void SendGoogPingResponse(const StunMessage* message); 313 void SendResponseMessage(const StunMessage& response); 314 315 // An accessor for unit tests. PortForTest()316 Port* PortForTest() { return port_.get(); } PortForTest()317 const Port* PortForTest() const { return port_.get(); } 318 319 // Public for unit tests. 320 uint32_t acked_nomination() const; 321 void set_remote_nomination(uint32_t remote_nomination); 322 323 protected: 324 // A ConnectionRequest is a simple STUN ping used to determine writability. 325 class ConnectionRequest; 326 327 // Constructs a new connection to the given remote port. 328 Connection(rtc::WeakPtr<Port> port, size_t index, const Candidate& candidate); 329 330 // Called back when StunRequestManager has a stun packet to send 331 void OnSendStunPacket(const void* data, size_t size, StunRequest* req); 332 333 // Callbacks from ConnectionRequest 334 virtual void OnConnectionRequestResponse(StunRequest* req, 335 StunMessage* response); 336 void OnConnectionRequestErrorResponse(ConnectionRequest* req, 337 StunMessage* response) 338 RTC_RUN_ON(network_thread_); 339 void OnConnectionRequestTimeout(ConnectionRequest* req) 340 RTC_RUN_ON(network_thread_); 341 void OnConnectionRequestSent(ConnectionRequest* req) 342 RTC_RUN_ON(network_thread_); 343 344 bool rtt_converged() const; 345 346 // If the response is not received within 2 * RTT, the response is assumed to 347 // be missing. 348 bool missing_responses(int64_t now) const; 349 350 // Changes the state and signals if necessary. 351 void set_write_state(WriteState value); 352 void UpdateReceiving(int64_t now); 353 void set_state(IceCandidatePairState state); 354 void set_connected(bool value); 355 356 // The local port where this connection sends and receives packets. port()357 Port* port() { return port_.get(); } 358 359 // NOTE: A pointer to the network thread is held by `port_` so in theory we 360 // shouldn't need to hold on to this pointer here, but rather defer to 361 // port_->thread(). However, some tests delete the classes in the wrong order 362 // so `port_` may be deleted before an instance of this class is deleted. 363 // TODO(tommi): This ^^^ should be fixed. 364 webrtc::TaskQueueBase* const network_thread_; 365 const uint32_t id_; 366 rtc::WeakPtr<Port> port_; 367 Candidate local_candidate_ RTC_GUARDED_BY(network_thread_); 368 Candidate remote_candidate_; 369 370 ConnectionInfo stats_; 371 rtc::RateTracker recv_rate_tracker_; 372 rtc::RateTracker send_rate_tracker_; 373 int64_t last_send_data_ = 0; 374 375 private: 376 // Update the local candidate based on the mapped address attribute. 377 // If the local candidate changed, fires SignalStateChange. 378 void MaybeUpdateLocalCandidate(StunRequest* request, StunMessage* response) 379 RTC_RUN_ON(network_thread_); 380 381 void LogCandidatePairConfig(webrtc::IceCandidatePairConfigType type) 382 RTC_RUN_ON(network_thread_); 383 void LogCandidatePairEvent(webrtc::IceCandidatePairEventType type, 384 uint32_t transaction_id) 385 RTC_RUN_ON(network_thread_); 386 387 // Check if this IceMessage is identical 388 // to last message ack:ed STUN_BINDING_REQUEST. 389 bool ShouldSendGoogPing(const StunMessage* message) 390 RTC_RUN_ON(network_thread_); 391 392 WriteState write_state_ RTC_GUARDED_BY(network_thread_); 393 bool receiving_ RTC_GUARDED_BY(network_thread_); 394 bool connected_ RTC_GUARDED_BY(network_thread_); 395 bool pruned_ RTC_GUARDED_BY(network_thread_); 396 bool selected_ RTC_GUARDED_BY(network_thread_) = false; 397 // By default `use_candidate_attr_` flag will be true, 398 // as we will be using aggressive nomination. 399 // But when peer is ice-lite, this flag "must" be initialized to false and 400 // turn on when connection becomes "best connection". 401 bool use_candidate_attr_ RTC_GUARDED_BY(network_thread_); 402 // Used by the controlling side to indicate that this connection will be 403 // selected for transmission if the peer supports ICE-renomination when this 404 // value is positive. A larger-value indicates that a connection is nominated 405 // later and should be selected by the controlled side with higher precedence. 406 // A zero-value indicates not nominating this connection. 407 uint32_t nomination_ RTC_GUARDED_BY(network_thread_) = 0; 408 // The last nomination that has been acknowledged. 409 uint32_t acked_nomination_ RTC_GUARDED_BY(network_thread_) = 0; 410 // Used by the controlled side to remember the nomination value received from 411 // the controlling side. When the peer does not support ICE re-nomination, its 412 // value will be 1 if the connection has been nominated. 413 uint32_t remote_nomination_ RTC_GUARDED_BY(network_thread_) = 0; 414 415 StunRequestManager requests_ RTC_GUARDED_BY(network_thread_); 416 int rtt_ RTC_GUARDED_BY(network_thread_); 417 int rtt_samples_ RTC_GUARDED_BY(network_thread_) = 0; 418 // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-totalroundtriptime 419 uint64_t total_round_trip_time_ms_ RTC_GUARDED_BY(network_thread_) = 0; 420 // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime 421 absl::optional<uint32_t> current_round_trip_time_ms_ 422 RTC_GUARDED_BY(network_thread_); 423 int64_t last_ping_sent_ RTC_GUARDED_BY( 424 network_thread_); // last time we sent a ping to the other side 425 int64_t last_ping_received_ 426 RTC_GUARDED_BY(network_thread_); // last time we received a ping from the 427 // other side 428 int64_t last_data_received_ RTC_GUARDED_BY(network_thread_); 429 int64_t last_ping_response_received_ RTC_GUARDED_BY(network_thread_); 430 int64_t receiving_unchanged_since_ RTC_GUARDED_BY(network_thread_) = 0; 431 std::vector<SentPing> pings_since_last_response_ 432 RTC_GUARDED_BY(network_thread_); 433 // Transaction ID of the last connectivity check received. Null if having not 434 // received a ping yet. 435 absl::optional<std::string> last_ping_id_received_ 436 RTC_GUARDED_BY(network_thread_); 437 438 absl::optional<int> unwritable_timeout_ RTC_GUARDED_BY(network_thread_); 439 absl::optional<int> unwritable_min_checks_ RTC_GUARDED_BY(network_thread_); 440 absl::optional<int> inactive_timeout_ RTC_GUARDED_BY(network_thread_); 441 442 IceCandidatePairState state_ RTC_GUARDED_BY(network_thread_); 443 // Time duration to switch from receiving to not receiving. 444 absl::optional<int> receiving_timeout_ RTC_GUARDED_BY(network_thread_); 445 const int64_t time_created_ms_ RTC_GUARDED_BY(network_thread_); 446 const int64_t delta_internal_unix_epoch_ms_ RTC_GUARDED_BY(network_thread_); 447 int num_pings_sent_ RTC_GUARDED_BY(network_thread_) = 0; 448 449 absl::optional<webrtc::IceCandidatePairDescription> log_description_ 450 RTC_GUARDED_BY(network_thread_); 451 webrtc::IceEventLog* ice_event_log_ RTC_GUARDED_BY(network_thread_) = nullptr; 452 453 // GOOG_PING_REQUEST is sent in place of STUN_BINDING_REQUEST 454 // if configured via field trial, the remote peer supports it (signaled 455 // in STUN_BINDING) and if the last STUN BINDING is identical to the one 456 // that is about to be sent. 457 absl::optional<bool> remote_support_goog_ping_ 458 RTC_GUARDED_BY(network_thread_); 459 std::unique_ptr<StunMessage> cached_stun_binding_ 460 RTC_GUARDED_BY(network_thread_); 461 462 const IceFieldTrials* field_trials_; 463 rtc::EventBasedExponentialMovingAverage rtt_estimate_ 464 RTC_GUARDED_BY(network_thread_); 465 }; 466 467 // ProxyConnection defers all the interesting work to the port. 468 class ProxyConnection : public Connection { 469 public: 470 ProxyConnection(rtc::WeakPtr<Port> port, 471 size_t index, 472 const Candidate& remote_candidate); 473 474 int Send(const void* data, 475 size_t size, 476 const rtc::PacketOptions& options) override; 477 int GetError() override; 478 479 private: 480 int error_ = 0; 481 }; 482 483 } // namespace cricket 484 485 #endif // P2P_BASE_CONNECTION_H_ 486