/* * Copyright 2004 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef P2P_BASE_STUN_REQUEST_H_ #define P2P_BASE_STUN_REQUEST_H_ #include #include #include #include #include #include #include "api/task_queue/pending_task_safety_flag.h" #include "api/task_queue/task_queue_base.h" #include "api/transport/stun.h" #include "api/units/time_delta.h" namespace cricket { class StunRequest; const int kAllRequestsForTest = 0; // Total max timeouts: 39.75 seconds // For years, this was 9.5 seconds, but for networks that experience moments of // high RTT (such as 40s on 2G networks), this doesn't work well. const int STUN_TOTAL_TIMEOUT = 39750; // milliseconds // Manages a set of STUN requests, sending and resending until we receive a // response or determine that the request has timed out. class StunRequestManager { public: StunRequestManager( webrtc::TaskQueueBase* thread, std::function send_packet); ~StunRequestManager(); // Starts sending the given request (perhaps after a delay). void Send(StunRequest* request); void SendDelayed(StunRequest* request, int delay); // If `msg_type` is kAllRequestsForTest, sends all pending requests right // away. Otherwise, sends those that have a matching type right away. Only for // testing. // TODO(tommi): Remove this method and update tests that use it to simulate // production code. void FlushForTest(int msg_type); // Returns true if at least one request with `msg_type` is scheduled for // transmission. For testing only. // TODO(tommi): Remove this method and update tests that use it to simulate // production code. bool HasRequestForTest(int msg_type); // Removes all stun requests that were added previously. void Clear(); // Determines whether the given message is a response to one of the // outstanding requests, and if so, processes it appropriately. bool CheckResponse(StunMessage* msg); bool CheckResponse(const char* data, size_t size); // Called from a StunRequest when a timeout occurs. void OnRequestTimedOut(StunRequest* request); bool empty() const; webrtc::TaskQueueBase* network_thread() const { return thread_; } void SendPacket(const void* data, size_t size, StunRequest* request); private: typedef std::map> RequestMap; webrtc::TaskQueueBase* const thread_; RequestMap requests_ RTC_GUARDED_BY(thread_); const std::function send_packet_; }; // Represents an individual request to be sent. The STUN message can either be // constructed beforehand or built on demand. class StunRequest { public: explicit StunRequest(StunRequestManager& manager); StunRequest(StunRequestManager& manager, std::unique_ptr message); virtual ~StunRequest(); // The manager handling this request (if it has been scheduled for sending). StunRequestManager* manager() { return &manager_; } // Returns the transaction ID of this request. const std::string& id() const { return msg_->transaction_id(); } // Returns the reduced transaction ID of this request. uint32_t reduced_transaction_id() const { return msg_->reduced_transaction_id(); } // Returns the STUN type of the request message. int type(); // Returns a const pointer to `msg_`. const StunMessage* msg() const; // Time elapsed since last send (in ms) int Elapsed() const; protected: friend class StunRequestManager; // Called by StunRequestManager. void Send(webrtc::TimeDelta delay); // Called from FlushForTest. // TODO(tommi): Remove when FlushForTest gets removed. void ResetTasksForTest(); StunMessage* mutable_msg() { return msg_.get(); } // Called when the message receives a response or times out. virtual void OnResponse(StunMessage* response) {} virtual void OnErrorResponse(StunMessage* response) {} virtual void OnTimeout() {} // Called when the message is sent. virtual void OnSent(); // Returns the next delay for resends in milliseconds. virtual int resend_delay(); webrtc::TaskQueueBase* network_thread() const { return manager_.network_thread(); } void set_timed_out(); private: void SendInternal(); // Calls `PostDelayedTask` to queue up a call to SendInternal after the // specified timeout. void SendDelayed(webrtc::TimeDelta delay); StunRequestManager& manager_; const std::unique_ptr msg_; int64_t tstamp_ RTC_GUARDED_BY(network_thread()); int count_ RTC_GUARDED_BY(network_thread()); bool timeout_ RTC_GUARDED_BY(network_thread()); webrtc::ScopedTaskSafety task_safety_{ webrtc::PendingTaskSafetyFlag::CreateDetachedInactive()}; }; } // namespace cricket #endif // P2P_BASE_STUN_REQUEST_H_