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