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