xref: /aosp_15_r20/external/webrtc/p2p/base/turn_port.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2012 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 #include "p2p/base/turn_port.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <functional>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker #include <vector>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
19*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
20*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
21*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/pending_task_safety_flag.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/transport/stun.h"
24*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/connection.h"
25*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/async_packet_socket.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_order.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/experiments/field_trial_parser.h"
30*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/net_helpers.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
34*d9f75844SAndroid Build Coastguard Worker 
35*d9f75844SAndroid Build Coastguard Worker namespace cricket {
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker namespace {
38*d9f75844SAndroid Build Coastguard Worker 
ResolveTurnHostnameForFamily(const webrtc::FieldTrialsView & field_trials)39*d9f75844SAndroid Build Coastguard Worker bool ResolveTurnHostnameForFamily(const webrtc::FieldTrialsView& field_trials) {
40*d9f75844SAndroid Build Coastguard Worker   // Bug fix for TURN hostname resolution on IPv6.
41*d9f75844SAndroid Build Coastguard Worker   // Field trial key reserved in bugs.webrtc.org/14334
42*d9f75844SAndroid Build Coastguard Worker   static constexpr char field_trial_name[] =
43*d9f75844SAndroid Build Coastguard Worker       "WebRTC-IPv6NetworkResolutionFixes";
44*d9f75844SAndroid Build Coastguard Worker   if (!field_trials.IsEnabled(field_trial_name)) {
45*d9f75844SAndroid Build Coastguard Worker     return false;
46*d9f75844SAndroid Build Coastguard Worker   }
47*d9f75844SAndroid Build Coastguard Worker 
48*d9f75844SAndroid Build Coastguard Worker   webrtc::FieldTrialParameter<bool> resolve_turn_hostname_for_family(
49*d9f75844SAndroid Build Coastguard Worker       "ResolveTurnHostnameForFamily", /*default_value=*/false);
50*d9f75844SAndroid Build Coastguard Worker   webrtc::ParseFieldTrial({&resolve_turn_hostname_for_family},
51*d9f75844SAndroid Build Coastguard Worker                           field_trials.Lookup(field_trial_name));
52*d9f75844SAndroid Build Coastguard Worker   return resolve_turn_hostname_for_family;
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker 
55*d9f75844SAndroid Build Coastguard Worker }  // namespace
56*d9f75844SAndroid Build Coastguard Worker 
57*d9f75844SAndroid Build Coastguard Worker using ::webrtc::SafeTask;
58*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TaskQueueBase;
59*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TimeDelta;
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker // TODO(juberti): Move to stun.h when relay messages have been renamed.
62*d9f75844SAndroid Build Coastguard Worker static const int TURN_ALLOCATE_REQUEST = STUN_ALLOCATE_REQUEST;
63*d9f75844SAndroid Build Coastguard Worker 
64*d9f75844SAndroid Build Coastguard Worker // Attributes in comprehension-optional range,
65*d9f75844SAndroid Build Coastguard Worker // ignored by TURN server that doesn't know about them.
66*d9f75844SAndroid Build Coastguard Worker // https://tools.ietf.org/html/rfc5389#section-18.2
67*d9f75844SAndroid Build Coastguard Worker const int STUN_ATTR_TURN_LOGGING_ID = 0xff05;
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker // TODO(juberti): Extract to turnmessage.h
70*d9f75844SAndroid Build Coastguard Worker static const int TURN_DEFAULT_PORT = 3478;
71*d9f75844SAndroid Build Coastguard Worker static const int TURN_CHANNEL_NUMBER_START = 0x4000;
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kTurnPermissionTimeout = TimeDelta::Minutes(5);
74*d9f75844SAndroid Build Coastguard Worker 
75*d9f75844SAndroid Build Coastguard Worker static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
76*d9f75844SAndroid Build Coastguard Worker 
77*d9f75844SAndroid Build Coastguard Worker // Retry at most twice (i.e. three different ALLOCATE requests) on
78*d9f75844SAndroid Build Coastguard Worker // STUN_ERROR_ALLOCATION_MISMATCH error per rfc5766.
79*d9f75844SAndroid Build Coastguard Worker static const size_t MAX_ALLOCATE_MISMATCH_RETRIES = 2;
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker static const int TURN_SUCCESS_RESULT_CODE = 0;
82*d9f75844SAndroid Build Coastguard Worker 
IsTurnChannelData(uint16_t msg_type)83*d9f75844SAndroid Build Coastguard Worker inline bool IsTurnChannelData(uint16_t msg_type) {
84*d9f75844SAndroid Build Coastguard Worker   return ((msg_type & 0xC000) == 0x4000);  // MSB are 0b01
85*d9f75844SAndroid Build Coastguard Worker }
86*d9f75844SAndroid Build Coastguard Worker 
GetRelayPreference(cricket::ProtocolType proto)87*d9f75844SAndroid Build Coastguard Worker static int GetRelayPreference(cricket::ProtocolType proto) {
88*d9f75844SAndroid Build Coastguard Worker   switch (proto) {
89*d9f75844SAndroid Build Coastguard Worker     case cricket::PROTO_TCP:
90*d9f75844SAndroid Build Coastguard Worker       return ICE_TYPE_PREFERENCE_RELAY_TCP;
91*d9f75844SAndroid Build Coastguard Worker     case cricket::PROTO_TLS:
92*d9f75844SAndroid Build Coastguard Worker       return ICE_TYPE_PREFERENCE_RELAY_TLS;
93*d9f75844SAndroid Build Coastguard Worker     default:
94*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(proto == PROTO_UDP);
95*d9f75844SAndroid Build Coastguard Worker       return ICE_TYPE_PREFERENCE_RELAY_UDP;
96*d9f75844SAndroid Build Coastguard Worker   }
97*d9f75844SAndroid Build Coastguard Worker }
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker class TurnAllocateRequest : public StunRequest {
100*d9f75844SAndroid Build Coastguard Worker  public:
101*d9f75844SAndroid Build Coastguard Worker   explicit TurnAllocateRequest(TurnPort* port);
102*d9f75844SAndroid Build Coastguard Worker   void OnSent() override;
103*d9f75844SAndroid Build Coastguard Worker   void OnResponse(StunMessage* response) override;
104*d9f75844SAndroid Build Coastguard Worker   void OnErrorResponse(StunMessage* response) override;
105*d9f75844SAndroid Build Coastguard Worker   void OnTimeout() override;
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker  private:
108*d9f75844SAndroid Build Coastguard Worker   // Handles authentication challenge from the server.
109*d9f75844SAndroid Build Coastguard Worker   void OnAuthChallenge(StunMessage* response, int code);
110*d9f75844SAndroid Build Coastguard Worker   void OnTryAlternate(StunMessage* response, int code);
111*d9f75844SAndroid Build Coastguard Worker   void OnUnknownAttribute(StunMessage* response);
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   TurnPort* port_;
114*d9f75844SAndroid Build Coastguard Worker };
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker class TurnRefreshRequest : public StunRequest {
117*d9f75844SAndroid Build Coastguard Worker  public:
118*d9f75844SAndroid Build Coastguard Worker   explicit TurnRefreshRequest(TurnPort* port, int lifetime = -1);
119*d9f75844SAndroid Build Coastguard Worker   void OnSent() override;
120*d9f75844SAndroid Build Coastguard Worker   void OnResponse(StunMessage* response) override;
121*d9f75844SAndroid Build Coastguard Worker   void OnErrorResponse(StunMessage* response) override;
122*d9f75844SAndroid Build Coastguard Worker   void OnTimeout() override;
123*d9f75844SAndroid Build Coastguard Worker 
124*d9f75844SAndroid Build Coastguard Worker  private:
125*d9f75844SAndroid Build Coastguard Worker   TurnPort* port_;
126*d9f75844SAndroid Build Coastguard Worker };
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker class TurnCreatePermissionRequest : public StunRequest {
129*d9f75844SAndroid Build Coastguard Worker  public:
130*d9f75844SAndroid Build Coastguard Worker   TurnCreatePermissionRequest(TurnPort* port,
131*d9f75844SAndroid Build Coastguard Worker                               TurnEntry* entry,
132*d9f75844SAndroid Build Coastguard Worker                               const rtc::SocketAddress& ext_addr);
133*d9f75844SAndroid Build Coastguard Worker   ~TurnCreatePermissionRequest() override;
134*d9f75844SAndroid Build Coastguard Worker   void OnSent() override;
135*d9f75844SAndroid Build Coastguard Worker   void OnResponse(StunMessage* response) override;
136*d9f75844SAndroid Build Coastguard Worker   void OnErrorResponse(StunMessage* response) override;
137*d9f75844SAndroid Build Coastguard Worker   void OnTimeout() override;
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker  private:
140*d9f75844SAndroid Build Coastguard Worker   TurnPort* port_;
141*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry_;
142*d9f75844SAndroid Build Coastguard Worker   rtc::SocketAddress ext_addr_;
143*d9f75844SAndroid Build Coastguard Worker };
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker class TurnChannelBindRequest : public StunRequest {
146*d9f75844SAndroid Build Coastguard Worker  public:
147*d9f75844SAndroid Build Coastguard Worker   TurnChannelBindRequest(TurnPort* port,
148*d9f75844SAndroid Build Coastguard Worker                          TurnEntry* entry,
149*d9f75844SAndroid Build Coastguard Worker                          int channel_id,
150*d9f75844SAndroid Build Coastguard Worker                          const rtc::SocketAddress& ext_addr);
151*d9f75844SAndroid Build Coastguard Worker   ~TurnChannelBindRequest() override;
152*d9f75844SAndroid Build Coastguard Worker   void OnSent() override;
153*d9f75844SAndroid Build Coastguard Worker   void OnResponse(StunMessage* response) override;
154*d9f75844SAndroid Build Coastguard Worker   void OnErrorResponse(StunMessage* response) override;
155*d9f75844SAndroid Build Coastguard Worker   void OnTimeout() override;
156*d9f75844SAndroid Build Coastguard Worker 
157*d9f75844SAndroid Build Coastguard Worker  private:
158*d9f75844SAndroid Build Coastguard Worker   TurnPort* port_;
159*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry_;
160*d9f75844SAndroid Build Coastguard Worker   int channel_id_;
161*d9f75844SAndroid Build Coastguard Worker   rtc::SocketAddress ext_addr_;
162*d9f75844SAndroid Build Coastguard Worker };
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker // Manages a "connection" to a remote destination. We will attempt to bring up
165*d9f75844SAndroid Build Coastguard Worker // a channel for this remote destination to reduce the overhead of sending data.
166*d9f75844SAndroid Build Coastguard Worker class TurnEntry : public sigslot::has_slots<> {
167*d9f75844SAndroid Build Coastguard Worker  public:
168*d9f75844SAndroid Build Coastguard Worker   enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
169*d9f75844SAndroid Build Coastguard Worker   TurnEntry(TurnPort* port, Connection* conn, int channel_id);
170*d9f75844SAndroid Build Coastguard Worker   ~TurnEntry();
171*d9f75844SAndroid Build Coastguard Worker 
port()172*d9f75844SAndroid Build Coastguard Worker   TurnPort* port() { return port_; }
173*d9f75844SAndroid Build Coastguard Worker 
channel_id() const174*d9f75844SAndroid Build Coastguard Worker   int channel_id() const { return channel_id_; }
175*d9f75844SAndroid Build Coastguard Worker   // For testing only.
set_channel_id(int channel_id)176*d9f75844SAndroid Build Coastguard Worker   void set_channel_id(int channel_id) { channel_id_ = channel_id; }
177*d9f75844SAndroid Build Coastguard Worker 
address() const178*d9f75844SAndroid Build Coastguard Worker   const rtc::SocketAddress& address() const { return ext_addr_; }
state() const179*d9f75844SAndroid Build Coastguard Worker   BindState state() const { return state_; }
180*d9f75844SAndroid Build Coastguard Worker 
181*d9f75844SAndroid Build Coastguard Worker   // Adds a new connection object to the list of connections that are associated
182*d9f75844SAndroid Build Coastguard Worker   // with this entry. If prior to this call there were no connections being
183*d9f75844SAndroid Build Coastguard Worker   // tracked (i.e. count goes from 0 -> 1), the internal safety flag is reset
184*d9f75844SAndroid Build Coastguard Worker   // which cancels any potential pending deletion tasks.
185*d9f75844SAndroid Build Coastguard Worker   void TrackConnection(Connection* conn);
186*d9f75844SAndroid Build Coastguard Worker 
187*d9f75844SAndroid Build Coastguard Worker   // Removes a connection from the list of tracked connections.
188*d9f75844SAndroid Build Coastguard Worker   // * If `conn` was the last connection removed, the function returns a
189*d9f75844SAndroid Build Coastguard Worker   //   safety flag that's used to schedule the deletion of the entry after a
190*d9f75844SAndroid Build Coastguard Worker   //   timeout expires. If during this timeout `TrackConnection` is called, the
191*d9f75844SAndroid Build Coastguard Worker   //   flag will be reset and pending tasks associated with it, cancelled.
192*d9f75844SAndroid Build Coastguard Worker   // * If `conn` was not the last connection, the return value will be nullptr.
193*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<webrtc::PendingTaskSafetyFlag> UntrackConnection(
194*d9f75844SAndroid Build Coastguard Worker       Connection* conn);
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker   // Helper methods to send permission and channel bind requests.
197*d9f75844SAndroid Build Coastguard Worker   void SendCreatePermissionRequest(int delay);
198*d9f75844SAndroid Build Coastguard Worker   void SendChannelBindRequest(int delay);
199*d9f75844SAndroid Build Coastguard Worker   // Sends a packet to the given destination address.
200*d9f75844SAndroid Build Coastguard Worker   // This will wrap the packet in STUN if necessary.
201*d9f75844SAndroid Build Coastguard Worker   int Send(const void* data,
202*d9f75844SAndroid Build Coastguard Worker            size_t size,
203*d9f75844SAndroid Build Coastguard Worker            bool payload,
204*d9f75844SAndroid Build Coastguard Worker            const rtc::PacketOptions& options);
205*d9f75844SAndroid Build Coastguard Worker 
206*d9f75844SAndroid Build Coastguard Worker   void OnCreatePermissionSuccess();
207*d9f75844SAndroid Build Coastguard Worker   void OnCreatePermissionError(StunMessage* response, int code);
208*d9f75844SAndroid Build Coastguard Worker   void OnCreatePermissionTimeout();
209*d9f75844SAndroid Build Coastguard Worker   void OnChannelBindSuccess();
210*d9f75844SAndroid Build Coastguard Worker   void OnChannelBindError(StunMessage* response, int code);
211*d9f75844SAndroid Build Coastguard Worker   void OnChannelBindTimeout();
212*d9f75844SAndroid Build Coastguard Worker   // Signal sent when TurnEntry is destroyed.
213*d9f75844SAndroid Build Coastguard Worker   webrtc::CallbackList<TurnEntry*> destroyed_callback_list_;
214*d9f75844SAndroid Build Coastguard Worker 
215*d9f75844SAndroid Build Coastguard Worker  private:
216*d9f75844SAndroid Build Coastguard Worker   TurnPort* port_;
217*d9f75844SAndroid Build Coastguard Worker   int channel_id_;
218*d9f75844SAndroid Build Coastguard Worker   rtc::SocketAddress ext_addr_;
219*d9f75844SAndroid Build Coastguard Worker   BindState state_;
220*d9f75844SAndroid Build Coastguard Worker   // List of associated connection instances to keep track of how many and
221*d9f75844SAndroid Build Coastguard Worker   // which connections are associated with this entry. Once this is empty,
222*d9f75844SAndroid Build Coastguard Worker   // the entry can be deleted.
223*d9f75844SAndroid Build Coastguard Worker   std::vector<Connection*> connections_;
224*d9f75844SAndroid Build Coastguard Worker   webrtc::ScopedTaskSafety task_safety_;
225*d9f75844SAndroid Build Coastguard Worker };
226*d9f75844SAndroid Build Coastguard Worker 
TurnPort(TaskQueueBase * thread,rtc::PacketSocketFactory * factory,const rtc::Network * network,rtc::AsyncPacketSocket * socket,absl::string_view username,absl::string_view password,const ProtocolAddress & server_address,const RelayCredentials & credentials,int server_priority,const std::vector<std::string> & tls_alpn_protocols,const std::vector<std::string> & tls_elliptic_curves,webrtc::TurnCustomizer * customizer,rtc::SSLCertificateVerifier * tls_cert_verifier,const webrtc::FieldTrialsView * field_trials)227*d9f75844SAndroid Build Coastguard Worker TurnPort::TurnPort(TaskQueueBase* thread,
228*d9f75844SAndroid Build Coastguard Worker                    rtc::PacketSocketFactory* factory,
229*d9f75844SAndroid Build Coastguard Worker                    const rtc::Network* network,
230*d9f75844SAndroid Build Coastguard Worker                    rtc::AsyncPacketSocket* socket,
231*d9f75844SAndroid Build Coastguard Worker                    absl::string_view username,
232*d9f75844SAndroid Build Coastguard Worker                    absl::string_view password,
233*d9f75844SAndroid Build Coastguard Worker                    const ProtocolAddress& server_address,
234*d9f75844SAndroid Build Coastguard Worker                    const RelayCredentials& credentials,
235*d9f75844SAndroid Build Coastguard Worker                    int server_priority,
236*d9f75844SAndroid Build Coastguard Worker                    const std::vector<std::string>& tls_alpn_protocols,
237*d9f75844SAndroid Build Coastguard Worker                    const std::vector<std::string>& tls_elliptic_curves,
238*d9f75844SAndroid Build Coastguard Worker                    webrtc::TurnCustomizer* customizer,
239*d9f75844SAndroid Build Coastguard Worker                    rtc::SSLCertificateVerifier* tls_cert_verifier,
240*d9f75844SAndroid Build Coastguard Worker                    const webrtc::FieldTrialsView* field_trials)
241*d9f75844SAndroid Build Coastguard Worker     : Port(thread,
242*d9f75844SAndroid Build Coastguard Worker            RELAY_PORT_TYPE,
243*d9f75844SAndroid Build Coastguard Worker            factory,
244*d9f75844SAndroid Build Coastguard Worker            network,
245*d9f75844SAndroid Build Coastguard Worker            username,
246*d9f75844SAndroid Build Coastguard Worker            password,
247*d9f75844SAndroid Build Coastguard Worker            field_trials),
248*d9f75844SAndroid Build Coastguard Worker       server_address_(server_address),
249*d9f75844SAndroid Build Coastguard Worker       tls_alpn_protocols_(tls_alpn_protocols),
250*d9f75844SAndroid Build Coastguard Worker       tls_elliptic_curves_(tls_elliptic_curves),
251*d9f75844SAndroid Build Coastguard Worker       tls_cert_verifier_(tls_cert_verifier),
252*d9f75844SAndroid Build Coastguard Worker       credentials_(credentials),
253*d9f75844SAndroid Build Coastguard Worker       socket_(socket),
254*d9f75844SAndroid Build Coastguard Worker       error_(0),
255*d9f75844SAndroid Build Coastguard Worker       stun_dscp_value_(rtc::DSCP_NO_CHANGE),
256*d9f75844SAndroid Build Coastguard Worker       request_manager_(
257*d9f75844SAndroid Build Coastguard Worker           thread,
258*d9f75844SAndroid Build Coastguard Worker           [this](const void* data, size_t size, StunRequest* request) {
259*d9f75844SAndroid Build Coastguard Worker             OnSendStunPacket(data, size, request);
260*d9f75844SAndroid Build Coastguard Worker           }),
261*d9f75844SAndroid Build Coastguard Worker       next_channel_number_(TURN_CHANNEL_NUMBER_START),
262*d9f75844SAndroid Build Coastguard Worker       state_(STATE_CONNECTING),
263*d9f75844SAndroid Build Coastguard Worker       server_priority_(server_priority),
264*d9f75844SAndroid Build Coastguard Worker       allocate_mismatch_retries_(0),
265*d9f75844SAndroid Build Coastguard Worker       turn_customizer_(customizer) {}
266*d9f75844SAndroid Build Coastguard Worker 
TurnPort(TaskQueueBase * thread,rtc::PacketSocketFactory * factory,const rtc::Network * network,uint16_t min_port,uint16_t max_port,absl::string_view username,absl::string_view password,const ProtocolAddress & server_address,const RelayCredentials & credentials,int server_priority,const std::vector<std::string> & tls_alpn_protocols,const std::vector<std::string> & tls_elliptic_curves,webrtc::TurnCustomizer * customizer,rtc::SSLCertificateVerifier * tls_cert_verifier,const webrtc::FieldTrialsView * field_trials)267*d9f75844SAndroid Build Coastguard Worker TurnPort::TurnPort(TaskQueueBase* thread,
268*d9f75844SAndroid Build Coastguard Worker                    rtc::PacketSocketFactory* factory,
269*d9f75844SAndroid Build Coastguard Worker                    const rtc::Network* network,
270*d9f75844SAndroid Build Coastguard Worker                    uint16_t min_port,
271*d9f75844SAndroid Build Coastguard Worker                    uint16_t max_port,
272*d9f75844SAndroid Build Coastguard Worker                    absl::string_view username,
273*d9f75844SAndroid Build Coastguard Worker                    absl::string_view password,
274*d9f75844SAndroid Build Coastguard Worker                    const ProtocolAddress& server_address,
275*d9f75844SAndroid Build Coastguard Worker                    const RelayCredentials& credentials,
276*d9f75844SAndroid Build Coastguard Worker                    int server_priority,
277*d9f75844SAndroid Build Coastguard Worker                    const std::vector<std::string>& tls_alpn_protocols,
278*d9f75844SAndroid Build Coastguard Worker                    const std::vector<std::string>& tls_elliptic_curves,
279*d9f75844SAndroid Build Coastguard Worker                    webrtc::TurnCustomizer* customizer,
280*d9f75844SAndroid Build Coastguard Worker                    rtc::SSLCertificateVerifier* tls_cert_verifier,
281*d9f75844SAndroid Build Coastguard Worker                    const webrtc::FieldTrialsView* field_trials)
282*d9f75844SAndroid Build Coastguard Worker     : Port(thread,
283*d9f75844SAndroid Build Coastguard Worker            RELAY_PORT_TYPE,
284*d9f75844SAndroid Build Coastguard Worker            factory,
285*d9f75844SAndroid Build Coastguard Worker            network,
286*d9f75844SAndroid Build Coastguard Worker            min_port,
287*d9f75844SAndroid Build Coastguard Worker            max_port,
288*d9f75844SAndroid Build Coastguard Worker            username,
289*d9f75844SAndroid Build Coastguard Worker            password,
290*d9f75844SAndroid Build Coastguard Worker            field_trials),
291*d9f75844SAndroid Build Coastguard Worker       server_address_(server_address),
292*d9f75844SAndroid Build Coastguard Worker       tls_alpn_protocols_(tls_alpn_protocols),
293*d9f75844SAndroid Build Coastguard Worker       tls_elliptic_curves_(tls_elliptic_curves),
294*d9f75844SAndroid Build Coastguard Worker       tls_cert_verifier_(tls_cert_verifier),
295*d9f75844SAndroid Build Coastguard Worker       credentials_(credentials),
296*d9f75844SAndroid Build Coastguard Worker       socket_(nullptr),
297*d9f75844SAndroid Build Coastguard Worker       error_(0),
298*d9f75844SAndroid Build Coastguard Worker       stun_dscp_value_(rtc::DSCP_NO_CHANGE),
299*d9f75844SAndroid Build Coastguard Worker       request_manager_(
300*d9f75844SAndroid Build Coastguard Worker           thread,
301*d9f75844SAndroid Build Coastguard Worker           [this](const void* data, size_t size, StunRequest* request) {
302*d9f75844SAndroid Build Coastguard Worker             OnSendStunPacket(data, size, request);
303*d9f75844SAndroid Build Coastguard Worker           }),
304*d9f75844SAndroid Build Coastguard Worker       next_channel_number_(TURN_CHANNEL_NUMBER_START),
305*d9f75844SAndroid Build Coastguard Worker       state_(STATE_CONNECTING),
306*d9f75844SAndroid Build Coastguard Worker       server_priority_(server_priority),
307*d9f75844SAndroid Build Coastguard Worker       allocate_mismatch_retries_(0),
308*d9f75844SAndroid Build Coastguard Worker       turn_customizer_(customizer) {}
309*d9f75844SAndroid Build Coastguard Worker 
~TurnPort()310*d9f75844SAndroid Build Coastguard Worker TurnPort::~TurnPort() {
311*d9f75844SAndroid Build Coastguard Worker   // TODO(juberti): Should this even be necessary?
312*d9f75844SAndroid Build Coastguard Worker 
313*d9f75844SAndroid Build Coastguard Worker   // release the allocation by sending a refresh with
314*d9f75844SAndroid Build Coastguard Worker   // lifetime 0.
315*d9f75844SAndroid Build Coastguard Worker   if (ready()) {
316*d9f75844SAndroid Build Coastguard Worker     Release();
317*d9f75844SAndroid Build Coastguard Worker   }
318*d9f75844SAndroid Build Coastguard Worker 
319*d9f75844SAndroid Build Coastguard Worker   entries_.clear();
320*d9f75844SAndroid Build Coastguard Worker 
321*d9f75844SAndroid Build Coastguard Worker   if (socket_)
322*d9f75844SAndroid Build Coastguard Worker     socket_->UnsubscribeClose(this);
323*d9f75844SAndroid Build Coastguard Worker 
324*d9f75844SAndroid Build Coastguard Worker   if (!SharedSocket()) {
325*d9f75844SAndroid Build Coastguard Worker     delete socket_;
326*d9f75844SAndroid Build Coastguard Worker   }
327*d9f75844SAndroid Build Coastguard Worker }
328*d9f75844SAndroid Build Coastguard Worker 
GetLocalAddress() const329*d9f75844SAndroid Build Coastguard Worker rtc::SocketAddress TurnPort::GetLocalAddress() const {
330*d9f75844SAndroid Build Coastguard Worker   return socket_ ? socket_->GetLocalAddress() : rtc::SocketAddress();
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker 
GetProtocol() const333*d9f75844SAndroid Build Coastguard Worker ProtocolType TurnPort::GetProtocol() const {
334*d9f75844SAndroid Build Coastguard Worker   return server_address_.proto;
335*d9f75844SAndroid Build Coastguard Worker }
336*d9f75844SAndroid Build Coastguard Worker 
GetTlsCertPolicy() const337*d9f75844SAndroid Build Coastguard Worker TlsCertPolicy TurnPort::GetTlsCertPolicy() const {
338*d9f75844SAndroid Build Coastguard Worker   return tls_cert_policy_;
339*d9f75844SAndroid Build Coastguard Worker }
340*d9f75844SAndroid Build Coastguard Worker 
SetTlsCertPolicy(TlsCertPolicy tls_cert_policy)341*d9f75844SAndroid Build Coastguard Worker void TurnPort::SetTlsCertPolicy(TlsCertPolicy tls_cert_policy) {
342*d9f75844SAndroid Build Coastguard Worker   tls_cert_policy_ = tls_cert_policy;
343*d9f75844SAndroid Build Coastguard Worker }
344*d9f75844SAndroid Build Coastguard Worker 
SetTurnLoggingId(absl::string_view turn_logging_id)345*d9f75844SAndroid Build Coastguard Worker void TurnPort::SetTurnLoggingId(absl::string_view turn_logging_id) {
346*d9f75844SAndroid Build Coastguard Worker   turn_logging_id_ = std::string(turn_logging_id);
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker 
GetTlsAlpnProtocols() const349*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> TurnPort::GetTlsAlpnProtocols() const {
350*d9f75844SAndroid Build Coastguard Worker   return tls_alpn_protocols_;
351*d9f75844SAndroid Build Coastguard Worker }
352*d9f75844SAndroid Build Coastguard Worker 
GetTlsEllipticCurves() const353*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> TurnPort::GetTlsEllipticCurves() const {
354*d9f75844SAndroid Build Coastguard Worker   return tls_elliptic_curves_;
355*d9f75844SAndroid Build Coastguard Worker }
356*d9f75844SAndroid Build Coastguard Worker 
PrepareAddress()357*d9f75844SAndroid Build Coastguard Worker void TurnPort::PrepareAddress() {
358*d9f75844SAndroid Build Coastguard Worker   if (credentials_.username.empty() || credentials_.password.empty()) {
359*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Allocation can't be started without setting the"
360*d9f75844SAndroid Build Coastguard Worker                          " TURN server credentials for the user.";
361*d9f75844SAndroid Build Coastguard Worker     OnAllocateError(STUN_ERROR_UNAUTHORIZED,
362*d9f75844SAndroid Build Coastguard Worker                     "Missing TURN server credentials.");
363*d9f75844SAndroid Build Coastguard Worker     return;
364*d9f75844SAndroid Build Coastguard Worker   }
365*d9f75844SAndroid Build Coastguard Worker 
366*d9f75844SAndroid Build Coastguard Worker   if (!server_address_.address.port()) {
367*d9f75844SAndroid Build Coastguard Worker     // We will set default TURN port, if no port is set in the address.
368*d9f75844SAndroid Build Coastguard Worker     server_address_.address.SetPort(TURN_DEFAULT_PORT);
369*d9f75844SAndroid Build Coastguard Worker   }
370*d9f75844SAndroid Build Coastguard Worker 
371*d9f75844SAndroid Build Coastguard Worker   if (!AllowedTurnPort(server_address_.address.port(), &field_trials())) {
372*d9f75844SAndroid Build Coastguard Worker     // This can only happen after a 300 ALTERNATE SERVER, since the port can't
373*d9f75844SAndroid Build Coastguard Worker     // be created with a disallowed port number.
374*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Attempt to start allocation with disallowed port# "
375*d9f75844SAndroid Build Coastguard Worker                       << server_address_.address.port();
376*d9f75844SAndroid Build Coastguard Worker     OnAllocateError(STUN_ERROR_SERVER_ERROR,
377*d9f75844SAndroid Build Coastguard Worker                     "Attempt to start allocation to a disallowed port");
378*d9f75844SAndroid Build Coastguard Worker     return;
379*d9f75844SAndroid Build Coastguard Worker   }
380*d9f75844SAndroid Build Coastguard Worker   if (server_address_.address.IsUnresolvedIP()) {
381*d9f75844SAndroid Build Coastguard Worker     ResolveTurnAddress(server_address_.address);
382*d9f75844SAndroid Build Coastguard Worker   } else {
383*d9f75844SAndroid Build Coastguard Worker     // If protocol family of server address doesn't match with local, return.
384*d9f75844SAndroid Build Coastguard Worker     if (!IsCompatibleAddress(server_address_.address)) {
385*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "IP address family does not match. server: "
386*d9f75844SAndroid Build Coastguard Worker                         << server_address_.address.family()
387*d9f75844SAndroid Build Coastguard Worker                         << " local: " << Network()->GetBestIP().family();
388*d9f75844SAndroid Build Coastguard Worker       OnAllocateError(STUN_ERROR_GLOBAL_FAILURE,
389*d9f75844SAndroid Build Coastguard Worker                       "IP address family does not match.");
390*d9f75844SAndroid Build Coastguard Worker       return;
391*d9f75844SAndroid Build Coastguard Worker     }
392*d9f75844SAndroid Build Coastguard Worker 
393*d9f75844SAndroid Build Coastguard Worker     // Insert the current address to prevent redirection pingpong.
394*d9f75844SAndroid Build Coastguard Worker     attempted_server_addresses_.insert(server_address_.address);
395*d9f75844SAndroid Build Coastguard Worker 
396*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString() << ": Trying to connect to TURN server via "
397*d9f75844SAndroid Build Coastguard Worker                      << ProtoToString(server_address_.proto) << " @ "
398*d9f75844SAndroid Build Coastguard Worker                      << server_address_.address.ToSensitiveString();
399*d9f75844SAndroid Build Coastguard Worker     if (!CreateTurnClientSocket()) {
400*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Failed to create TURN client socket";
401*d9f75844SAndroid Build Coastguard Worker       OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
402*d9f75844SAndroid Build Coastguard Worker                       "Failed to create TURN client socket.");
403*d9f75844SAndroid Build Coastguard Worker       return;
404*d9f75844SAndroid Build Coastguard Worker     }
405*d9f75844SAndroid Build Coastguard Worker     if (server_address_.proto == PROTO_UDP) {
406*d9f75844SAndroid Build Coastguard Worker       // If its UDP, send AllocateRequest now.
407*d9f75844SAndroid Build Coastguard Worker       // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
408*d9f75844SAndroid Build Coastguard Worker       SendRequest(new TurnAllocateRequest(this), 0);
409*d9f75844SAndroid Build Coastguard Worker     }
410*d9f75844SAndroid Build Coastguard Worker   }
411*d9f75844SAndroid Build Coastguard Worker }
412*d9f75844SAndroid Build Coastguard Worker 
CreateTurnClientSocket()413*d9f75844SAndroid Build Coastguard Worker bool TurnPort::CreateTurnClientSocket() {
414*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!socket_ || SharedSocket());
415*d9f75844SAndroid Build Coastguard Worker 
416*d9f75844SAndroid Build Coastguard Worker   if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
417*d9f75844SAndroid Build Coastguard Worker     socket_ = socket_factory()->CreateUdpSocket(
418*d9f75844SAndroid Build Coastguard Worker         rtc::SocketAddress(Network()->GetBestIP(), 0), min_port(), max_port());
419*d9f75844SAndroid Build Coastguard Worker   } else if (server_address_.proto == PROTO_TCP ||
420*d9f75844SAndroid Build Coastguard Worker              server_address_.proto == PROTO_TLS) {
421*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!SharedSocket());
422*d9f75844SAndroid Build Coastguard Worker     int opts = rtc::PacketSocketFactory::OPT_STUN;
423*d9f75844SAndroid Build Coastguard Worker 
424*d9f75844SAndroid Build Coastguard Worker     // Apply server address TLS and insecure bits to options.
425*d9f75844SAndroid Build Coastguard Worker     if (server_address_.proto == PROTO_TLS) {
426*d9f75844SAndroid Build Coastguard Worker       if (tls_cert_policy_ ==
427*d9f75844SAndroid Build Coastguard Worker           TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK) {
428*d9f75844SAndroid Build Coastguard Worker         opts |= rtc::PacketSocketFactory::OPT_TLS_INSECURE;
429*d9f75844SAndroid Build Coastguard Worker       } else {
430*d9f75844SAndroid Build Coastguard Worker         opts |= rtc::PacketSocketFactory::OPT_TLS;
431*d9f75844SAndroid Build Coastguard Worker       }
432*d9f75844SAndroid Build Coastguard Worker     }
433*d9f75844SAndroid Build Coastguard Worker 
434*d9f75844SAndroid Build Coastguard Worker     rtc::PacketSocketTcpOptions tcp_options;
435*d9f75844SAndroid Build Coastguard Worker     tcp_options.opts = opts;
436*d9f75844SAndroid Build Coastguard Worker     tcp_options.tls_alpn_protocols = tls_alpn_protocols_;
437*d9f75844SAndroid Build Coastguard Worker     tcp_options.tls_elliptic_curves = tls_elliptic_curves_;
438*d9f75844SAndroid Build Coastguard Worker     tcp_options.tls_cert_verifier = tls_cert_verifier_;
439*d9f75844SAndroid Build Coastguard Worker     socket_ = socket_factory()->CreateClientTcpSocket(
440*d9f75844SAndroid Build Coastguard Worker         rtc::SocketAddress(Network()->GetBestIP(), 0), server_address_.address,
441*d9f75844SAndroid Build Coastguard Worker         proxy(), user_agent(), tcp_options);
442*d9f75844SAndroid Build Coastguard Worker   }
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker   if (!socket_) {
445*d9f75844SAndroid Build Coastguard Worker     error_ = SOCKET_ERROR;
446*d9f75844SAndroid Build Coastguard Worker     return false;
447*d9f75844SAndroid Build Coastguard Worker   }
448*d9f75844SAndroid Build Coastguard Worker 
449*d9f75844SAndroid Build Coastguard Worker   // Apply options if any.
450*d9f75844SAndroid Build Coastguard Worker   for (SocketOptionsMap::iterator iter = socket_options_.begin();
451*d9f75844SAndroid Build Coastguard Worker        iter != socket_options_.end(); ++iter) {
452*d9f75844SAndroid Build Coastguard Worker     socket_->SetOption(iter->first, iter->second);
453*d9f75844SAndroid Build Coastguard Worker   }
454*d9f75844SAndroid Build Coastguard Worker 
455*d9f75844SAndroid Build Coastguard Worker   if (!SharedSocket()) {
456*d9f75844SAndroid Build Coastguard Worker     // If socket is shared, AllocationSequence will receive the packet.
457*d9f75844SAndroid Build Coastguard Worker     socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
458*d9f75844SAndroid Build Coastguard Worker   }
459*d9f75844SAndroid Build Coastguard Worker 
460*d9f75844SAndroid Build Coastguard Worker   socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
461*d9f75844SAndroid Build Coastguard Worker 
462*d9f75844SAndroid Build Coastguard Worker   socket_->SignalSentPacket.connect(this, &TurnPort::OnSentPacket);
463*d9f75844SAndroid Build Coastguard Worker 
464*d9f75844SAndroid Build Coastguard Worker   // TCP port is ready to send stun requests after the socket is connected,
465*d9f75844SAndroid Build Coastguard Worker   // while UDP port is ready to do so once the socket is created.
466*d9f75844SAndroid Build Coastguard Worker   if (server_address_.proto == PROTO_TCP ||
467*d9f75844SAndroid Build Coastguard Worker       server_address_.proto == PROTO_TLS) {
468*d9f75844SAndroid Build Coastguard Worker     socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
469*d9f75844SAndroid Build Coastguard Worker     socket_->SubscribeClose(this, [this](rtc::AsyncPacketSocket* s, int err) {
470*d9f75844SAndroid Build Coastguard Worker       OnSocketClose(s, err);
471*d9f75844SAndroid Build Coastguard Worker     });
472*d9f75844SAndroid Build Coastguard Worker   } else {
473*d9f75844SAndroid Build Coastguard Worker     state_ = STATE_CONNECTED;
474*d9f75844SAndroid Build Coastguard Worker   }
475*d9f75844SAndroid Build Coastguard Worker   return true;
476*d9f75844SAndroid Build Coastguard Worker }
477*d9f75844SAndroid Build Coastguard Worker 
OnSocketConnect(rtc::AsyncPacketSocket * socket)478*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
479*d9f75844SAndroid Build Coastguard Worker   // This slot should only be invoked if we're using a connection-oriented
480*d9f75844SAndroid Build Coastguard Worker   // protocol.
481*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(server_address_.proto == PROTO_TCP ||
482*d9f75844SAndroid Build Coastguard Worker              server_address_.proto == PROTO_TLS);
483*d9f75844SAndroid Build Coastguard Worker 
484*d9f75844SAndroid Build Coastguard Worker   // Do not use this port if the socket bound to an address not associated with
485*d9f75844SAndroid Build Coastguard Worker   // the desired network interface. This is seen in Chrome, where TCP sockets
486*d9f75844SAndroid Build Coastguard Worker   // cannot be given a binding address, and the platform is expected to pick
487*d9f75844SAndroid Build Coastguard Worker   // the correct local address.
488*d9f75844SAndroid Build Coastguard Worker   //
489*d9f75844SAndroid Build Coastguard Worker   // However, there are two situations in which we allow the bound address to
490*d9f75844SAndroid Build Coastguard Worker   // not be one of the addresses of the requested interface:
491*d9f75844SAndroid Build Coastguard Worker   // 1. The bound address is the loopback address. This happens when a proxy
492*d9f75844SAndroid Build Coastguard Worker   // forces TCP to bind to only the localhost address (see issue 3927).
493*d9f75844SAndroid Build Coastguard Worker   // 2. The bound address is the "any address". This happens when
494*d9f75844SAndroid Build Coastguard Worker   // multiple_routes is disabled (see issue 4780).
495*d9f75844SAndroid Build Coastguard Worker   //
496*d9f75844SAndroid Build Coastguard Worker   // Note that, aside from minor differences in log statements, this logic is
497*d9f75844SAndroid Build Coastguard Worker   // identical to that in TcpPort.
498*d9f75844SAndroid Build Coastguard Worker   const rtc::SocketAddress& socket_address = socket->GetLocalAddress();
499*d9f75844SAndroid Build Coastguard Worker   if (absl::c_none_of(Network()->GetIPs(),
500*d9f75844SAndroid Build Coastguard Worker                       [socket_address](const rtc::InterfaceAddress& addr) {
501*d9f75844SAndroid Build Coastguard Worker                         return socket_address.ipaddr() == addr;
502*d9f75844SAndroid Build Coastguard Worker                       })) {
503*d9f75844SAndroid Build Coastguard Worker     if (socket->GetLocalAddress().IsLoopbackIP()) {
504*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Socket is bound to the address:"
505*d9f75844SAndroid Build Coastguard Worker                           << socket_address.ipaddr().ToSensitiveString()
506*d9f75844SAndroid Build Coastguard Worker                           << ", rather than an address associated with network:"
507*d9f75844SAndroid Build Coastguard Worker                           << Network()->ToString()
508*d9f75844SAndroid Build Coastguard Worker                           << ". Still allowing it since it's localhost.";
509*d9f75844SAndroid Build Coastguard Worker     } else if (IPIsAny(Network()->GetBestIP())) {
510*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING)
511*d9f75844SAndroid Build Coastguard Worker           << "Socket is bound to the address:"
512*d9f75844SAndroid Build Coastguard Worker           << socket_address.ipaddr().ToSensitiveString()
513*d9f75844SAndroid Build Coastguard Worker           << ", rather than an address associated with network:"
514*d9f75844SAndroid Build Coastguard Worker           << Network()->ToString()
515*d9f75844SAndroid Build Coastguard Worker           << ". Still allowing it since it's the 'any' address"
516*d9f75844SAndroid Build Coastguard Worker              ", possibly caused by multiple_routes being disabled.";
517*d9f75844SAndroid Build Coastguard Worker     } else {
518*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Socket is bound to the address:"
519*d9f75844SAndroid Build Coastguard Worker                           << socket_address.ipaddr().ToSensitiveString()
520*d9f75844SAndroid Build Coastguard Worker                           << ", rather than an address associated with network:"
521*d9f75844SAndroid Build Coastguard Worker                           << Network()->ToString() << ". Discarding TURN port.";
522*d9f75844SAndroid Build Coastguard Worker       OnAllocateError(
523*d9f75844SAndroid Build Coastguard Worker           STUN_ERROR_GLOBAL_FAILURE,
524*d9f75844SAndroid Build Coastguard Worker           "Address not associated with the desired network interface.");
525*d9f75844SAndroid Build Coastguard Worker       return;
526*d9f75844SAndroid Build Coastguard Worker     }
527*d9f75844SAndroid Build Coastguard Worker   }
528*d9f75844SAndroid Build Coastguard Worker 
529*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_CONNECTED;  // It is ready to send stun requests.
530*d9f75844SAndroid Build Coastguard Worker   if (server_address_.address.IsUnresolvedIP()) {
531*d9f75844SAndroid Build Coastguard Worker     server_address_.address = socket_->GetRemoteAddress();
532*d9f75844SAndroid Build Coastguard Worker   }
533*d9f75844SAndroid Build Coastguard Worker 
534*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "TurnPort connected to "
535*d9f75844SAndroid Build Coastguard Worker                    << socket->GetRemoteAddress().ToSensitiveString()
536*d9f75844SAndroid Build Coastguard Worker                    << " using tcp.";
537*d9f75844SAndroid Build Coastguard Worker   SendRequest(new TurnAllocateRequest(this), 0);
538*d9f75844SAndroid Build Coastguard Worker }
539*d9f75844SAndroid Build Coastguard Worker 
OnSocketClose(rtc::AsyncPacketSocket * socket,int error)540*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
541*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << ToString()
542*d9f75844SAndroid Build Coastguard Worker                       << ": Connection with server failed with error: "
543*d9f75844SAndroid Build Coastguard Worker                       << error;
544*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(socket == socket_);
545*d9f75844SAndroid Build Coastguard Worker   Close();
546*d9f75844SAndroid Build Coastguard Worker }
547*d9f75844SAndroid Build Coastguard Worker 
OnAllocateMismatch()548*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnAllocateMismatch() {
549*d9f75844SAndroid Build Coastguard Worker   if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
550*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString() << ": Giving up on the port after "
551*d9f75844SAndroid Build Coastguard Worker                         << allocate_mismatch_retries_
552*d9f75844SAndroid Build Coastguard Worker                         << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
553*d9f75844SAndroid Build Coastguard Worker     OnAllocateError(STUN_ERROR_ALLOCATION_MISMATCH,
554*d9f75844SAndroid Build Coastguard Worker                     "Maximum retries reached for allocation mismatch.");
555*d9f75844SAndroid Build Coastguard Worker     return;
556*d9f75844SAndroid Build Coastguard Worker   }
557*d9f75844SAndroid Build Coastguard Worker 
558*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString()
559*d9f75844SAndroid Build Coastguard Worker                    << ": Allocating a new socket after "
560*d9f75844SAndroid Build Coastguard Worker                       "STUN_ERROR_ALLOCATION_MISMATCH, retry: "
561*d9f75844SAndroid Build Coastguard Worker                    << allocate_mismatch_retries_ + 1;
562*d9f75844SAndroid Build Coastguard Worker 
563*d9f75844SAndroid Build Coastguard Worker   socket_->UnsubscribeClose(this);
564*d9f75844SAndroid Build Coastguard Worker 
565*d9f75844SAndroid Build Coastguard Worker   if (SharedSocket()) {
566*d9f75844SAndroid Build Coastguard Worker     ResetSharedSocket();
567*d9f75844SAndroid Build Coastguard Worker   } else {
568*d9f75844SAndroid Build Coastguard Worker     delete socket_;
569*d9f75844SAndroid Build Coastguard Worker   }
570*d9f75844SAndroid Build Coastguard Worker   socket_ = nullptr;
571*d9f75844SAndroid Build Coastguard Worker 
572*d9f75844SAndroid Build Coastguard Worker   ResetNonce();
573*d9f75844SAndroid Build Coastguard Worker   PrepareAddress();
574*d9f75844SAndroid Build Coastguard Worker   ++allocate_mismatch_retries_;
575*d9f75844SAndroid Build Coastguard Worker }
576*d9f75844SAndroid Build Coastguard Worker 
CreateConnection(const Candidate & remote_candidate,CandidateOrigin origin)577*d9f75844SAndroid Build Coastguard Worker Connection* TurnPort::CreateConnection(const Candidate& remote_candidate,
578*d9f75844SAndroid Build Coastguard Worker                                        CandidateOrigin origin) {
579*d9f75844SAndroid Build Coastguard Worker   // TURN-UDP can only connect to UDP candidates.
580*d9f75844SAndroid Build Coastguard Worker   if (!SupportsProtocol(remote_candidate.protocol())) {
581*d9f75844SAndroid Build Coastguard Worker     return nullptr;
582*d9f75844SAndroid Build Coastguard Worker   }
583*d9f75844SAndroid Build Coastguard Worker 
584*d9f75844SAndroid Build Coastguard Worker   if (state_ == STATE_DISCONNECTED || state_ == STATE_RECEIVEONLY) {
585*d9f75844SAndroid Build Coastguard Worker     return nullptr;
586*d9f75844SAndroid Build Coastguard Worker   }
587*d9f75844SAndroid Build Coastguard Worker 
588*d9f75844SAndroid Build Coastguard Worker   // If the remote endpoint signaled us an mDNS candidate, we do not form a pair
589*d9f75844SAndroid Build Coastguard Worker   // with the relay candidate to avoid IP leakage in the CreatePermission
590*d9f75844SAndroid Build Coastguard Worker   // request.
591*d9f75844SAndroid Build Coastguard Worker   if (absl::EndsWith(remote_candidate.address().hostname(), LOCAL_TLD)) {
592*d9f75844SAndroid Build Coastguard Worker     return nullptr;
593*d9f75844SAndroid Build Coastguard Worker   }
594*d9f75844SAndroid Build Coastguard Worker 
595*d9f75844SAndroid Build Coastguard Worker   // A TURN port will have two candidates, STUN and TURN. STUN may not
596*d9f75844SAndroid Build Coastguard Worker   // present in all cases. If present stun candidate will be added first
597*d9f75844SAndroid Build Coastguard Worker   // and TURN candidate later.
598*d9f75844SAndroid Build Coastguard Worker   for (size_t index = 0; index < Candidates().size(); ++index) {
599*d9f75844SAndroid Build Coastguard Worker     const Candidate& local_candidate = Candidates()[index];
600*d9f75844SAndroid Build Coastguard Worker     if (local_candidate.type() == RELAY_PORT_TYPE &&
601*d9f75844SAndroid Build Coastguard Worker         local_candidate.address().family() ==
602*d9f75844SAndroid Build Coastguard Worker             remote_candidate.address().family()) {
603*d9f75844SAndroid Build Coastguard Worker       ProxyConnection* conn =
604*d9f75844SAndroid Build Coastguard Worker           new ProxyConnection(NewWeakPtr(), index, remote_candidate);
605*d9f75844SAndroid Build Coastguard Worker       // Create an entry, if needed, so we can get our permissions set up
606*d9f75844SAndroid Build Coastguard Worker       // correctly.
607*d9f75844SAndroid Build Coastguard Worker       if (CreateOrRefreshEntry(conn, next_channel_number_)) {
608*d9f75844SAndroid Build Coastguard Worker         next_channel_number_++;
609*d9f75844SAndroid Build Coastguard Worker       }
610*d9f75844SAndroid Build Coastguard Worker       AddOrReplaceConnection(conn);
611*d9f75844SAndroid Build Coastguard Worker       return conn;
612*d9f75844SAndroid Build Coastguard Worker     }
613*d9f75844SAndroid Build Coastguard Worker   }
614*d9f75844SAndroid Build Coastguard Worker   return nullptr;
615*d9f75844SAndroid Build Coastguard Worker }
616*d9f75844SAndroid Build Coastguard Worker 
FailAndPruneConnection(const rtc::SocketAddress & address)617*d9f75844SAndroid Build Coastguard Worker bool TurnPort::FailAndPruneConnection(const rtc::SocketAddress& address) {
618*d9f75844SAndroid Build Coastguard Worker   Connection* conn = GetConnection(address);
619*d9f75844SAndroid Build Coastguard Worker   if (conn != nullptr) {
620*d9f75844SAndroid Build Coastguard Worker     conn->FailAndPrune();
621*d9f75844SAndroid Build Coastguard Worker     return true;
622*d9f75844SAndroid Build Coastguard Worker   }
623*d9f75844SAndroid Build Coastguard Worker   return false;
624*d9f75844SAndroid Build Coastguard Worker }
625*d9f75844SAndroid Build Coastguard Worker 
SetOption(rtc::Socket::Option opt,int value)626*d9f75844SAndroid Build Coastguard Worker int TurnPort::SetOption(rtc::Socket::Option opt, int value) {
627*d9f75844SAndroid Build Coastguard Worker   // Remember the last requested DSCP value, for STUN traffic.
628*d9f75844SAndroid Build Coastguard Worker   if (opt == rtc::Socket::OPT_DSCP)
629*d9f75844SAndroid Build Coastguard Worker     stun_dscp_value_ = static_cast<rtc::DiffServCodePoint>(value);
630*d9f75844SAndroid Build Coastguard Worker 
631*d9f75844SAndroid Build Coastguard Worker   if (!socket_) {
632*d9f75844SAndroid Build Coastguard Worker     // If socket is not created yet, these options will be applied during socket
633*d9f75844SAndroid Build Coastguard Worker     // creation.
634*d9f75844SAndroid Build Coastguard Worker     socket_options_[opt] = value;
635*d9f75844SAndroid Build Coastguard Worker     return 0;
636*d9f75844SAndroid Build Coastguard Worker   }
637*d9f75844SAndroid Build Coastguard Worker   return socket_->SetOption(opt, value);
638*d9f75844SAndroid Build Coastguard Worker }
639*d9f75844SAndroid Build Coastguard Worker 
GetOption(rtc::Socket::Option opt,int * value)640*d9f75844SAndroid Build Coastguard Worker int TurnPort::GetOption(rtc::Socket::Option opt, int* value) {
641*d9f75844SAndroid Build Coastguard Worker   if (!socket_) {
642*d9f75844SAndroid Build Coastguard Worker     SocketOptionsMap::const_iterator it = socket_options_.find(opt);
643*d9f75844SAndroid Build Coastguard Worker     if (it == socket_options_.end()) {
644*d9f75844SAndroid Build Coastguard Worker       return -1;
645*d9f75844SAndroid Build Coastguard Worker     }
646*d9f75844SAndroid Build Coastguard Worker     *value = it->second;
647*d9f75844SAndroid Build Coastguard Worker     return 0;
648*d9f75844SAndroid Build Coastguard Worker   }
649*d9f75844SAndroid Build Coastguard Worker 
650*d9f75844SAndroid Build Coastguard Worker   return socket_->GetOption(opt, value);
651*d9f75844SAndroid Build Coastguard Worker }
652*d9f75844SAndroid Build Coastguard Worker 
GetError()653*d9f75844SAndroid Build Coastguard Worker int TurnPort::GetError() {
654*d9f75844SAndroid Build Coastguard Worker   return error_;
655*d9f75844SAndroid Build Coastguard Worker }
656*d9f75844SAndroid Build Coastguard Worker 
SendTo(const void * data,size_t size,const rtc::SocketAddress & addr,const rtc::PacketOptions & options,bool payload)657*d9f75844SAndroid Build Coastguard Worker int TurnPort::SendTo(const void* data,
658*d9f75844SAndroid Build Coastguard Worker                      size_t size,
659*d9f75844SAndroid Build Coastguard Worker                      const rtc::SocketAddress& addr,
660*d9f75844SAndroid Build Coastguard Worker                      const rtc::PacketOptions& options,
661*d9f75844SAndroid Build Coastguard Worker                      bool payload) {
662*d9f75844SAndroid Build Coastguard Worker   // Try to find an entry for this specific address; we should have one.
663*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry = FindEntry(addr);
664*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(entry);
665*d9f75844SAndroid Build Coastguard Worker 
666*d9f75844SAndroid Build Coastguard Worker   if (!ready()) {
667*d9f75844SAndroid Build Coastguard Worker     error_ = ENOTCONN;
668*d9f75844SAndroid Build Coastguard Worker     return SOCKET_ERROR;
669*d9f75844SAndroid Build Coastguard Worker   }
670*d9f75844SAndroid Build Coastguard Worker 
671*d9f75844SAndroid Build Coastguard Worker   // Send the actual contents to the server using the usual mechanism.
672*d9f75844SAndroid Build Coastguard Worker   rtc::PacketOptions modified_options(options);
673*d9f75844SAndroid Build Coastguard Worker   CopyPortInformationToPacketInfo(&modified_options.info_signaled_after_sent);
674*d9f75844SAndroid Build Coastguard Worker   int sent = entry->Send(data, size, payload, modified_options);
675*d9f75844SAndroid Build Coastguard Worker   if (sent <= 0) {
676*d9f75844SAndroid Build Coastguard Worker     error_ = socket_->GetError();
677*d9f75844SAndroid Build Coastguard Worker     return SOCKET_ERROR;
678*d9f75844SAndroid Build Coastguard Worker   }
679*d9f75844SAndroid Build Coastguard Worker 
680*d9f75844SAndroid Build Coastguard Worker   // The caller of the function is expecting the number of user data bytes,
681*d9f75844SAndroid Build Coastguard Worker   // rather than the size of the packet.
682*d9f75844SAndroid Build Coastguard Worker   return static_cast<int>(size);
683*d9f75844SAndroid Build Coastguard Worker }
684*d9f75844SAndroid Build Coastguard Worker 
CanHandleIncomingPacketsFrom(const rtc::SocketAddress & addr) const685*d9f75844SAndroid Build Coastguard Worker bool TurnPort::CanHandleIncomingPacketsFrom(
686*d9f75844SAndroid Build Coastguard Worker     const rtc::SocketAddress& addr) const {
687*d9f75844SAndroid Build Coastguard Worker   return server_address_.address == addr;
688*d9f75844SAndroid Build Coastguard Worker }
689*d9f75844SAndroid Build Coastguard Worker 
HandleIncomingPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,int64_t packet_time_us)690*d9f75844SAndroid Build Coastguard Worker bool TurnPort::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
691*d9f75844SAndroid Build Coastguard Worker                                     const char* data,
692*d9f75844SAndroid Build Coastguard Worker                                     size_t size,
693*d9f75844SAndroid Build Coastguard Worker                                     const rtc::SocketAddress& remote_addr,
694*d9f75844SAndroid Build Coastguard Worker                                     int64_t packet_time_us) {
695*d9f75844SAndroid Build Coastguard Worker   if (socket != socket_) {
696*d9f75844SAndroid Build Coastguard Worker     // The packet was received on a shared socket after we've allocated a new
697*d9f75844SAndroid Build Coastguard Worker     // socket for this TURN port.
698*d9f75844SAndroid Build Coastguard Worker     return false;
699*d9f75844SAndroid Build Coastguard Worker   }
700*d9f75844SAndroid Build Coastguard Worker 
701*d9f75844SAndroid Build Coastguard Worker   // This is to guard against a STUN response from previous server after
702*d9f75844SAndroid Build Coastguard Worker   // alternative server redirection. TODO(guoweis): add a unit test for this
703*d9f75844SAndroid Build Coastguard Worker   // race condition.
704*d9f75844SAndroid Build Coastguard Worker   if (remote_addr != server_address_.address) {
705*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
706*d9f75844SAndroid Build Coastguard Worker                         << ": Discarding TURN message from unknown address: "
707*d9f75844SAndroid Build Coastguard Worker                         << remote_addr.ToSensitiveString()
708*d9f75844SAndroid Build Coastguard Worker                         << " server_address_: "
709*d9f75844SAndroid Build Coastguard Worker                         << server_address_.address.ToSensitiveString();
710*d9f75844SAndroid Build Coastguard Worker     return false;
711*d9f75844SAndroid Build Coastguard Worker   }
712*d9f75844SAndroid Build Coastguard Worker 
713*d9f75844SAndroid Build Coastguard Worker   // The message must be at least the size of a channel header.
714*d9f75844SAndroid Build Coastguard Worker   if (size < TURN_CHANNEL_HEADER_SIZE) {
715*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
716*d9f75844SAndroid Build Coastguard Worker                         << ": Received TURN message that was too short";
717*d9f75844SAndroid Build Coastguard Worker     return false;
718*d9f75844SAndroid Build Coastguard Worker   }
719*d9f75844SAndroid Build Coastguard Worker 
720*d9f75844SAndroid Build Coastguard Worker   if (state_ == STATE_DISCONNECTED) {
721*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING)
722*d9f75844SAndroid Build Coastguard Worker         << ToString()
723*d9f75844SAndroid Build Coastguard Worker         << ": Received TURN message while the TURN port is disconnected";
724*d9f75844SAndroid Build Coastguard Worker     return false;
725*d9f75844SAndroid Build Coastguard Worker   }
726*d9f75844SAndroid Build Coastguard Worker 
727*d9f75844SAndroid Build Coastguard Worker   // Check the message type, to see if is a Channel Data message.
728*d9f75844SAndroid Build Coastguard Worker   // The message will either be channel data, a TURN data indication, or
729*d9f75844SAndroid Build Coastguard Worker   // a response to a previous request.
730*d9f75844SAndroid Build Coastguard Worker   uint16_t msg_type = rtc::GetBE16(data);
731*d9f75844SAndroid Build Coastguard Worker   if (IsTurnChannelData(msg_type)) {
732*d9f75844SAndroid Build Coastguard Worker     HandleChannelData(msg_type, data, size, packet_time_us);
733*d9f75844SAndroid Build Coastguard Worker     return true;
734*d9f75844SAndroid Build Coastguard Worker   }
735*d9f75844SAndroid Build Coastguard Worker 
736*d9f75844SAndroid Build Coastguard Worker   if (msg_type == TURN_DATA_INDICATION) {
737*d9f75844SAndroid Build Coastguard Worker     HandleDataIndication(data, size, packet_time_us);
738*d9f75844SAndroid Build Coastguard Worker     return true;
739*d9f75844SAndroid Build Coastguard Worker   }
740*d9f75844SAndroid Build Coastguard Worker 
741*d9f75844SAndroid Build Coastguard Worker   if (SharedSocket() && (msg_type == STUN_BINDING_RESPONSE ||
742*d9f75844SAndroid Build Coastguard Worker                          msg_type == STUN_BINDING_ERROR_RESPONSE)) {
743*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_VERBOSE)
744*d9f75844SAndroid Build Coastguard Worker         << ToString()
745*d9f75844SAndroid Build Coastguard Worker         << ": Ignoring STUN binding response message on shared socket.";
746*d9f75844SAndroid Build Coastguard Worker     return false;
747*d9f75844SAndroid Build Coastguard Worker   }
748*d9f75844SAndroid Build Coastguard Worker 
749*d9f75844SAndroid Build Coastguard Worker   request_manager_.CheckResponse(data, size);
750*d9f75844SAndroid Build Coastguard Worker 
751*d9f75844SAndroid Build Coastguard Worker   return true;
752*d9f75844SAndroid Build Coastguard Worker }
753*d9f75844SAndroid Build Coastguard Worker 
OnReadPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,const int64_t & packet_time_us)754*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnReadPacket(rtc::AsyncPacketSocket* socket,
755*d9f75844SAndroid Build Coastguard Worker                             const char* data,
756*d9f75844SAndroid Build Coastguard Worker                             size_t size,
757*d9f75844SAndroid Build Coastguard Worker                             const rtc::SocketAddress& remote_addr,
758*d9f75844SAndroid Build Coastguard Worker                             const int64_t& packet_time_us) {
759*d9f75844SAndroid Build Coastguard Worker   HandleIncomingPacket(socket, data, size, remote_addr, packet_time_us);
760*d9f75844SAndroid Build Coastguard Worker }
761*d9f75844SAndroid Build Coastguard Worker 
OnSentPacket(rtc::AsyncPacketSocket * socket,const rtc::SentPacket & sent_packet)762*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnSentPacket(rtc::AsyncPacketSocket* socket,
763*d9f75844SAndroid Build Coastguard Worker                             const rtc::SentPacket& sent_packet) {
764*d9f75844SAndroid Build Coastguard Worker   PortInterface::SignalSentPacket(sent_packet);
765*d9f75844SAndroid Build Coastguard Worker }
766*d9f75844SAndroid Build Coastguard Worker 
OnReadyToSend(rtc::AsyncPacketSocket * socket)767*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
768*d9f75844SAndroid Build Coastguard Worker   if (ready()) {
769*d9f75844SAndroid Build Coastguard Worker     Port::OnReadyToSend();
770*d9f75844SAndroid Build Coastguard Worker   }
771*d9f75844SAndroid Build Coastguard Worker }
772*d9f75844SAndroid Build Coastguard Worker 
SupportsProtocol(absl::string_view protocol) const773*d9f75844SAndroid Build Coastguard Worker bool TurnPort::SupportsProtocol(absl::string_view protocol) const {
774*d9f75844SAndroid Build Coastguard Worker   // Turn port only connects to UDP candidates.
775*d9f75844SAndroid Build Coastguard Worker   return protocol == UDP_PROTOCOL_NAME;
776*d9f75844SAndroid Build Coastguard Worker }
777*d9f75844SAndroid Build Coastguard Worker 
778*d9f75844SAndroid Build Coastguard Worker // Update current server address port with the alternate server address port.
SetAlternateServer(const rtc::SocketAddress & address)779*d9f75844SAndroid Build Coastguard Worker bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
780*d9f75844SAndroid Build Coastguard Worker   // Check if we have seen this address before and reject if we did.
781*d9f75844SAndroid Build Coastguard Worker   AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
782*d9f75844SAndroid Build Coastguard Worker   if (iter != attempted_server_addresses_.end()) {
783*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString() << ": Redirection to ["
784*d9f75844SAndroid Build Coastguard Worker                         << address.ToSensitiveString()
785*d9f75844SAndroid Build Coastguard Worker                         << "] ignored, allocation failed.";
786*d9f75844SAndroid Build Coastguard Worker     return false;
787*d9f75844SAndroid Build Coastguard Worker   }
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker   // If protocol family of server address doesn't match with local, return.
790*d9f75844SAndroid Build Coastguard Worker   if (!IsCompatibleAddress(address)) {
791*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Server IP address family does not match with "
792*d9f75844SAndroid Build Coastguard Worker                            "local host address family type";
793*d9f75844SAndroid Build Coastguard Worker     return false;
794*d9f75844SAndroid Build Coastguard Worker   }
795*d9f75844SAndroid Build Coastguard Worker 
796*d9f75844SAndroid Build Coastguard Worker   // Block redirects to a loopback address.
797*d9f75844SAndroid Build Coastguard Worker   // See: https://bugs.chromium.org/p/chromium/issues/detail?id=649118
798*d9f75844SAndroid Build Coastguard Worker   if (address.IsLoopbackIP()) {
799*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
800*d9f75844SAndroid Build Coastguard Worker                         << ": Blocking attempted redirect to loopback address.";
801*d9f75844SAndroid Build Coastguard Worker     return false;
802*d9f75844SAndroid Build Coastguard Worker   }
803*d9f75844SAndroid Build Coastguard Worker 
804*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": Redirecting from TURN server ["
805*d9f75844SAndroid Build Coastguard Worker                    << server_address_.address.ToSensitiveString()
806*d9f75844SAndroid Build Coastguard Worker                    << "] to TURN server [" << address.ToSensitiveString()
807*d9f75844SAndroid Build Coastguard Worker                    << "]";
808*d9f75844SAndroid Build Coastguard Worker   server_address_ = ProtocolAddress(address, server_address_.proto);
809*d9f75844SAndroid Build Coastguard Worker 
810*d9f75844SAndroid Build Coastguard Worker   // Insert the current address to prevent redirection pingpong.
811*d9f75844SAndroid Build Coastguard Worker   attempted_server_addresses_.insert(server_address_.address);
812*d9f75844SAndroid Build Coastguard Worker   return true;
813*d9f75844SAndroid Build Coastguard Worker }
814*d9f75844SAndroid Build Coastguard Worker 
ResolveTurnAddress(const rtc::SocketAddress & address)815*d9f75844SAndroid Build Coastguard Worker void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) {
816*d9f75844SAndroid Build Coastguard Worker   if (resolver_)
817*d9f75844SAndroid Build Coastguard Worker     return;
818*d9f75844SAndroid Build Coastguard Worker 
819*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": Starting TURN host lookup for "
820*d9f75844SAndroid Build Coastguard Worker                    << address.ToSensitiveString();
821*d9f75844SAndroid Build Coastguard Worker   resolver_ = socket_factory()->CreateAsyncDnsResolver();
822*d9f75844SAndroid Build Coastguard Worker   auto callback = [this] {
823*d9f75844SAndroid Build Coastguard Worker     // If DNS resolve is failed when trying to connect to the server using TCP,
824*d9f75844SAndroid Build Coastguard Worker     // one of the reason could be due to DNS queries blocked by firewall.
825*d9f75844SAndroid Build Coastguard Worker     // In such cases we will try to connect to the server with hostname,
826*d9f75844SAndroid Build Coastguard Worker     // assuming socket layer will resolve the hostname through a HTTP proxy (if
827*d9f75844SAndroid Build Coastguard Worker     // any).
828*d9f75844SAndroid Build Coastguard Worker     auto& result = resolver_->result();
829*d9f75844SAndroid Build Coastguard Worker     if (result.GetError() != 0 && (server_address_.proto == PROTO_TCP ||
830*d9f75844SAndroid Build Coastguard Worker                                    server_address_.proto == PROTO_TLS)) {
831*d9f75844SAndroid Build Coastguard Worker       if (!CreateTurnClientSocket()) {
832*d9f75844SAndroid Build Coastguard Worker         OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
833*d9f75844SAndroid Build Coastguard Worker                         "TURN host lookup received error.");
834*d9f75844SAndroid Build Coastguard Worker       }
835*d9f75844SAndroid Build Coastguard Worker       return;
836*d9f75844SAndroid Build Coastguard Worker     }
837*d9f75844SAndroid Build Coastguard Worker 
838*d9f75844SAndroid Build Coastguard Worker     // Copy the original server address in `resolved_address`. For TLS based
839*d9f75844SAndroid Build Coastguard Worker     // sockets we need hostname along with resolved address.
840*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress resolved_address = server_address_.address;
841*d9f75844SAndroid Build Coastguard Worker     if (result.GetError() != 0 ||
842*d9f75844SAndroid Build Coastguard Worker         !result.GetResolvedAddress(Network()->GetBestIP().family(),
843*d9f75844SAndroid Build Coastguard Worker                                    &resolved_address)) {
844*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << ToString() << ": TURN host lookup received error "
845*d9f75844SAndroid Build Coastguard Worker                           << result.GetError();
846*d9f75844SAndroid Build Coastguard Worker       error_ = result.GetError();
847*d9f75844SAndroid Build Coastguard Worker       OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
848*d9f75844SAndroid Build Coastguard Worker                       "TURN host lookup received error.");
849*d9f75844SAndroid Build Coastguard Worker       return;
850*d9f75844SAndroid Build Coastguard Worker     }
851*d9f75844SAndroid Build Coastguard Worker     server_address_.address = resolved_address;
852*d9f75844SAndroid Build Coastguard Worker     PrepareAddress();
853*d9f75844SAndroid Build Coastguard Worker   };
854*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/14733): remove duplicate resolution with STUN port.
855*d9f75844SAndroid Build Coastguard Worker   if (ResolveTurnHostnameForFamily(field_trials())) {
856*d9f75844SAndroid Build Coastguard Worker     resolver_->Start(address, Network()->family(), std::move(callback));
857*d9f75844SAndroid Build Coastguard Worker   } else {
858*d9f75844SAndroid Build Coastguard Worker     resolver_->Start(address, std::move(callback));
859*d9f75844SAndroid Build Coastguard Worker   }
860*d9f75844SAndroid Build Coastguard Worker }
861*d9f75844SAndroid Build Coastguard Worker 
OnSendStunPacket(const void * data,size_t size,StunRequest * request)862*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnSendStunPacket(const void* data,
863*d9f75844SAndroid Build Coastguard Worker                                 size_t size,
864*d9f75844SAndroid Build Coastguard Worker                                 StunRequest* request) {
865*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(connected());
866*d9f75844SAndroid Build Coastguard Worker   rtc::PacketOptions options(StunDscpValue());
867*d9f75844SAndroid Build Coastguard Worker   options.info_signaled_after_sent.packet_type = rtc::PacketType::kTurnMessage;
868*d9f75844SAndroid Build Coastguard Worker   CopyPortInformationToPacketInfo(&options.info_signaled_after_sent);
869*d9f75844SAndroid Build Coastguard Worker   if (Send(data, size, options) < 0) {
870*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << ToString() << ": Failed to send TURN message, error: "
871*d9f75844SAndroid Build Coastguard Worker                       << socket_->GetError();
872*d9f75844SAndroid Build Coastguard Worker   }
873*d9f75844SAndroid Build Coastguard Worker }
874*d9f75844SAndroid Build Coastguard Worker 
OnStunAddress(const rtc::SocketAddress & address)875*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
876*d9f75844SAndroid Build Coastguard Worker   // STUN Port will discover STUN candidate, as it's supplied with first TURN
877*d9f75844SAndroid Build Coastguard Worker   // server address.
878*d9f75844SAndroid Build Coastguard Worker   // Why not using this address? - P2PTransportChannel will start creating
879*d9f75844SAndroid Build Coastguard Worker   // connections after first candidate, which means it could start creating the
880*d9f75844SAndroid Build Coastguard Worker   // connections before TURN candidate added. For that to handle, we need to
881*d9f75844SAndroid Build Coastguard Worker   // supply STUN candidate from this port to UDPPort, and TurnPort should have
882*d9f75844SAndroid Build Coastguard Worker   // handle to UDPPort to pass back the address.
883*d9f75844SAndroid Build Coastguard Worker }
884*d9f75844SAndroid Build Coastguard Worker 
OnAllocateSuccess(const rtc::SocketAddress & address,const rtc::SocketAddress & stun_address)885*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
886*d9f75844SAndroid Build Coastguard Worker                                  const rtc::SocketAddress& stun_address) {
887*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_READY;
888*d9f75844SAndroid Build Coastguard Worker 
889*d9f75844SAndroid Build Coastguard Worker   rtc::SocketAddress related_address = stun_address;
890*d9f75844SAndroid Build Coastguard Worker 
891*d9f75844SAndroid Build Coastguard Worker   // For relayed candidate, Base is the candidate itself.
892*d9f75844SAndroid Build Coastguard Worker   AddAddress(address,          // Candidate address.
893*d9f75844SAndroid Build Coastguard Worker              address,          // Base address.
894*d9f75844SAndroid Build Coastguard Worker              related_address,  // Related address.
895*d9f75844SAndroid Build Coastguard Worker              UDP_PROTOCOL_NAME,
896*d9f75844SAndroid Build Coastguard Worker              ProtoToString(server_address_.proto),  // The first hop protocol.
897*d9f75844SAndroid Build Coastguard Worker              "",  // TCP candidate type, empty for turn candidates.
898*d9f75844SAndroid Build Coastguard Worker              RELAY_PORT_TYPE, GetRelayPreference(server_address_.proto),
899*d9f75844SAndroid Build Coastguard Worker              server_priority_, ReconstructedServerUrl(), true);
900*d9f75844SAndroid Build Coastguard Worker }
901*d9f75844SAndroid Build Coastguard Worker 
OnAllocateError(int error_code,absl::string_view reason)902*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnAllocateError(int error_code, absl::string_view reason) {
903*d9f75844SAndroid Build Coastguard Worker   // We will send SignalPortError asynchronously as this can be sent during
904*d9f75844SAndroid Build Coastguard Worker   // port initialization. This way it will not be blocking other port
905*d9f75844SAndroid Build Coastguard Worker   // creation.
906*d9f75844SAndroid Build Coastguard Worker   thread()->PostTask(
907*d9f75844SAndroid Build Coastguard Worker       SafeTask(task_safety_.flag(), [this] { SignalPortError(this); }));
908*d9f75844SAndroid Build Coastguard Worker   std::string address = GetLocalAddress().HostAsSensitiveURIString();
909*d9f75844SAndroid Build Coastguard Worker   int port = GetLocalAddress().port();
910*d9f75844SAndroid Build Coastguard Worker   if (server_address_.proto == PROTO_TCP &&
911*d9f75844SAndroid Build Coastguard Worker       server_address_.address.IsPrivateIP()) {
912*d9f75844SAndroid Build Coastguard Worker     address.clear();
913*d9f75844SAndroid Build Coastguard Worker     port = 0;
914*d9f75844SAndroid Build Coastguard Worker   }
915*d9f75844SAndroid Build Coastguard Worker   SignalCandidateError(
916*d9f75844SAndroid Build Coastguard Worker       this, IceCandidateErrorEvent(address, port, ReconstructedServerUrl(),
917*d9f75844SAndroid Build Coastguard Worker                                    error_code, reason));
918*d9f75844SAndroid Build Coastguard Worker }
919*d9f75844SAndroid Build Coastguard Worker 
OnRefreshError()920*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnRefreshError() {
921*d9f75844SAndroid Build Coastguard Worker   // Need to clear the requests asynchronously because otherwise, the refresh
922*d9f75844SAndroid Build Coastguard Worker   // request may be deleted twice: once at the end of the message processing
923*d9f75844SAndroid Build Coastguard Worker   // and the other in HandleRefreshError().
924*d9f75844SAndroid Build Coastguard Worker   thread()->PostTask(
925*d9f75844SAndroid Build Coastguard Worker       SafeTask(task_safety_.flag(), [this] { HandleRefreshError(); }));
926*d9f75844SAndroid Build Coastguard Worker }
927*d9f75844SAndroid Build Coastguard Worker 
HandleRefreshError()928*d9f75844SAndroid Build Coastguard Worker void TurnPort::HandleRefreshError() {
929*d9f75844SAndroid Build Coastguard Worker   request_manager_.Clear();
930*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_RECEIVEONLY;
931*d9f75844SAndroid Build Coastguard Worker   // Fail and prune all connections; stop sending data.
932*d9f75844SAndroid Build Coastguard Worker   for (auto kv : connections()) {
933*d9f75844SAndroid Build Coastguard Worker     kv.second->FailAndPrune();
934*d9f75844SAndroid Build Coastguard Worker   }
935*d9f75844SAndroid Build Coastguard Worker }
936*d9f75844SAndroid Build Coastguard Worker 
Release()937*d9f75844SAndroid Build Coastguard Worker void TurnPort::Release() {
938*d9f75844SAndroid Build Coastguard Worker   // Remove any pending refresh requests.
939*d9f75844SAndroid Build Coastguard Worker   request_manager_.Clear();
940*d9f75844SAndroid Build Coastguard Worker 
941*d9f75844SAndroid Build Coastguard Worker   // Send refresh with lifetime 0.
942*d9f75844SAndroid Build Coastguard Worker   TurnRefreshRequest* req = new TurnRefreshRequest(this, 0);
943*d9f75844SAndroid Build Coastguard Worker   SendRequest(req, 0);
944*d9f75844SAndroid Build Coastguard Worker 
945*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_RECEIVEONLY;
946*d9f75844SAndroid Build Coastguard Worker }
947*d9f75844SAndroid Build Coastguard Worker 
Close()948*d9f75844SAndroid Build Coastguard Worker void TurnPort::Close() {
949*d9f75844SAndroid Build Coastguard Worker   if (!ready()) {
950*d9f75844SAndroid Build Coastguard Worker     OnAllocateError(SERVER_NOT_REACHABLE_ERROR, "");
951*d9f75844SAndroid Build Coastguard Worker   }
952*d9f75844SAndroid Build Coastguard Worker   request_manager_.Clear();
953*d9f75844SAndroid Build Coastguard Worker   // Stop the port from creating new connections.
954*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_DISCONNECTED;
955*d9f75844SAndroid Build Coastguard Worker   // Delete all existing connections; stop sending data.
956*d9f75844SAndroid Build Coastguard Worker   DestroyAllConnections();
957*d9f75844SAndroid Build Coastguard Worker   if (callbacks_for_test_) {
958*d9f75844SAndroid Build Coastguard Worker     callbacks_for_test_->OnTurnPortClosed();
959*d9f75844SAndroid Build Coastguard Worker   }
960*d9f75844SAndroid Build Coastguard Worker }
961*d9f75844SAndroid Build Coastguard Worker 
StunDscpValue() const962*d9f75844SAndroid Build Coastguard Worker rtc::DiffServCodePoint TurnPort::StunDscpValue() const {
963*d9f75844SAndroid Build Coastguard Worker   return stun_dscp_value_;
964*d9f75844SAndroid Build Coastguard Worker }
965*d9f75844SAndroid Build Coastguard Worker 
966*d9f75844SAndroid Build Coastguard Worker // static
AllowedTurnPort(int port,const webrtc::FieldTrialsView * field_trials)967*d9f75844SAndroid Build Coastguard Worker bool TurnPort::AllowedTurnPort(int port,
968*d9f75844SAndroid Build Coastguard Worker                                const webrtc::FieldTrialsView* field_trials) {
969*d9f75844SAndroid Build Coastguard Worker   // Port 53, 80 and 443 are used for existing deployments.
970*d9f75844SAndroid Build Coastguard Worker   // Ports above 1024 are assumed to be OK to use.
971*d9f75844SAndroid Build Coastguard Worker   if (port == 53 || port == 80 || port == 443 || port >= 1024) {
972*d9f75844SAndroid Build Coastguard Worker     return true;
973*d9f75844SAndroid Build Coastguard Worker   }
974*d9f75844SAndroid Build Coastguard Worker   // Allow any port if relevant field trial is set. This allows disabling the
975*d9f75844SAndroid Build Coastguard Worker   // check.
976*d9f75844SAndroid Build Coastguard Worker   if (field_trials && field_trials->IsEnabled("WebRTC-Turn-AllowSystemPorts")) {
977*d9f75844SAndroid Build Coastguard Worker     return true;
978*d9f75844SAndroid Build Coastguard Worker   }
979*d9f75844SAndroid Build Coastguard Worker   return false;
980*d9f75844SAndroid Build Coastguard Worker }
981*d9f75844SAndroid Build Coastguard Worker 
TryAlternateServer()982*d9f75844SAndroid Build Coastguard Worker void TurnPort::TryAlternateServer() {
983*d9f75844SAndroid Build Coastguard Worker   if (server_address().proto == PROTO_UDP) {
984*d9f75844SAndroid Build Coastguard Worker     // Send another allocate request to alternate server, with the received
985*d9f75844SAndroid Build Coastguard Worker     // realm and nonce values.
986*d9f75844SAndroid Build Coastguard Worker     SendRequest(new TurnAllocateRequest(this), 0);
987*d9f75844SAndroid Build Coastguard Worker   } else {
988*d9f75844SAndroid Build Coastguard Worker     // Since it's TCP, we have to delete the connected socket and reconnect
989*d9f75844SAndroid Build Coastguard Worker     // with the alternate server. PrepareAddress will send stun binding once
990*d9f75844SAndroid Build Coastguard Worker     // the new socket is connected.
991*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(server_address().proto == PROTO_TCP ||
992*d9f75844SAndroid Build Coastguard Worker                server_address().proto == PROTO_TLS);
993*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!SharedSocket());
994*d9f75844SAndroid Build Coastguard Worker     delete socket_;
995*d9f75844SAndroid Build Coastguard Worker     socket_ = nullptr;
996*d9f75844SAndroid Build Coastguard Worker     PrepareAddress();
997*d9f75844SAndroid Build Coastguard Worker   }
998*d9f75844SAndroid Build Coastguard Worker }
999*d9f75844SAndroid Build Coastguard Worker 
OnAllocateRequestTimeout()1000*d9f75844SAndroid Build Coastguard Worker void TurnPort::OnAllocateRequestTimeout() {
1001*d9f75844SAndroid Build Coastguard Worker   OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
1002*d9f75844SAndroid Build Coastguard Worker                   "TURN allocate request timed out.");
1003*d9f75844SAndroid Build Coastguard Worker }
1004*d9f75844SAndroid Build Coastguard Worker 
HandleDataIndication(const char * data,size_t size,int64_t packet_time_us)1005*d9f75844SAndroid Build Coastguard Worker void TurnPort::HandleDataIndication(const char* data,
1006*d9f75844SAndroid Build Coastguard Worker                                     size_t size,
1007*d9f75844SAndroid Build Coastguard Worker                                     int64_t packet_time_us) {
1008*d9f75844SAndroid Build Coastguard Worker   // Read in the message, and process according to RFC5766, Section 10.4.
1009*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferReader buf(data, size);
1010*d9f75844SAndroid Build Coastguard Worker   TurnMessage msg;
1011*d9f75844SAndroid Build Coastguard Worker   if (!msg.Read(&buf)) {
1012*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1013*d9f75844SAndroid Build Coastguard Worker                         << ": Received invalid TURN data indication";
1014*d9f75844SAndroid Build Coastguard Worker     return;
1015*d9f75844SAndroid Build Coastguard Worker   }
1016*d9f75844SAndroid Build Coastguard Worker 
1017*d9f75844SAndroid Build Coastguard Worker   // Check mandatory attributes.
1018*d9f75844SAndroid Build Coastguard Worker   const StunAddressAttribute* addr_attr =
1019*d9f75844SAndroid Build Coastguard Worker       msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
1020*d9f75844SAndroid Build Coastguard Worker   if (!addr_attr) {
1021*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1022*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
1023*d9f75844SAndroid Build Coastguard Worker                            "in data indication.";
1024*d9f75844SAndroid Build Coastguard Worker     return;
1025*d9f75844SAndroid Build Coastguard Worker   }
1026*d9f75844SAndroid Build Coastguard Worker 
1027*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
1028*d9f75844SAndroid Build Coastguard Worker   if (!data_attr) {
1029*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1030*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_DATA attribute in "
1031*d9f75844SAndroid Build Coastguard Worker                            "data indication.";
1032*d9f75844SAndroid Build Coastguard Worker     return;
1033*d9f75844SAndroid Build Coastguard Worker   }
1034*d9f75844SAndroid Build Coastguard Worker 
1035*d9f75844SAndroid Build Coastguard Worker   // Log a warning if the data didn't come from an address that we think we have
1036*d9f75844SAndroid Build Coastguard Worker   // a permission for.
1037*d9f75844SAndroid Build Coastguard Worker   rtc::SocketAddress ext_addr(addr_attr->GetAddress());
1038*d9f75844SAndroid Build Coastguard Worker   if (!HasPermission(ext_addr.ipaddr())) {
1039*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1040*d9f75844SAndroid Build Coastguard Worker                         << ": Received TURN data indication with unknown "
1041*d9f75844SAndroid Build Coastguard Worker                            "peer address, addr: "
1042*d9f75844SAndroid Build Coastguard Worker                         << ext_addr.ToSensitiveString();
1043*d9f75844SAndroid Build Coastguard Worker   }
1044*d9f75844SAndroid Build Coastguard Worker 
1045*d9f75844SAndroid Build Coastguard Worker   DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr, PROTO_UDP,
1046*d9f75844SAndroid Build Coastguard Worker                  packet_time_us);
1047*d9f75844SAndroid Build Coastguard Worker }
1048*d9f75844SAndroid Build Coastguard Worker 
HandleChannelData(int channel_id,const char * data,size_t size,int64_t packet_time_us)1049*d9f75844SAndroid Build Coastguard Worker void TurnPort::HandleChannelData(int channel_id,
1050*d9f75844SAndroid Build Coastguard Worker                                  const char* data,
1051*d9f75844SAndroid Build Coastguard Worker                                  size_t size,
1052*d9f75844SAndroid Build Coastguard Worker                                  int64_t packet_time_us) {
1053*d9f75844SAndroid Build Coastguard Worker   // Read the message, and process according to RFC5766, Section 11.6.
1054*d9f75844SAndroid Build Coastguard Worker   //    0                   1                   2                   3
1055*d9f75844SAndroid Build Coastguard Worker   //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1056*d9f75844SAndroid Build Coastguard Worker   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1057*d9f75844SAndroid Build Coastguard Worker   //   |         Channel Number        |            Length             |
1058*d9f75844SAndroid Build Coastguard Worker   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1059*d9f75844SAndroid Build Coastguard Worker   //   |                                                               |
1060*d9f75844SAndroid Build Coastguard Worker   //   /                       Application Data                        /
1061*d9f75844SAndroid Build Coastguard Worker   //   /                                                               /
1062*d9f75844SAndroid Build Coastguard Worker   //   |                                                               |
1063*d9f75844SAndroid Build Coastguard Worker   //   |                               +-------------------------------+
1064*d9f75844SAndroid Build Coastguard Worker   //   |                               |
1065*d9f75844SAndroid Build Coastguard Worker   //   +-------------------------------+
1066*d9f75844SAndroid Build Coastguard Worker 
1067*d9f75844SAndroid Build Coastguard Worker   // Extract header fields from the message.
1068*d9f75844SAndroid Build Coastguard Worker   uint16_t len = rtc::GetBE16(data + 2);
1069*d9f75844SAndroid Build Coastguard Worker   if (len > size - TURN_CHANNEL_HEADER_SIZE) {
1070*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1071*d9f75844SAndroid Build Coastguard Worker                         << ": Received TURN channel data message with "
1072*d9f75844SAndroid Build Coastguard Worker                            "incorrect length, len: "
1073*d9f75844SAndroid Build Coastguard Worker                         << len;
1074*d9f75844SAndroid Build Coastguard Worker     return;
1075*d9f75844SAndroid Build Coastguard Worker   }
1076*d9f75844SAndroid Build Coastguard Worker   // Allowing messages larger than `len`, as ChannelData can be padded.
1077*d9f75844SAndroid Build Coastguard Worker 
1078*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry = FindEntry(channel_id);
1079*d9f75844SAndroid Build Coastguard Worker   if (!entry) {
1080*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1081*d9f75844SAndroid Build Coastguard Worker                         << ": Received TURN channel data message for invalid "
1082*d9f75844SAndroid Build Coastguard Worker                            "channel, channel_id: "
1083*d9f75844SAndroid Build Coastguard Worker                         << channel_id;
1084*d9f75844SAndroid Build Coastguard Worker     return;
1085*d9f75844SAndroid Build Coastguard Worker   }
1086*d9f75844SAndroid Build Coastguard Worker 
1087*d9f75844SAndroid Build Coastguard Worker   DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
1088*d9f75844SAndroid Build Coastguard Worker                  PROTO_UDP, packet_time_us);
1089*d9f75844SAndroid Build Coastguard Worker }
1090*d9f75844SAndroid Build Coastguard Worker 
DispatchPacket(const char * data,size_t size,const rtc::SocketAddress & remote_addr,ProtocolType proto,int64_t packet_time_us)1091*d9f75844SAndroid Build Coastguard Worker void TurnPort::DispatchPacket(const char* data,
1092*d9f75844SAndroid Build Coastguard Worker                               size_t size,
1093*d9f75844SAndroid Build Coastguard Worker                               const rtc::SocketAddress& remote_addr,
1094*d9f75844SAndroid Build Coastguard Worker                               ProtocolType proto,
1095*d9f75844SAndroid Build Coastguard Worker                               int64_t packet_time_us) {
1096*d9f75844SAndroid Build Coastguard Worker   if (Connection* conn = GetConnection(remote_addr)) {
1097*d9f75844SAndroid Build Coastguard Worker     conn->OnReadPacket(data, size, packet_time_us);
1098*d9f75844SAndroid Build Coastguard Worker   } else {
1099*d9f75844SAndroid Build Coastguard Worker     Port::OnReadPacket(data, size, remote_addr, proto);
1100*d9f75844SAndroid Build Coastguard Worker   }
1101*d9f75844SAndroid Build Coastguard Worker }
1102*d9f75844SAndroid Build Coastguard Worker 
ScheduleRefresh(uint32_t lifetime)1103*d9f75844SAndroid Build Coastguard Worker bool TurnPort::ScheduleRefresh(uint32_t lifetime) {
1104*d9f75844SAndroid Build Coastguard Worker   // Lifetime is in seconds, delay is in milliseconds.
1105*d9f75844SAndroid Build Coastguard Worker   int delay = 1 * 60 * 1000;
1106*d9f75844SAndroid Build Coastguard Worker 
1107*d9f75844SAndroid Build Coastguard Worker   // Cutoff lifetime bigger than 1h.
1108*d9f75844SAndroid Build Coastguard Worker   constexpr uint32_t max_lifetime = 60 * 60;
1109*d9f75844SAndroid Build Coastguard Worker 
1110*d9f75844SAndroid Build Coastguard Worker   if (lifetime < 2 * 60) {
1111*d9f75844SAndroid Build Coastguard Worker     // The RFC does not mention a lower limit on lifetime.
1112*d9f75844SAndroid Build Coastguard Worker     // So if server sends a value less than 2 minutes, we schedule a refresh
1113*d9f75844SAndroid Build Coastguard Worker     // for half lifetime.
1114*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1115*d9f75844SAndroid Build Coastguard Worker                         << ": Received response with short lifetime: "
1116*d9f75844SAndroid Build Coastguard Worker                         << lifetime << " seconds.";
1117*d9f75844SAndroid Build Coastguard Worker     delay = (lifetime * 1000) / 2;
1118*d9f75844SAndroid Build Coastguard Worker   } else if (lifetime > max_lifetime) {
1119*d9f75844SAndroid Build Coastguard Worker     // Make 1 hour largest delay, and then we schedule a refresh for one minute
1120*d9f75844SAndroid Build Coastguard Worker     // less than max lifetime.
1121*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << ToString()
1122*d9f75844SAndroid Build Coastguard Worker                         << ": Received response with long lifetime: "
1123*d9f75844SAndroid Build Coastguard Worker                         << lifetime << " seconds.";
1124*d9f75844SAndroid Build Coastguard Worker     delay = (max_lifetime - 60) * 1000;
1125*d9f75844SAndroid Build Coastguard Worker   } else {
1126*d9f75844SAndroid Build Coastguard Worker     // Normal case,
1127*d9f75844SAndroid Build Coastguard Worker     // we schedule a refresh for one minute less than requested lifetime.
1128*d9f75844SAndroid Build Coastguard Worker     delay = (lifetime - 60) * 1000;
1129*d9f75844SAndroid Build Coastguard Worker   }
1130*d9f75844SAndroid Build Coastguard Worker 
1131*d9f75844SAndroid Build Coastguard Worker   SendRequest(new TurnRefreshRequest(this), delay);
1132*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": Scheduled refresh in " << delay << "ms.";
1133*d9f75844SAndroid Build Coastguard Worker   return true;
1134*d9f75844SAndroid Build Coastguard Worker }
1135*d9f75844SAndroid Build Coastguard Worker 
SendRequest(StunRequest * req,int delay)1136*d9f75844SAndroid Build Coastguard Worker void TurnPort::SendRequest(StunRequest* req, int delay) {
1137*d9f75844SAndroid Build Coastguard Worker   request_manager_.SendDelayed(req, delay);
1138*d9f75844SAndroid Build Coastguard Worker }
1139*d9f75844SAndroid Build Coastguard Worker 
AddRequestAuthInfo(StunMessage * msg)1140*d9f75844SAndroid Build Coastguard Worker void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
1141*d9f75844SAndroid Build Coastguard Worker   // If we've gotten the necessary data from the server, add it to our request.
1142*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!hash_.empty());
1143*d9f75844SAndroid Build Coastguard Worker   msg->AddAttribute(std::make_unique<StunByteStringAttribute>(
1144*d9f75844SAndroid Build Coastguard Worker       STUN_ATTR_USERNAME, credentials_.username));
1145*d9f75844SAndroid Build Coastguard Worker   msg->AddAttribute(
1146*d9f75844SAndroid Build Coastguard Worker       std::make_unique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
1147*d9f75844SAndroid Build Coastguard Worker   msg->AddAttribute(
1148*d9f75844SAndroid Build Coastguard Worker       std::make_unique<StunByteStringAttribute>(STUN_ATTR_NONCE, nonce_));
1149*d9f75844SAndroid Build Coastguard Worker   const bool success = msg->AddMessageIntegrity(hash());
1150*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(success);
1151*d9f75844SAndroid Build Coastguard Worker }
1152*d9f75844SAndroid Build Coastguard Worker 
Send(const void * data,size_t len,const rtc::PacketOptions & options)1153*d9f75844SAndroid Build Coastguard Worker int TurnPort::Send(const void* data,
1154*d9f75844SAndroid Build Coastguard Worker                    size_t len,
1155*d9f75844SAndroid Build Coastguard Worker                    const rtc::PacketOptions& options) {
1156*d9f75844SAndroid Build Coastguard Worker   return socket_->SendTo(data, len, server_address_.address, options);
1157*d9f75844SAndroid Build Coastguard Worker }
1158*d9f75844SAndroid Build Coastguard Worker 
UpdateHash()1159*d9f75844SAndroid Build Coastguard Worker void TurnPort::UpdateHash() {
1160*d9f75844SAndroid Build Coastguard Worker   const bool success = ComputeStunCredentialHash(credentials_.username, realm_,
1161*d9f75844SAndroid Build Coastguard Worker                                                  credentials_.password, &hash_);
1162*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(success);
1163*d9f75844SAndroid Build Coastguard Worker }
1164*d9f75844SAndroid Build Coastguard Worker 
UpdateNonce(StunMessage * response)1165*d9f75844SAndroid Build Coastguard Worker bool TurnPort::UpdateNonce(StunMessage* response) {
1166*d9f75844SAndroid Build Coastguard Worker   // When stale nonce error received, we should update
1167*d9f75844SAndroid Build Coastguard Worker   // hash and store realm and nonce.
1168*d9f75844SAndroid Build Coastguard Worker   // Check the mandatory attributes.
1169*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* realm_attr =
1170*d9f75844SAndroid Build Coastguard Worker       response->GetByteString(STUN_ATTR_REALM);
1171*d9f75844SAndroid Build Coastguard Worker   if (!realm_attr) {
1172*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
1173*d9f75844SAndroid Build Coastguard Worker                          "stale nonce error response.";
1174*d9f75844SAndroid Build Coastguard Worker     return false;
1175*d9f75844SAndroid Build Coastguard Worker   }
1176*d9f75844SAndroid Build Coastguard Worker   set_realm(realm_attr->string_view());
1177*d9f75844SAndroid Build Coastguard Worker 
1178*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* nonce_attr =
1179*d9f75844SAndroid Build Coastguard Worker       response->GetByteString(STUN_ATTR_NONCE);
1180*d9f75844SAndroid Build Coastguard Worker   if (!nonce_attr) {
1181*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
1182*d9f75844SAndroid Build Coastguard Worker                          "stale nonce error response.";
1183*d9f75844SAndroid Build Coastguard Worker     return false;
1184*d9f75844SAndroid Build Coastguard Worker   }
1185*d9f75844SAndroid Build Coastguard Worker   set_nonce(nonce_attr->string_view());
1186*d9f75844SAndroid Build Coastguard Worker   return true;
1187*d9f75844SAndroid Build Coastguard Worker }
1188*d9f75844SAndroid Build Coastguard Worker 
ResetNonce()1189*d9f75844SAndroid Build Coastguard Worker void TurnPort::ResetNonce() {
1190*d9f75844SAndroid Build Coastguard Worker   hash_.clear();
1191*d9f75844SAndroid Build Coastguard Worker   nonce_.clear();
1192*d9f75844SAndroid Build Coastguard Worker   realm_.clear();
1193*d9f75844SAndroid Build Coastguard Worker }
1194*d9f75844SAndroid Build Coastguard Worker 
HasPermission(const rtc::IPAddress & ipaddr) const1195*d9f75844SAndroid Build Coastguard Worker bool TurnPort::HasPermission(const rtc::IPAddress& ipaddr) const {
1196*d9f75844SAndroid Build Coastguard Worker   return absl::c_any_of(entries_, [&ipaddr](const auto& e) {
1197*d9f75844SAndroid Build Coastguard Worker     return e->address().ipaddr() == ipaddr;
1198*d9f75844SAndroid Build Coastguard Worker   });
1199*d9f75844SAndroid Build Coastguard Worker }
1200*d9f75844SAndroid Build Coastguard Worker 
FindEntry(const rtc::SocketAddress & addr) const1201*d9f75844SAndroid Build Coastguard Worker TurnEntry* TurnPort::FindEntry(const rtc::SocketAddress& addr) const {
1202*d9f75844SAndroid Build Coastguard Worker   auto it = absl::c_find_if(
1203*d9f75844SAndroid Build Coastguard Worker       entries_, [&addr](const auto& e) { return e->address() == addr; });
1204*d9f75844SAndroid Build Coastguard Worker   return (it != entries_.end()) ? it->get() : nullptr;
1205*d9f75844SAndroid Build Coastguard Worker }
1206*d9f75844SAndroid Build Coastguard Worker 
FindEntry(int channel_id) const1207*d9f75844SAndroid Build Coastguard Worker TurnEntry* TurnPort::FindEntry(int channel_id) const {
1208*d9f75844SAndroid Build Coastguard Worker   auto it = absl::c_find_if(entries_, [&channel_id](const auto& e) {
1209*d9f75844SAndroid Build Coastguard Worker     return e->channel_id() == channel_id;
1210*d9f75844SAndroid Build Coastguard Worker   });
1211*d9f75844SAndroid Build Coastguard Worker   return (it != entries_.end()) ? it->get() : nullptr;
1212*d9f75844SAndroid Build Coastguard Worker }
1213*d9f75844SAndroid Build Coastguard Worker 
CreateOrRefreshEntry(Connection * conn,int channel_number)1214*d9f75844SAndroid Build Coastguard Worker bool TurnPort::CreateOrRefreshEntry(Connection* conn, int channel_number) {
1215*d9f75844SAndroid Build Coastguard Worker   const Candidate& remote_candidate = conn->remote_candidate();
1216*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry = FindEntry(remote_candidate.address());
1217*d9f75844SAndroid Build Coastguard Worker   if (entry == nullptr) {
1218*d9f75844SAndroid Build Coastguard Worker     entries_.push_back(std::make_unique<TurnEntry>(this, conn, channel_number));
1219*d9f75844SAndroid Build Coastguard Worker     return true;
1220*d9f75844SAndroid Build Coastguard Worker   }
1221*d9f75844SAndroid Build Coastguard Worker 
1222*d9f75844SAndroid Build Coastguard Worker   // Associate this connection object with an existing entry. If the entry
1223*d9f75844SAndroid Build Coastguard Worker   // has been scheduled for deletion, this will cancel that task.
1224*d9f75844SAndroid Build Coastguard Worker   entry->TrackConnection(conn);
1225*d9f75844SAndroid Build Coastguard Worker 
1226*d9f75844SAndroid Build Coastguard Worker   return false;
1227*d9f75844SAndroid Build Coastguard Worker }
1228*d9f75844SAndroid Build Coastguard Worker 
HandleConnectionDestroyed(Connection * conn)1229*d9f75844SAndroid Build Coastguard Worker void TurnPort::HandleConnectionDestroyed(Connection* conn) {
1230*d9f75844SAndroid Build Coastguard Worker   // Schedule an event to destroy TurnEntry for the connection, which is
1231*d9f75844SAndroid Build Coastguard Worker   // being destroyed.
1232*d9f75844SAndroid Build Coastguard Worker   const rtc::SocketAddress& remote_address = conn->remote_candidate().address();
1233*d9f75844SAndroid Build Coastguard Worker   // We should always have an entry for this connection.
1234*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry = FindEntry(remote_address);
1235*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<webrtc::PendingTaskSafetyFlag> flag =
1236*d9f75844SAndroid Build Coastguard Worker       entry->UntrackConnection(conn);
1237*d9f75844SAndroid Build Coastguard Worker   if (flag) {
1238*d9f75844SAndroid Build Coastguard Worker     // An assumption here is that the lifetime flag for the entry, is within
1239*d9f75844SAndroid Build Coastguard Worker     // the lifetime scope of `task_safety_` and therefore use of `this` is safe.
1240*d9f75844SAndroid Build Coastguard Worker     // If an entry gets reused (associated with a new connection) while this
1241*d9f75844SAndroid Build Coastguard Worker     // task is pending, the entry will reset the safety flag, thus cancel this
1242*d9f75844SAndroid Build Coastguard Worker     // task.
1243*d9f75844SAndroid Build Coastguard Worker     thread()->PostDelayedTask(SafeTask(flag,
1244*d9f75844SAndroid Build Coastguard Worker                                        [this, entry] {
1245*d9f75844SAndroid Build Coastguard Worker                                          entries_.erase(absl::c_find_if(
1246*d9f75844SAndroid Build Coastguard Worker                                              entries_, [entry](const auto& e) {
1247*d9f75844SAndroid Build Coastguard Worker                                                return e.get() == entry;
1248*d9f75844SAndroid Build Coastguard Worker                                              }));
1249*d9f75844SAndroid Build Coastguard Worker                                        }),
1250*d9f75844SAndroid Build Coastguard Worker                               kTurnPermissionTimeout);
1251*d9f75844SAndroid Build Coastguard Worker   }
1252*d9f75844SAndroid Build Coastguard Worker }
1253*d9f75844SAndroid Build Coastguard Worker 
SetCallbacksForTest(CallbacksForTest * callbacks)1254*d9f75844SAndroid Build Coastguard Worker void TurnPort::SetCallbacksForTest(CallbacksForTest* callbacks) {
1255*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!callbacks_for_test_);
1256*d9f75844SAndroid Build Coastguard Worker   callbacks_for_test_ = callbacks;
1257*d9f75844SAndroid Build Coastguard Worker }
1258*d9f75844SAndroid Build Coastguard Worker 
SetEntryChannelId(const rtc::SocketAddress & address,int channel_id)1259*d9f75844SAndroid Build Coastguard Worker bool TurnPort::SetEntryChannelId(const rtc::SocketAddress& address,
1260*d9f75844SAndroid Build Coastguard Worker                                  int channel_id) {
1261*d9f75844SAndroid Build Coastguard Worker   TurnEntry* entry = FindEntry(address);
1262*d9f75844SAndroid Build Coastguard Worker   if (!entry) {
1263*d9f75844SAndroid Build Coastguard Worker     return false;
1264*d9f75844SAndroid Build Coastguard Worker   }
1265*d9f75844SAndroid Build Coastguard Worker   entry->set_channel_id(channel_id);
1266*d9f75844SAndroid Build Coastguard Worker   return true;
1267*d9f75844SAndroid Build Coastguard Worker }
1268*d9f75844SAndroid Build Coastguard Worker 
ReconstructedServerUrl()1269*d9f75844SAndroid Build Coastguard Worker std::string TurnPort::ReconstructedServerUrl() {
1270*d9f75844SAndroid Build Coastguard Worker   // draft-petithuguenin-behave-turn-uris-01
1271*d9f75844SAndroid Build Coastguard Worker   // turnURI       = scheme ":" turn-host [ ":" turn-port ]
1272*d9f75844SAndroid Build Coastguard Worker   //                 [ "?transport=" transport ]
1273*d9f75844SAndroid Build Coastguard Worker   // scheme        = "turn" / "turns"
1274*d9f75844SAndroid Build Coastguard Worker   // transport     = "udp" / "tcp" / transport-ext
1275*d9f75844SAndroid Build Coastguard Worker   // transport-ext = 1*unreserved
1276*d9f75844SAndroid Build Coastguard Worker   // turn-host     = IP-literal / IPv4address / reg-name
1277*d9f75844SAndroid Build Coastguard Worker   // turn-port     = *DIGIT
1278*d9f75844SAndroid Build Coastguard Worker   std::string scheme = "turn";
1279*d9f75844SAndroid Build Coastguard Worker   std::string transport = "tcp";
1280*d9f75844SAndroid Build Coastguard Worker   switch (server_address_.proto) {
1281*d9f75844SAndroid Build Coastguard Worker     case PROTO_SSLTCP:
1282*d9f75844SAndroid Build Coastguard Worker     case PROTO_TLS:
1283*d9f75844SAndroid Build Coastguard Worker       scheme = "turns";
1284*d9f75844SAndroid Build Coastguard Worker       break;
1285*d9f75844SAndroid Build Coastguard Worker     case PROTO_UDP:
1286*d9f75844SAndroid Build Coastguard Worker       transport = "udp";
1287*d9f75844SAndroid Build Coastguard Worker       break;
1288*d9f75844SAndroid Build Coastguard Worker     case PROTO_TCP:
1289*d9f75844SAndroid Build Coastguard Worker       break;
1290*d9f75844SAndroid Build Coastguard Worker   }
1291*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder url;
1292*d9f75844SAndroid Build Coastguard Worker   url << scheme << ":" << server_address_.address.hostname() << ":"
1293*d9f75844SAndroid Build Coastguard Worker       << server_address_.address.port() << "?transport=" << transport;
1294*d9f75844SAndroid Build Coastguard Worker   return url.Release();
1295*d9f75844SAndroid Build Coastguard Worker }
1296*d9f75844SAndroid Build Coastguard Worker 
TurnCustomizerMaybeModifyOutgoingStunMessage(StunMessage * message)1297*d9f75844SAndroid Build Coastguard Worker void TurnPort::TurnCustomizerMaybeModifyOutgoingStunMessage(
1298*d9f75844SAndroid Build Coastguard Worker     StunMessage* message) {
1299*d9f75844SAndroid Build Coastguard Worker   if (turn_customizer_ == nullptr) {
1300*d9f75844SAndroid Build Coastguard Worker     return;
1301*d9f75844SAndroid Build Coastguard Worker   }
1302*d9f75844SAndroid Build Coastguard Worker 
1303*d9f75844SAndroid Build Coastguard Worker   turn_customizer_->MaybeModifyOutgoingStunMessage(this, message);
1304*d9f75844SAndroid Build Coastguard Worker }
1305*d9f75844SAndroid Build Coastguard Worker 
TurnCustomizerAllowChannelData(const void * data,size_t size,bool payload)1306*d9f75844SAndroid Build Coastguard Worker bool TurnPort::TurnCustomizerAllowChannelData(const void* data,
1307*d9f75844SAndroid Build Coastguard Worker                                               size_t size,
1308*d9f75844SAndroid Build Coastguard Worker                                               bool payload) {
1309*d9f75844SAndroid Build Coastguard Worker   if (turn_customizer_ == nullptr) {
1310*d9f75844SAndroid Build Coastguard Worker     return true;
1311*d9f75844SAndroid Build Coastguard Worker   }
1312*d9f75844SAndroid Build Coastguard Worker 
1313*d9f75844SAndroid Build Coastguard Worker   return turn_customizer_->AllowChannelData(this, data, size, payload);
1314*d9f75844SAndroid Build Coastguard Worker }
1315*d9f75844SAndroid Build Coastguard Worker 
MaybeAddTurnLoggingId(StunMessage * msg)1316*d9f75844SAndroid Build Coastguard Worker void TurnPort::MaybeAddTurnLoggingId(StunMessage* msg) {
1317*d9f75844SAndroid Build Coastguard Worker   if (!turn_logging_id_.empty()) {
1318*d9f75844SAndroid Build Coastguard Worker     msg->AddAttribute(std::make_unique<StunByteStringAttribute>(
1319*d9f75844SAndroid Build Coastguard Worker         STUN_ATTR_TURN_LOGGING_ID, turn_logging_id_));
1320*d9f75844SAndroid Build Coastguard Worker   }
1321*d9f75844SAndroid Build Coastguard Worker }
1322*d9f75844SAndroid Build Coastguard Worker 
TurnAllocateRequest(TurnPort * port)1323*d9f75844SAndroid Build Coastguard Worker TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
1324*d9f75844SAndroid Build Coastguard Worker     : StunRequest(port->request_manager(),
1325*d9f75844SAndroid Build Coastguard Worker                   std::make_unique<TurnMessage>(TURN_ALLOCATE_REQUEST)),
1326*d9f75844SAndroid Build Coastguard Worker       port_(port) {
1327*d9f75844SAndroid Build Coastguard Worker   StunMessage* message = mutable_msg();
1328*d9f75844SAndroid Build Coastguard Worker   // Create the request as indicated in RFC 5766, Section 6.1.
1329*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(message->type(), TURN_ALLOCATE_REQUEST);
1330*d9f75844SAndroid Build Coastguard Worker   auto transport_attr =
1331*d9f75844SAndroid Build Coastguard Worker       StunAttribute::CreateUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
1332*d9f75844SAndroid Build Coastguard Worker   transport_attr->SetValue(IPPROTO_UDP << 24);
1333*d9f75844SAndroid Build Coastguard Worker   message->AddAttribute(std::move(transport_attr));
1334*d9f75844SAndroid Build Coastguard Worker   if (!port_->hash().empty()) {
1335*d9f75844SAndroid Build Coastguard Worker     port_->AddRequestAuthInfo(message);
1336*d9f75844SAndroid Build Coastguard Worker   }
1337*d9f75844SAndroid Build Coastguard Worker   port_->MaybeAddTurnLoggingId(message);
1338*d9f75844SAndroid Build Coastguard Worker   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(message);
1339*d9f75844SAndroid Build Coastguard Worker }
1340*d9f75844SAndroid Build Coastguard Worker 
OnSent()1341*d9f75844SAndroid Build Coastguard Worker void TurnAllocateRequest::OnSent() {
1342*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString() << ": TURN allocate request sent, id="
1343*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id());
1344*d9f75844SAndroid Build Coastguard Worker   StunRequest::OnSent();
1345*d9f75844SAndroid Build Coastguard Worker }
1346*d9f75844SAndroid Build Coastguard Worker 
OnResponse(StunMessage * response)1347*d9f75844SAndroid Build Coastguard Worker void TurnAllocateRequest::OnResponse(StunMessage* response) {
1348*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1349*d9f75844SAndroid Build Coastguard Worker                    << ": TURN allocate requested successfully, id="
1350*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id())
1351*d9f75844SAndroid Build Coastguard Worker                    << ", code=0"  // Makes logging easier to parse.
1352*d9f75844SAndroid Build Coastguard Worker                       ", rtt="
1353*d9f75844SAndroid Build Coastguard Worker                    << Elapsed();
1354*d9f75844SAndroid Build Coastguard Worker 
1355*d9f75844SAndroid Build Coastguard Worker   // Check mandatory attributes as indicated in RFC5766, Section 6.3.
1356*d9f75844SAndroid Build Coastguard Worker   const StunAddressAttribute* mapped_attr =
1357*d9f75844SAndroid Build Coastguard Worker       response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1358*d9f75844SAndroid Build Coastguard Worker   if (!mapped_attr) {
1359*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1360*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
1361*d9f75844SAndroid Build Coastguard Worker                            "attribute in allocate success response";
1362*d9f75844SAndroid Build Coastguard Worker     return;
1363*d9f75844SAndroid Build Coastguard Worker   }
1364*d9f75844SAndroid Build Coastguard Worker   // Using XOR-Mapped-Address for stun.
1365*d9f75844SAndroid Build Coastguard Worker   port_->OnStunAddress(mapped_attr->GetAddress());
1366*d9f75844SAndroid Build Coastguard Worker 
1367*d9f75844SAndroid Build Coastguard Worker   const StunAddressAttribute* relayed_attr =
1368*d9f75844SAndroid Build Coastguard Worker       response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
1369*d9f75844SAndroid Build Coastguard Worker   if (!relayed_attr) {
1370*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1371*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
1372*d9f75844SAndroid Build Coastguard Worker                            "attribute in allocate success response";
1373*d9f75844SAndroid Build Coastguard Worker     return;
1374*d9f75844SAndroid Build Coastguard Worker   }
1375*d9f75844SAndroid Build Coastguard Worker 
1376*d9f75844SAndroid Build Coastguard Worker   const StunUInt32Attribute* lifetime_attr =
1377*d9f75844SAndroid Build Coastguard Worker       response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
1378*d9f75844SAndroid Build Coastguard Worker   if (!lifetime_attr) {
1379*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1380*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_TURN_LIFETIME attribute in "
1381*d9f75844SAndroid Build Coastguard Worker                            "allocate success response";
1382*d9f75844SAndroid Build Coastguard Worker     return;
1383*d9f75844SAndroid Build Coastguard Worker   }
1384*d9f75844SAndroid Build Coastguard Worker   // Notify the port the allocate succeeded, and schedule a refresh request.
1385*d9f75844SAndroid Build Coastguard Worker   port_->OnAllocateSuccess(relayed_attr->GetAddress(),
1386*d9f75844SAndroid Build Coastguard Worker                            mapped_attr->GetAddress());
1387*d9f75844SAndroid Build Coastguard Worker   port_->ScheduleRefresh(lifetime_attr->value());
1388*d9f75844SAndroid Build Coastguard Worker }
1389*d9f75844SAndroid Build Coastguard Worker 
OnErrorResponse(StunMessage * response)1390*d9f75844SAndroid Build Coastguard Worker void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
1391*d9f75844SAndroid Build Coastguard Worker   // Process error response according to RFC5766, Section 6.4.
1392*d9f75844SAndroid Build Coastguard Worker   int error_code = response->GetErrorCodeValue();
1393*d9f75844SAndroid Build Coastguard Worker 
1394*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1395*d9f75844SAndroid Build Coastguard Worker                    << ": Received TURN allocate error response, id="
1396*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id()) << ", code=" << error_code
1397*d9f75844SAndroid Build Coastguard Worker                    << ", rtt=" << Elapsed();
1398*d9f75844SAndroid Build Coastguard Worker 
1399*d9f75844SAndroid Build Coastguard Worker   switch (error_code) {
1400*d9f75844SAndroid Build Coastguard Worker     case STUN_ERROR_UNAUTHORIZED:  // Unauthrorized.
1401*d9f75844SAndroid Build Coastguard Worker       OnAuthChallenge(response, error_code);
1402*d9f75844SAndroid Build Coastguard Worker       break;
1403*d9f75844SAndroid Build Coastguard Worker     case STUN_ERROR_TRY_ALTERNATE:
1404*d9f75844SAndroid Build Coastguard Worker       OnTryAlternate(response, error_code);
1405*d9f75844SAndroid Build Coastguard Worker       break;
1406*d9f75844SAndroid Build Coastguard Worker     case STUN_ERROR_ALLOCATION_MISMATCH: {
1407*d9f75844SAndroid Build Coastguard Worker       // We must handle this error async because trying to delete the socket in
1408*d9f75844SAndroid Build Coastguard Worker       // OnErrorResponse will cause a deadlock on the socket.
1409*d9f75844SAndroid Build Coastguard Worker       TurnPort* port = port_;
1410*d9f75844SAndroid Build Coastguard Worker       port->thread()->PostTask(SafeTask(
1411*d9f75844SAndroid Build Coastguard Worker           port->task_safety_.flag(), [port] { port->OnAllocateMismatch(); }));
1412*d9f75844SAndroid Build Coastguard Worker     } break;
1413*d9f75844SAndroid Build Coastguard Worker     default:
1414*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << port_->ToString()
1415*d9f75844SAndroid Build Coastguard Worker                           << ": Received TURN allocate error response, id="
1416*d9f75844SAndroid Build Coastguard Worker                           << rtc::hex_encode(id()) << ", code=" << error_code
1417*d9f75844SAndroid Build Coastguard Worker                           << ", rtt=" << Elapsed();
1418*d9f75844SAndroid Build Coastguard Worker       const StunErrorCodeAttribute* attr = response->GetErrorCode();
1419*d9f75844SAndroid Build Coastguard Worker       port_->OnAllocateError(error_code, attr ? attr->reason() : "");
1420*d9f75844SAndroid Build Coastguard Worker   }
1421*d9f75844SAndroid Build Coastguard Worker }
1422*d9f75844SAndroid Build Coastguard Worker 
OnTimeout()1423*d9f75844SAndroid Build Coastguard Worker void TurnAllocateRequest::OnTimeout() {
1424*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << port_->ToString() << ": TURN allocate request "
1425*d9f75844SAndroid Build Coastguard Worker                       << rtc::hex_encode(id()) << " timeout";
1426*d9f75844SAndroid Build Coastguard Worker   port_->OnAllocateRequestTimeout();
1427*d9f75844SAndroid Build Coastguard Worker }
1428*d9f75844SAndroid Build Coastguard Worker 
OnAuthChallenge(StunMessage * response,int code)1429*d9f75844SAndroid Build Coastguard Worker void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
1430*d9f75844SAndroid Build Coastguard Worker   // If we failed to authenticate even after we sent our credentials, fail hard.
1431*d9f75844SAndroid Build Coastguard Worker   if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
1432*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1433*d9f75844SAndroid Build Coastguard Worker                         << ": Failed to authenticate with the server "
1434*d9f75844SAndroid Build Coastguard Worker                            "after challenge.";
1435*d9f75844SAndroid Build Coastguard Worker     const StunErrorCodeAttribute* attr = response->GetErrorCode();
1436*d9f75844SAndroid Build Coastguard Worker     port_->OnAllocateError(STUN_ERROR_UNAUTHORIZED, attr ? attr->reason() : "");
1437*d9f75844SAndroid Build Coastguard Worker     return;
1438*d9f75844SAndroid Build Coastguard Worker   }
1439*d9f75844SAndroid Build Coastguard Worker 
1440*d9f75844SAndroid Build Coastguard Worker   // Check the mandatory attributes.
1441*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* realm_attr =
1442*d9f75844SAndroid Build Coastguard Worker       response->GetByteString(STUN_ATTR_REALM);
1443*d9f75844SAndroid Build Coastguard Worker   if (!realm_attr) {
1444*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1445*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_REALM attribute in "
1446*d9f75844SAndroid Build Coastguard Worker                            "allocate unauthorized response.";
1447*d9f75844SAndroid Build Coastguard Worker     return;
1448*d9f75844SAndroid Build Coastguard Worker   }
1449*d9f75844SAndroid Build Coastguard Worker   port_->set_realm(realm_attr->string_view());
1450*d9f75844SAndroid Build Coastguard Worker 
1451*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* nonce_attr =
1452*d9f75844SAndroid Build Coastguard Worker       response->GetByteString(STUN_ATTR_NONCE);
1453*d9f75844SAndroid Build Coastguard Worker   if (!nonce_attr) {
1454*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1455*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_NONCE attribute in "
1456*d9f75844SAndroid Build Coastguard Worker                            "allocate unauthorized response.";
1457*d9f75844SAndroid Build Coastguard Worker     return;
1458*d9f75844SAndroid Build Coastguard Worker   }
1459*d9f75844SAndroid Build Coastguard Worker   port_->set_nonce(nonce_attr->string_view());
1460*d9f75844SAndroid Build Coastguard Worker 
1461*d9f75844SAndroid Build Coastguard Worker   // Send another allocate request, with the received realm and nonce values.
1462*d9f75844SAndroid Build Coastguard Worker   port_->SendRequest(new TurnAllocateRequest(port_), 0);
1463*d9f75844SAndroid Build Coastguard Worker }
1464*d9f75844SAndroid Build Coastguard Worker 
OnTryAlternate(StunMessage * response,int code)1465*d9f75844SAndroid Build Coastguard Worker void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
1466*d9f75844SAndroid Build Coastguard Worker   // According to RFC 5389 section 11, there are use cases where
1467*d9f75844SAndroid Build Coastguard Worker   // authentication of response is not possible, we're not validating
1468*d9f75844SAndroid Build Coastguard Worker   // message integrity.
1469*d9f75844SAndroid Build Coastguard Worker   const StunErrorCodeAttribute* error_code_attr = response->GetErrorCode();
1470*d9f75844SAndroid Build Coastguard Worker   // Get the alternate server address attribute value.
1471*d9f75844SAndroid Build Coastguard Worker   const StunAddressAttribute* alternate_server_attr =
1472*d9f75844SAndroid Build Coastguard Worker       response->GetAddress(STUN_ATTR_ALTERNATE_SERVER);
1473*d9f75844SAndroid Build Coastguard Worker   if (!alternate_server_attr) {
1474*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1475*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_ALTERNATE_SERVER "
1476*d9f75844SAndroid Build Coastguard Worker                            "attribute in try alternate error response";
1477*d9f75844SAndroid Build Coastguard Worker     port_->OnAllocateError(STUN_ERROR_TRY_ALTERNATE,
1478*d9f75844SAndroid Build Coastguard Worker                            error_code_attr ? error_code_attr->reason() : "");
1479*d9f75844SAndroid Build Coastguard Worker     return;
1480*d9f75844SAndroid Build Coastguard Worker   }
1481*d9f75844SAndroid Build Coastguard Worker   if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) {
1482*d9f75844SAndroid Build Coastguard Worker     port_->OnAllocateError(STUN_ERROR_TRY_ALTERNATE,
1483*d9f75844SAndroid Build Coastguard Worker                            error_code_attr ? error_code_attr->reason() : "");
1484*d9f75844SAndroid Build Coastguard Worker     return;
1485*d9f75844SAndroid Build Coastguard Worker   }
1486*d9f75844SAndroid Build Coastguard Worker 
1487*d9f75844SAndroid Build Coastguard Worker   // Check the attributes.
1488*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* realm_attr =
1489*d9f75844SAndroid Build Coastguard Worker       response->GetByteString(STUN_ATTR_REALM);
1490*d9f75844SAndroid Build Coastguard Worker   if (realm_attr) {
1491*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << port_->ToString()
1492*d9f75844SAndroid Build Coastguard Worker                      << ": Applying STUN_ATTR_REALM attribute in "
1493*d9f75844SAndroid Build Coastguard Worker                         "try alternate error response.";
1494*d9f75844SAndroid Build Coastguard Worker     port_->set_realm(realm_attr->string_view());
1495*d9f75844SAndroid Build Coastguard Worker   }
1496*d9f75844SAndroid Build Coastguard Worker 
1497*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* nonce_attr =
1498*d9f75844SAndroid Build Coastguard Worker       response->GetByteString(STUN_ATTR_NONCE);
1499*d9f75844SAndroid Build Coastguard Worker   if (nonce_attr) {
1500*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << port_->ToString()
1501*d9f75844SAndroid Build Coastguard Worker                      << ": Applying STUN_ATTR_NONCE attribute in "
1502*d9f75844SAndroid Build Coastguard Worker                         "try alternate error response.";
1503*d9f75844SAndroid Build Coastguard Worker     port_->set_nonce(nonce_attr->string_view());
1504*d9f75844SAndroid Build Coastguard Worker   }
1505*d9f75844SAndroid Build Coastguard Worker 
1506*d9f75844SAndroid Build Coastguard Worker   // For TCP, we can't close the original Tcp socket during handling a 300 as
1507*d9f75844SAndroid Build Coastguard Worker   // we're still inside that socket's event handler. Doing so will cause
1508*d9f75844SAndroid Build Coastguard Worker   // deadlock.
1509*d9f75844SAndroid Build Coastguard Worker   TurnPort* port = port_;
1510*d9f75844SAndroid Build Coastguard Worker   port->thread()->PostTask(SafeTask(port->task_safety_.flag(),
1511*d9f75844SAndroid Build Coastguard Worker                                     [port] { port->TryAlternateServer(); }));
1512*d9f75844SAndroid Build Coastguard Worker }
1513*d9f75844SAndroid Build Coastguard Worker 
TurnRefreshRequest(TurnPort * port,int lifetime)1514*d9f75844SAndroid Build Coastguard Worker TurnRefreshRequest::TurnRefreshRequest(TurnPort* port, int lifetime /*= -1*/)
1515*d9f75844SAndroid Build Coastguard Worker     : StunRequest(port->request_manager(),
1516*d9f75844SAndroid Build Coastguard Worker                   std::make_unique<TurnMessage>(TURN_REFRESH_REQUEST)),
1517*d9f75844SAndroid Build Coastguard Worker       port_(port) {
1518*d9f75844SAndroid Build Coastguard Worker   StunMessage* message = mutable_msg();
1519*d9f75844SAndroid Build Coastguard Worker   // Create the request as indicated in RFC 5766, Section 7.1.
1520*d9f75844SAndroid Build Coastguard Worker   // No attributes need to be included.
1521*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(message->type(), TURN_REFRESH_REQUEST);
1522*d9f75844SAndroid Build Coastguard Worker   if (lifetime > -1) {
1523*d9f75844SAndroid Build Coastguard Worker     message->AddAttribute(
1524*d9f75844SAndroid Build Coastguard Worker         std::make_unique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime));
1525*d9f75844SAndroid Build Coastguard Worker   }
1526*d9f75844SAndroid Build Coastguard Worker 
1527*d9f75844SAndroid Build Coastguard Worker   port_->AddRequestAuthInfo(message);
1528*d9f75844SAndroid Build Coastguard Worker   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(message);
1529*d9f75844SAndroid Build Coastguard Worker }
1530*d9f75844SAndroid Build Coastguard Worker 
OnSent()1531*d9f75844SAndroid Build Coastguard Worker void TurnRefreshRequest::OnSent() {
1532*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString() << ": TURN refresh request sent, id="
1533*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id());
1534*d9f75844SAndroid Build Coastguard Worker   StunRequest::OnSent();
1535*d9f75844SAndroid Build Coastguard Worker }
1536*d9f75844SAndroid Build Coastguard Worker 
OnResponse(StunMessage * response)1537*d9f75844SAndroid Build Coastguard Worker void TurnRefreshRequest::OnResponse(StunMessage* response) {
1538*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1539*d9f75844SAndroid Build Coastguard Worker                    << ": TURN refresh requested successfully, id="
1540*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id())
1541*d9f75844SAndroid Build Coastguard Worker                    << ", code=0"  // Makes logging easier to parse.
1542*d9f75844SAndroid Build Coastguard Worker                       ", rtt="
1543*d9f75844SAndroid Build Coastguard Worker                    << Elapsed();
1544*d9f75844SAndroid Build Coastguard Worker 
1545*d9f75844SAndroid Build Coastguard Worker   // Check mandatory attributes as indicated in RFC5766, Section 7.3.
1546*d9f75844SAndroid Build Coastguard Worker   const StunUInt32Attribute* lifetime_attr =
1547*d9f75844SAndroid Build Coastguard Worker       response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
1548*d9f75844SAndroid Build Coastguard Worker   if (!lifetime_attr) {
1549*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1550*d9f75844SAndroid Build Coastguard Worker                         << ": Missing STUN_ATTR_TURN_LIFETIME attribute in "
1551*d9f75844SAndroid Build Coastguard Worker                            "refresh success response.";
1552*d9f75844SAndroid Build Coastguard Worker     return;
1553*d9f75844SAndroid Build Coastguard Worker   }
1554*d9f75844SAndroid Build Coastguard Worker 
1555*d9f75844SAndroid Build Coastguard Worker   if (lifetime_attr->value() > 0) {
1556*d9f75844SAndroid Build Coastguard Worker     // Schedule a refresh based on the returned lifetime value.
1557*d9f75844SAndroid Build Coastguard Worker     port_->ScheduleRefresh(lifetime_attr->value());
1558*d9f75844SAndroid Build Coastguard Worker   } else {
1559*d9f75844SAndroid Build Coastguard Worker     // If we scheduled a refresh with lifetime 0, we're releasing this
1560*d9f75844SAndroid Build Coastguard Worker     // allocation; see TurnPort::Release.
1561*d9f75844SAndroid Build Coastguard Worker     TurnPort* port = port_;
1562*d9f75844SAndroid Build Coastguard Worker     port->thread()->PostTask(
1563*d9f75844SAndroid Build Coastguard Worker         SafeTask(port->task_safety_.flag(), [port] { port->Close(); }));
1564*d9f75844SAndroid Build Coastguard Worker   }
1565*d9f75844SAndroid Build Coastguard Worker 
1566*d9f75844SAndroid Build Coastguard Worker   if (port_->callbacks_for_test_) {
1567*d9f75844SAndroid Build Coastguard Worker     port_->callbacks_for_test_->OnTurnRefreshResult(TURN_SUCCESS_RESULT_CODE);
1568*d9f75844SAndroid Build Coastguard Worker   }
1569*d9f75844SAndroid Build Coastguard Worker }
1570*d9f75844SAndroid Build Coastguard Worker 
OnErrorResponse(StunMessage * response)1571*d9f75844SAndroid Build Coastguard Worker void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
1572*d9f75844SAndroid Build Coastguard Worker   int error_code = response->GetErrorCodeValue();
1573*d9f75844SAndroid Build Coastguard Worker 
1574*d9f75844SAndroid Build Coastguard Worker   if (error_code == STUN_ERROR_STALE_NONCE) {
1575*d9f75844SAndroid Build Coastguard Worker     if (port_->UpdateNonce(response)) {
1576*d9f75844SAndroid Build Coastguard Worker       // Send RefreshRequest immediately.
1577*d9f75844SAndroid Build Coastguard Worker       port_->SendRequest(new TurnRefreshRequest(port_), 0);
1578*d9f75844SAndroid Build Coastguard Worker     }
1579*d9f75844SAndroid Build Coastguard Worker   } else {
1580*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << port_->ToString()
1581*d9f75844SAndroid Build Coastguard Worker                         << ": Received TURN refresh error response, id="
1582*d9f75844SAndroid Build Coastguard Worker                         << rtc::hex_encode(id()) << ", code=" << error_code
1583*d9f75844SAndroid Build Coastguard Worker                         << ", rtt=" << Elapsed();
1584*d9f75844SAndroid Build Coastguard Worker     port_->OnRefreshError();
1585*d9f75844SAndroid Build Coastguard Worker     if (port_->callbacks_for_test_) {
1586*d9f75844SAndroid Build Coastguard Worker       port_->callbacks_for_test_->OnTurnRefreshResult(error_code);
1587*d9f75844SAndroid Build Coastguard Worker     }
1588*d9f75844SAndroid Build Coastguard Worker   }
1589*d9f75844SAndroid Build Coastguard Worker }
1590*d9f75844SAndroid Build Coastguard Worker 
OnTimeout()1591*d9f75844SAndroid Build Coastguard Worker void TurnRefreshRequest::OnTimeout() {
1592*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << port_->ToString() << ": TURN refresh timeout "
1593*d9f75844SAndroid Build Coastguard Worker                       << rtc::hex_encode(id());
1594*d9f75844SAndroid Build Coastguard Worker   port_->OnRefreshError();
1595*d9f75844SAndroid Build Coastguard Worker }
1596*d9f75844SAndroid Build Coastguard Worker 
TurnCreatePermissionRequest(TurnPort * port,TurnEntry * entry,const rtc::SocketAddress & ext_addr)1597*d9f75844SAndroid Build Coastguard Worker TurnCreatePermissionRequest::TurnCreatePermissionRequest(
1598*d9f75844SAndroid Build Coastguard Worker     TurnPort* port,
1599*d9f75844SAndroid Build Coastguard Worker     TurnEntry* entry,
1600*d9f75844SAndroid Build Coastguard Worker     const rtc::SocketAddress& ext_addr)
1601*d9f75844SAndroid Build Coastguard Worker     : StunRequest(
1602*d9f75844SAndroid Build Coastguard Worker           port->request_manager(),
1603*d9f75844SAndroid Build Coastguard Worker           std::make_unique<TurnMessage>(TURN_CREATE_PERMISSION_REQUEST)),
1604*d9f75844SAndroid Build Coastguard Worker       port_(port),
1605*d9f75844SAndroid Build Coastguard Worker       entry_(entry),
1606*d9f75844SAndroid Build Coastguard Worker       ext_addr_(ext_addr) {
1607*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(entry_);
1608*d9f75844SAndroid Build Coastguard Worker   entry_->destroyed_callback_list_.AddReceiver(this, [this](TurnEntry* entry) {
1609*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(entry_ == entry);
1610*d9f75844SAndroid Build Coastguard Worker     entry_ = nullptr;
1611*d9f75844SAndroid Build Coastguard Worker   });
1612*d9f75844SAndroid Build Coastguard Worker   StunMessage* message = mutable_msg();
1613*d9f75844SAndroid Build Coastguard Worker   // Create the request as indicated in RFC5766, Section 9.1.
1614*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(message->type(), TURN_CREATE_PERMISSION_REQUEST);
1615*d9f75844SAndroid Build Coastguard Worker   message->AddAttribute(std::make_unique<StunXorAddressAttribute>(
1616*d9f75844SAndroid Build Coastguard Worker       STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
1617*d9f75844SAndroid Build Coastguard Worker   port_->AddRequestAuthInfo(message);
1618*d9f75844SAndroid Build Coastguard Worker   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(message);
1619*d9f75844SAndroid Build Coastguard Worker }
1620*d9f75844SAndroid Build Coastguard Worker 
~TurnCreatePermissionRequest()1621*d9f75844SAndroid Build Coastguard Worker TurnCreatePermissionRequest::~TurnCreatePermissionRequest() {
1622*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1623*d9f75844SAndroid Build Coastguard Worker     entry_->destroyed_callback_list_.RemoveReceivers(this);
1624*d9f75844SAndroid Build Coastguard Worker   }
1625*d9f75844SAndroid Build Coastguard Worker }
1626*d9f75844SAndroid Build Coastguard Worker 
OnSent()1627*d9f75844SAndroid Build Coastguard Worker void TurnCreatePermissionRequest::OnSent() {
1628*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1629*d9f75844SAndroid Build Coastguard Worker                    << ": TURN create permission request sent, id="
1630*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id());
1631*d9f75844SAndroid Build Coastguard Worker   StunRequest::OnSent();
1632*d9f75844SAndroid Build Coastguard Worker }
1633*d9f75844SAndroid Build Coastguard Worker 
OnResponse(StunMessage * response)1634*d9f75844SAndroid Build Coastguard Worker void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
1635*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1636*d9f75844SAndroid Build Coastguard Worker                    << ": TURN permission requested successfully, id="
1637*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id())
1638*d9f75844SAndroid Build Coastguard Worker                    << ", code=0"  // Makes logging easier to parse.
1639*d9f75844SAndroid Build Coastguard Worker                       ", rtt="
1640*d9f75844SAndroid Build Coastguard Worker                    << Elapsed();
1641*d9f75844SAndroid Build Coastguard Worker 
1642*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1643*d9f75844SAndroid Build Coastguard Worker     entry_->OnCreatePermissionSuccess();
1644*d9f75844SAndroid Build Coastguard Worker   }
1645*d9f75844SAndroid Build Coastguard Worker }
1646*d9f75844SAndroid Build Coastguard Worker 
OnErrorResponse(StunMessage * response)1647*d9f75844SAndroid Build Coastguard Worker void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
1648*d9f75844SAndroid Build Coastguard Worker   int error_code = response->GetErrorCodeValue();
1649*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << port_->ToString()
1650*d9f75844SAndroid Build Coastguard Worker                       << ": Received TURN create permission error response, id="
1651*d9f75844SAndroid Build Coastguard Worker                       << rtc::hex_encode(id()) << ", code=" << error_code
1652*d9f75844SAndroid Build Coastguard Worker                       << ", rtt=" << Elapsed();
1653*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1654*d9f75844SAndroid Build Coastguard Worker     entry_->OnCreatePermissionError(response, error_code);
1655*d9f75844SAndroid Build Coastguard Worker   }
1656*d9f75844SAndroid Build Coastguard Worker }
1657*d9f75844SAndroid Build Coastguard Worker 
OnTimeout()1658*d9f75844SAndroid Build Coastguard Worker void TurnCreatePermissionRequest::OnTimeout() {
1659*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << port_->ToString()
1660*d9f75844SAndroid Build Coastguard Worker                       << ": TURN create permission timeout "
1661*d9f75844SAndroid Build Coastguard Worker                       << rtc::hex_encode(id());
1662*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1663*d9f75844SAndroid Build Coastguard Worker     entry_->OnCreatePermissionTimeout();
1664*d9f75844SAndroid Build Coastguard Worker   }
1665*d9f75844SAndroid Build Coastguard Worker }
1666*d9f75844SAndroid Build Coastguard Worker 
TurnChannelBindRequest(TurnPort * port,TurnEntry * entry,int channel_id,const rtc::SocketAddress & ext_addr)1667*d9f75844SAndroid Build Coastguard Worker TurnChannelBindRequest::TurnChannelBindRequest(
1668*d9f75844SAndroid Build Coastguard Worker     TurnPort* port,
1669*d9f75844SAndroid Build Coastguard Worker     TurnEntry* entry,
1670*d9f75844SAndroid Build Coastguard Worker     int channel_id,
1671*d9f75844SAndroid Build Coastguard Worker     const rtc::SocketAddress& ext_addr)
1672*d9f75844SAndroid Build Coastguard Worker     : StunRequest(port->request_manager(),
1673*d9f75844SAndroid Build Coastguard Worker                   std::make_unique<TurnMessage>(TURN_CHANNEL_BIND_REQUEST)),
1674*d9f75844SAndroid Build Coastguard Worker       port_(port),
1675*d9f75844SAndroid Build Coastguard Worker       entry_(entry),
1676*d9f75844SAndroid Build Coastguard Worker       channel_id_(channel_id),
1677*d9f75844SAndroid Build Coastguard Worker       ext_addr_(ext_addr) {
1678*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(entry_);
1679*d9f75844SAndroid Build Coastguard Worker   entry_->destroyed_callback_list_.AddReceiver(this, [this](TurnEntry* entry) {
1680*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(entry_ == entry);
1681*d9f75844SAndroid Build Coastguard Worker     entry_ = nullptr;
1682*d9f75844SAndroid Build Coastguard Worker   });
1683*d9f75844SAndroid Build Coastguard Worker   StunMessage* message = mutable_msg();
1684*d9f75844SAndroid Build Coastguard Worker   // Create the request as indicated in RFC5766, Section 11.1.
1685*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_EQ(message->type(), TURN_CHANNEL_BIND_REQUEST);
1686*d9f75844SAndroid Build Coastguard Worker   message->AddAttribute(std::make_unique<StunUInt32Attribute>(
1687*d9f75844SAndroid Build Coastguard Worker       STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16));
1688*d9f75844SAndroid Build Coastguard Worker   message->AddAttribute(std::make_unique<StunXorAddressAttribute>(
1689*d9f75844SAndroid Build Coastguard Worker       STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
1690*d9f75844SAndroid Build Coastguard Worker   port_->AddRequestAuthInfo(message);
1691*d9f75844SAndroid Build Coastguard Worker   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(message);
1692*d9f75844SAndroid Build Coastguard Worker }
1693*d9f75844SAndroid Build Coastguard Worker 
~TurnChannelBindRequest()1694*d9f75844SAndroid Build Coastguard Worker TurnChannelBindRequest::~TurnChannelBindRequest() {
1695*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1696*d9f75844SAndroid Build Coastguard Worker     entry_->destroyed_callback_list_.RemoveReceivers(this);
1697*d9f75844SAndroid Build Coastguard Worker   }
1698*d9f75844SAndroid Build Coastguard Worker }
1699*d9f75844SAndroid Build Coastguard Worker 
OnSent()1700*d9f75844SAndroid Build Coastguard Worker void TurnChannelBindRequest::OnSent() {
1701*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1702*d9f75844SAndroid Build Coastguard Worker                    << ": TURN channel bind request sent, id="
1703*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id());
1704*d9f75844SAndroid Build Coastguard Worker   StunRequest::OnSent();
1705*d9f75844SAndroid Build Coastguard Worker }
1706*d9f75844SAndroid Build Coastguard Worker 
OnResponse(StunMessage * response)1707*d9f75844SAndroid Build Coastguard Worker void TurnChannelBindRequest::OnResponse(StunMessage* response) {
1708*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString()
1709*d9f75844SAndroid Build Coastguard Worker                    << ": TURN channel bind requested successfully, id="
1710*d9f75844SAndroid Build Coastguard Worker                    << rtc::hex_encode(id())
1711*d9f75844SAndroid Build Coastguard Worker                    << ", code=0"  // Makes logging easier to parse.
1712*d9f75844SAndroid Build Coastguard Worker                       ", rtt="
1713*d9f75844SAndroid Build Coastguard Worker                    << Elapsed();
1714*d9f75844SAndroid Build Coastguard Worker 
1715*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1716*d9f75844SAndroid Build Coastguard Worker     entry_->OnChannelBindSuccess();
1717*d9f75844SAndroid Build Coastguard Worker     // Refresh the channel binding just under the permission timeout
1718*d9f75844SAndroid Build Coastguard Worker     // threshold. The channel binding has a longer lifetime, but
1719*d9f75844SAndroid Build Coastguard Worker     // this is the easiest way to keep both the channel and the
1720*d9f75844SAndroid Build Coastguard Worker     // permission from expiring.
1721*d9f75844SAndroid Build Coastguard Worker     TimeDelta delay = kTurnPermissionTimeout - TimeDelta::Minutes(1);
1722*d9f75844SAndroid Build Coastguard Worker     entry_->SendChannelBindRequest(delay.ms());
1723*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << port_->ToString() << ": Scheduled channel bind in "
1724*d9f75844SAndroid Build Coastguard Worker                      << delay.ms() << "ms.";
1725*d9f75844SAndroid Build Coastguard Worker   }
1726*d9f75844SAndroid Build Coastguard Worker }
1727*d9f75844SAndroid Build Coastguard Worker 
OnErrorResponse(StunMessage * response)1728*d9f75844SAndroid Build Coastguard Worker void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
1729*d9f75844SAndroid Build Coastguard Worker   int error_code = response->GetErrorCodeValue();
1730*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << port_->ToString()
1731*d9f75844SAndroid Build Coastguard Worker                       << ": Received TURN channel bind error response, id="
1732*d9f75844SAndroid Build Coastguard Worker                       << rtc::hex_encode(id()) << ", code=" << error_code
1733*d9f75844SAndroid Build Coastguard Worker                       << ", rtt=" << Elapsed();
1734*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1735*d9f75844SAndroid Build Coastguard Worker     entry_->OnChannelBindError(response, error_code);
1736*d9f75844SAndroid Build Coastguard Worker   }
1737*d9f75844SAndroid Build Coastguard Worker }
1738*d9f75844SAndroid Build Coastguard Worker 
OnTimeout()1739*d9f75844SAndroid Build Coastguard Worker void TurnChannelBindRequest::OnTimeout() {
1740*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << port_->ToString() << ": TURN channel bind timeout "
1741*d9f75844SAndroid Build Coastguard Worker                       << rtc::hex_encode(id());
1742*d9f75844SAndroid Build Coastguard Worker   if (entry_) {
1743*d9f75844SAndroid Build Coastguard Worker     entry_->OnChannelBindTimeout();
1744*d9f75844SAndroid Build Coastguard Worker   }
1745*d9f75844SAndroid Build Coastguard Worker }
1746*d9f75844SAndroid Build Coastguard Worker 
TurnEntry(TurnPort * port,Connection * conn,int channel_id)1747*d9f75844SAndroid Build Coastguard Worker TurnEntry::TurnEntry(TurnPort* port, Connection* conn, int channel_id)
1748*d9f75844SAndroid Build Coastguard Worker     : port_(port),
1749*d9f75844SAndroid Build Coastguard Worker       channel_id_(channel_id),
1750*d9f75844SAndroid Build Coastguard Worker       ext_addr_(conn->remote_candidate().address()),
1751*d9f75844SAndroid Build Coastguard Worker       state_(STATE_UNBOUND),
1752*d9f75844SAndroid Build Coastguard Worker       connections_({conn}) {
1753*d9f75844SAndroid Build Coastguard Worker   // Creating permission for `ext_addr_`.
1754*d9f75844SAndroid Build Coastguard Worker   SendCreatePermissionRequest(0);
1755*d9f75844SAndroid Build Coastguard Worker }
1756*d9f75844SAndroid Build Coastguard Worker 
~TurnEntry()1757*d9f75844SAndroid Build Coastguard Worker TurnEntry::~TurnEntry() {
1758*d9f75844SAndroid Build Coastguard Worker   destroyed_callback_list_.Send(this);
1759*d9f75844SAndroid Build Coastguard Worker }
1760*d9f75844SAndroid Build Coastguard Worker 
TrackConnection(Connection * conn)1761*d9f75844SAndroid Build Coastguard Worker void TurnEntry::TrackConnection(Connection* conn) {
1762*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(absl::c_find(connections_, conn) == connections_.end());
1763*d9f75844SAndroid Build Coastguard Worker   if (connections_.empty()) {
1764*d9f75844SAndroid Build Coastguard Worker     task_safety_.reset();
1765*d9f75844SAndroid Build Coastguard Worker   }
1766*d9f75844SAndroid Build Coastguard Worker   connections_.push_back(conn);
1767*d9f75844SAndroid Build Coastguard Worker }
1768*d9f75844SAndroid Build Coastguard Worker 
UntrackConnection(Connection * conn)1769*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::PendingTaskSafetyFlag> TurnEntry::UntrackConnection(
1770*d9f75844SAndroid Build Coastguard Worker     Connection* conn) {
1771*d9f75844SAndroid Build Coastguard Worker   connections_.erase(absl::c_find(connections_, conn));
1772*d9f75844SAndroid Build Coastguard Worker   return connections_.empty() ? task_safety_.flag() : nullptr;
1773*d9f75844SAndroid Build Coastguard Worker }
1774*d9f75844SAndroid Build Coastguard Worker 
SendCreatePermissionRequest(int delay)1775*d9f75844SAndroid Build Coastguard Worker void TurnEntry::SendCreatePermissionRequest(int delay) {
1776*d9f75844SAndroid Build Coastguard Worker   port_->SendRequest(new TurnCreatePermissionRequest(port_, this, ext_addr_),
1777*d9f75844SAndroid Build Coastguard Worker                      delay);
1778*d9f75844SAndroid Build Coastguard Worker }
1779*d9f75844SAndroid Build Coastguard Worker 
SendChannelBindRequest(int delay)1780*d9f75844SAndroid Build Coastguard Worker void TurnEntry::SendChannelBindRequest(int delay) {
1781*d9f75844SAndroid Build Coastguard Worker   port_->SendRequest(
1782*d9f75844SAndroid Build Coastguard Worker       new TurnChannelBindRequest(port_, this, channel_id_, ext_addr_), delay);
1783*d9f75844SAndroid Build Coastguard Worker }
1784*d9f75844SAndroid Build Coastguard Worker 
Send(const void * data,size_t size,bool payload,const rtc::PacketOptions & options)1785*d9f75844SAndroid Build Coastguard Worker int TurnEntry::Send(const void* data,
1786*d9f75844SAndroid Build Coastguard Worker                     size_t size,
1787*d9f75844SAndroid Build Coastguard Worker                     bool payload,
1788*d9f75844SAndroid Build Coastguard Worker                     const rtc::PacketOptions& options) {
1789*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferWriter buf;
1790*d9f75844SAndroid Build Coastguard Worker   if (state_ != STATE_BOUND ||
1791*d9f75844SAndroid Build Coastguard Worker       !port_->TurnCustomizerAllowChannelData(data, size, payload)) {
1792*d9f75844SAndroid Build Coastguard Worker     // If we haven't bound the channel yet, we have to use a Send Indication.
1793*d9f75844SAndroid Build Coastguard Worker     // The turn_customizer_ can also make us use Send Indication.
1794*d9f75844SAndroid Build Coastguard Worker     TurnMessage msg(TURN_SEND_INDICATION);
1795*d9f75844SAndroid Build Coastguard Worker     msg.AddAttribute(std::make_unique<StunXorAddressAttribute>(
1796*d9f75844SAndroid Build Coastguard Worker         STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
1797*d9f75844SAndroid Build Coastguard Worker     msg.AddAttribute(
1798*d9f75844SAndroid Build Coastguard Worker         std::make_unique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
1799*d9f75844SAndroid Build Coastguard Worker 
1800*d9f75844SAndroid Build Coastguard Worker     port_->TurnCustomizerMaybeModifyOutgoingStunMessage(&msg);
1801*d9f75844SAndroid Build Coastguard Worker 
1802*d9f75844SAndroid Build Coastguard Worker     const bool success = msg.Write(&buf);
1803*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(success);
1804*d9f75844SAndroid Build Coastguard Worker 
1805*d9f75844SAndroid Build Coastguard Worker     // If we're sending real data, request a channel bind that we can use later.
1806*d9f75844SAndroid Build Coastguard Worker     if (state_ == STATE_UNBOUND && payload) {
1807*d9f75844SAndroid Build Coastguard Worker       SendChannelBindRequest(0);
1808*d9f75844SAndroid Build Coastguard Worker       state_ = STATE_BINDING;
1809*d9f75844SAndroid Build Coastguard Worker     }
1810*d9f75844SAndroid Build Coastguard Worker   } else {
1811*d9f75844SAndroid Build Coastguard Worker     // If the channel is bound, we can send the data as a Channel Message.
1812*d9f75844SAndroid Build Coastguard Worker     buf.WriteUInt16(channel_id_);
1813*d9f75844SAndroid Build Coastguard Worker     buf.WriteUInt16(static_cast<uint16_t>(size));
1814*d9f75844SAndroid Build Coastguard Worker     buf.WriteBytes(reinterpret_cast<const char*>(data), size);
1815*d9f75844SAndroid Build Coastguard Worker   }
1816*d9f75844SAndroid Build Coastguard Worker   rtc::PacketOptions modified_options(options);
1817*d9f75844SAndroid Build Coastguard Worker   modified_options.info_signaled_after_sent.turn_overhead_bytes =
1818*d9f75844SAndroid Build Coastguard Worker       buf.Length() - size;
1819*d9f75844SAndroid Build Coastguard Worker   return port_->Send(buf.Data(), buf.Length(), modified_options);
1820*d9f75844SAndroid Build Coastguard Worker }
1821*d9f75844SAndroid Build Coastguard Worker 
OnCreatePermissionSuccess()1822*d9f75844SAndroid Build Coastguard Worker void TurnEntry::OnCreatePermissionSuccess() {
1823*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString() << ": Create permission for "
1824*d9f75844SAndroid Build Coastguard Worker                    << ext_addr_.ToSensitiveString() << " succeeded";
1825*d9f75844SAndroid Build Coastguard Worker   if (port_->callbacks_for_test_) {
1826*d9f75844SAndroid Build Coastguard Worker     port_->callbacks_for_test_->OnTurnCreatePermissionResult(
1827*d9f75844SAndroid Build Coastguard Worker         TURN_SUCCESS_RESULT_CODE);
1828*d9f75844SAndroid Build Coastguard Worker   }
1829*d9f75844SAndroid Build Coastguard Worker 
1830*d9f75844SAndroid Build Coastguard Worker   // If `state_` is STATE_BOUND, the permission will be refreshed
1831*d9f75844SAndroid Build Coastguard Worker   // by ChannelBindRequest.
1832*d9f75844SAndroid Build Coastguard Worker   if (state_ != STATE_BOUND) {
1833*d9f75844SAndroid Build Coastguard Worker     // Refresh the permission request about 1 minute before the permission
1834*d9f75844SAndroid Build Coastguard Worker     // times out.
1835*d9f75844SAndroid Build Coastguard Worker     TimeDelta delay = kTurnPermissionTimeout - TimeDelta::Minutes(1);
1836*d9f75844SAndroid Build Coastguard Worker     SendCreatePermissionRequest(delay.ms());
1837*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << port_->ToString()
1838*d9f75844SAndroid Build Coastguard Worker                      << ": Scheduled create-permission-request in "
1839*d9f75844SAndroid Build Coastguard Worker                      << delay.ms() << "ms.";
1840*d9f75844SAndroid Build Coastguard Worker   }
1841*d9f75844SAndroid Build Coastguard Worker }
1842*d9f75844SAndroid Build Coastguard Worker 
OnCreatePermissionError(StunMessage * response,int code)1843*d9f75844SAndroid Build Coastguard Worker void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
1844*d9f75844SAndroid Build Coastguard Worker   if (code == STUN_ERROR_STALE_NONCE) {
1845*d9f75844SAndroid Build Coastguard Worker     if (port_->UpdateNonce(response)) {
1846*d9f75844SAndroid Build Coastguard Worker       SendCreatePermissionRequest(0);
1847*d9f75844SAndroid Build Coastguard Worker     }
1848*d9f75844SAndroid Build Coastguard Worker   } else {
1849*d9f75844SAndroid Build Coastguard Worker     bool found = port_->FailAndPruneConnection(ext_addr_);
1850*d9f75844SAndroid Build Coastguard Worker     if (found) {
1851*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Received TURN CreatePermission error response, "
1852*d9f75844SAndroid Build Coastguard Worker                            "code="
1853*d9f75844SAndroid Build Coastguard Worker                         << code << "; pruned connection.";
1854*d9f75844SAndroid Build Coastguard Worker     }
1855*d9f75844SAndroid Build Coastguard Worker   }
1856*d9f75844SAndroid Build Coastguard Worker   if (port_->callbacks_for_test_) {
1857*d9f75844SAndroid Build Coastguard Worker     port_->callbacks_for_test_->OnTurnCreatePermissionResult(code);
1858*d9f75844SAndroid Build Coastguard Worker   }
1859*d9f75844SAndroid Build Coastguard Worker }
1860*d9f75844SAndroid Build Coastguard Worker 
OnCreatePermissionTimeout()1861*d9f75844SAndroid Build Coastguard Worker void TurnEntry::OnCreatePermissionTimeout() {
1862*d9f75844SAndroid Build Coastguard Worker   port_->FailAndPruneConnection(ext_addr_);
1863*d9f75844SAndroid Build Coastguard Worker }
1864*d9f75844SAndroid Build Coastguard Worker 
OnChannelBindSuccess()1865*d9f75844SAndroid Build Coastguard Worker void TurnEntry::OnChannelBindSuccess() {
1866*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << port_->ToString() << ": Successful channel bind for "
1867*d9f75844SAndroid Build Coastguard Worker                    << ext_addr_.ToSensitiveString();
1868*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(state_ == STATE_BINDING || state_ == STATE_BOUND);
1869*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_BOUND;
1870*d9f75844SAndroid Build Coastguard Worker }
1871*d9f75844SAndroid Build Coastguard Worker 
OnChannelBindError(StunMessage * response,int code)1872*d9f75844SAndroid Build Coastguard Worker void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1873*d9f75844SAndroid Build Coastguard Worker   // If the channel bind fails due to errors other than STATE_NONCE,
1874*d9f75844SAndroid Build Coastguard Worker   // we will fail and prune the connection and rely on ICE restart to
1875*d9f75844SAndroid Build Coastguard Worker   // re-establish a new connection if needed.
1876*d9f75844SAndroid Build Coastguard Worker   if (code == STUN_ERROR_STALE_NONCE) {
1877*d9f75844SAndroid Build Coastguard Worker     if (port_->UpdateNonce(response)) {
1878*d9f75844SAndroid Build Coastguard Worker       // Send channel bind request with fresh nonce.
1879*d9f75844SAndroid Build Coastguard Worker       SendChannelBindRequest(0);
1880*d9f75844SAndroid Build Coastguard Worker     }
1881*d9f75844SAndroid Build Coastguard Worker   } else {
1882*d9f75844SAndroid Build Coastguard Worker     state_ = STATE_UNBOUND;
1883*d9f75844SAndroid Build Coastguard Worker     port_->FailAndPruneConnection(ext_addr_);
1884*d9f75844SAndroid Build Coastguard Worker   }
1885*d9f75844SAndroid Build Coastguard Worker }
OnChannelBindTimeout()1886*d9f75844SAndroid Build Coastguard Worker void TurnEntry::OnChannelBindTimeout() {
1887*d9f75844SAndroid Build Coastguard Worker   state_ = STATE_UNBOUND;
1888*d9f75844SAndroid Build Coastguard Worker   port_->FailAndPruneConnection(ext_addr_);
1889*d9f75844SAndroid Build Coastguard Worker }
1890*d9f75844SAndroid Build Coastguard Worker }  // namespace cricket
1891