1 /* 2 * Copyright 2004 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_STUN_REQUEST_H_ 12 #define P2P_BASE_STUN_REQUEST_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <functional> 18 #include <map> 19 #include <memory> 20 #include <string> 21 22 #include "api/task_queue/pending_task_safety_flag.h" 23 #include "api/task_queue/task_queue_base.h" 24 #include "api/transport/stun.h" 25 #include "api/units/time_delta.h" 26 27 namespace cricket { 28 29 class StunRequest; 30 31 const int kAllRequestsForTest = 0; 32 33 // Total max timeouts: 39.75 seconds 34 // For years, this was 9.5 seconds, but for networks that experience moments of 35 // high RTT (such as 40s on 2G networks), this doesn't work well. 36 const int STUN_TOTAL_TIMEOUT = 39750; // milliseconds 37 38 // Manages a set of STUN requests, sending and resending until we receive a 39 // response or determine that the request has timed out. 40 class StunRequestManager { 41 public: 42 StunRequestManager( 43 webrtc::TaskQueueBase* thread, 44 std::function<void(const void*, size_t, StunRequest*)> send_packet); 45 ~StunRequestManager(); 46 47 // Starts sending the given request (perhaps after a delay). 48 void Send(StunRequest* request); 49 void SendDelayed(StunRequest* request, int delay); 50 51 // If `msg_type` is kAllRequestsForTest, sends all pending requests right 52 // away. Otherwise, sends those that have a matching type right away. Only for 53 // testing. 54 // TODO(tommi): Remove this method and update tests that use it to simulate 55 // production code. 56 void FlushForTest(int msg_type); 57 58 // Returns true if at least one request with `msg_type` is scheduled for 59 // transmission. For testing only. 60 // TODO(tommi): Remove this method and update tests that use it to simulate 61 // production code. 62 bool HasRequestForTest(int msg_type); 63 64 // Removes all stun requests that were added previously. 65 void Clear(); 66 67 // Determines whether the given message is a response to one of the 68 // outstanding requests, and if so, processes it appropriately. 69 bool CheckResponse(StunMessage* msg); 70 bool CheckResponse(const char* data, size_t size); 71 72 // Called from a StunRequest when a timeout occurs. 73 void OnRequestTimedOut(StunRequest* request); 74 75 bool empty() const; 76 network_thread()77 webrtc::TaskQueueBase* network_thread() const { return thread_; } 78 79 void SendPacket(const void* data, size_t size, StunRequest* request); 80 81 private: 82 typedef std::map<std::string, std::unique_ptr<StunRequest>> RequestMap; 83 84 webrtc::TaskQueueBase* const thread_; 85 RequestMap requests_ RTC_GUARDED_BY(thread_); 86 const std::function<void(const void*, size_t, StunRequest*)> send_packet_; 87 }; 88 89 // Represents an individual request to be sent. The STUN message can either be 90 // constructed beforehand or built on demand. 91 class StunRequest { 92 public: 93 explicit StunRequest(StunRequestManager& manager); 94 StunRequest(StunRequestManager& manager, 95 std::unique_ptr<StunMessage> message); 96 virtual ~StunRequest(); 97 98 // The manager handling this request (if it has been scheduled for sending). manager()99 StunRequestManager* manager() { return &manager_; } 100 101 // Returns the transaction ID of this request. id()102 const std::string& id() const { return msg_->transaction_id(); } 103 104 // Returns the reduced transaction ID of this request. reduced_transaction_id()105 uint32_t reduced_transaction_id() const { 106 return msg_->reduced_transaction_id(); 107 } 108 109 // Returns the STUN type of the request message. 110 int type(); 111 112 // Returns a const pointer to `msg_`. 113 const StunMessage* msg() const; 114 115 // Time elapsed since last send (in ms) 116 int Elapsed() const; 117 118 protected: 119 friend class StunRequestManager; 120 121 // Called by StunRequestManager. 122 void Send(webrtc::TimeDelta delay); 123 124 // Called from FlushForTest. 125 // TODO(tommi): Remove when FlushForTest gets removed. 126 void ResetTasksForTest(); 127 mutable_msg()128 StunMessage* mutable_msg() { return msg_.get(); } 129 130 // Called when the message receives a response or times out. OnResponse(StunMessage * response)131 virtual void OnResponse(StunMessage* response) {} OnErrorResponse(StunMessage * response)132 virtual void OnErrorResponse(StunMessage* response) {} OnTimeout()133 virtual void OnTimeout() {} 134 // Called when the message is sent. 135 virtual void OnSent(); 136 // Returns the next delay for resends in milliseconds. 137 virtual int resend_delay(); 138 network_thread()139 webrtc::TaskQueueBase* network_thread() const { 140 return manager_.network_thread(); 141 } 142 143 void set_timed_out(); 144 145 private: 146 void SendInternal(); 147 // Calls `PostDelayedTask` to queue up a call to SendInternal after the 148 // specified timeout. 149 void SendDelayed(webrtc::TimeDelta delay); 150 151 StunRequestManager& manager_; 152 const std::unique_ptr<StunMessage> msg_; 153 int64_t tstamp_ RTC_GUARDED_BY(network_thread()); 154 int count_ RTC_GUARDED_BY(network_thread()); 155 bool timeout_ RTC_GUARDED_BY(network_thread()); 156 webrtc::ScopedTaskSafety task_safety_{ 157 webrtc::PendingTaskSafetyFlag::CreateDetachedInactive()}; 158 }; 159 160 } // namespace cricket 161 162 #endif // P2P_BASE_STUN_REQUEST_H_ 163