xref: /aosp_15_r20/external/webrtc/p2p/base/stun_request.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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