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_server.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <tuple> // for std::tie
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
19*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/packet_socket_factory.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/transport/stun.h"
25*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/async_stun_tcp_socket.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_buffer.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
30*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/message_digest.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_adapters.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker namespace cricket {
35*d9f75844SAndroid Build Coastguard Worker namespace {
36*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TimeDelta;
37*d9f75844SAndroid Build Coastguard Worker
38*d9f75844SAndroid Build Coastguard Worker // TODO(juberti): Move this all to a future turnmessage.h
39*d9f75844SAndroid Build Coastguard Worker // static const int IPPROTO_UDP = 17;
40*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kNonceTimeout = TimeDelta::Minutes(60);
41*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kDefaultAllocationTimeout = TimeDelta::Minutes(10);
42*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kPermissionTimeout = TimeDelta::Minutes(5);
43*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kChannelTimeout = TimeDelta::Minutes(10);
44*d9f75844SAndroid Build Coastguard Worker
45*d9f75844SAndroid Build Coastguard Worker constexpr int kMinChannelNumber = 0x4000;
46*d9f75844SAndroid Build Coastguard Worker constexpr int kMaxChannelNumber = 0x7FFF;
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker constexpr size_t kNonceKeySize = 16;
49*d9f75844SAndroid Build Coastguard Worker constexpr size_t kNonceSize = 48;
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker constexpr size_t TURN_CHANNEL_HEADER_SIZE = 4U;
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker // TODO(mallinath) - Move these to a common place.
IsTurnChannelData(uint16_t msg_type)54*d9f75844SAndroid Build Coastguard Worker bool IsTurnChannelData(uint16_t msg_type) {
55*d9f75844SAndroid Build Coastguard Worker // The first two bits of a channel data message are 0b01.
56*d9f75844SAndroid Build Coastguard Worker return ((msg_type & 0xC000) == 0x4000);
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker
59*d9f75844SAndroid Build Coastguard Worker } // namespace
60*d9f75844SAndroid Build Coastguard Worker
GetStunSuccessResponseTypeOrZero(const StunMessage & req)61*d9f75844SAndroid Build Coastguard Worker int GetStunSuccessResponseTypeOrZero(const StunMessage& req) {
62*d9f75844SAndroid Build Coastguard Worker const int resp_type = GetStunSuccessResponseType(req.type());
63*d9f75844SAndroid Build Coastguard Worker return resp_type == -1 ? 0 : resp_type;
64*d9f75844SAndroid Build Coastguard Worker }
65*d9f75844SAndroid Build Coastguard Worker
GetStunErrorResponseTypeOrZero(const StunMessage & req)66*d9f75844SAndroid Build Coastguard Worker int GetStunErrorResponseTypeOrZero(const StunMessage& req) {
67*d9f75844SAndroid Build Coastguard Worker const int resp_type = GetStunErrorResponseType(req.type());
68*d9f75844SAndroid Build Coastguard Worker return resp_type == -1 ? 0 : resp_type;
69*d9f75844SAndroid Build Coastguard Worker }
70*d9f75844SAndroid Build Coastguard Worker
InitErrorResponse(int code,absl::string_view reason,StunMessage * resp)71*d9f75844SAndroid Build Coastguard Worker static void InitErrorResponse(int code,
72*d9f75844SAndroid Build Coastguard Worker absl::string_view reason,
73*d9f75844SAndroid Build Coastguard Worker StunMessage* resp) {
74*d9f75844SAndroid Build Coastguard Worker resp->AddAttribute(std::make_unique<cricket::StunErrorCodeAttribute>(
75*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_ERROR_CODE, code, std::string(reason)));
76*d9f75844SAndroid Build Coastguard Worker }
77*d9f75844SAndroid Build Coastguard Worker
TurnServer(webrtc::TaskQueueBase * thread)78*d9f75844SAndroid Build Coastguard Worker TurnServer::TurnServer(webrtc::TaskQueueBase* thread)
79*d9f75844SAndroid Build Coastguard Worker : thread_(thread),
80*d9f75844SAndroid Build Coastguard Worker nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
81*d9f75844SAndroid Build Coastguard Worker auth_hook_(NULL),
82*d9f75844SAndroid Build Coastguard Worker redirect_hook_(NULL),
83*d9f75844SAndroid Build Coastguard Worker enable_otu_nonce_(false) {}
84*d9f75844SAndroid Build Coastguard Worker
~TurnServer()85*d9f75844SAndroid Build Coastguard Worker TurnServer::~TurnServer() {
86*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
87*d9f75844SAndroid Build Coastguard Worker for (InternalSocketMap::iterator it = server_sockets_.begin();
88*d9f75844SAndroid Build Coastguard Worker it != server_sockets_.end(); ++it) {
89*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* socket = it->first;
90*d9f75844SAndroid Build Coastguard Worker delete socket;
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker
93*d9f75844SAndroid Build Coastguard Worker for (ServerSocketMap::iterator it = server_listen_sockets_.begin();
94*d9f75844SAndroid Build Coastguard Worker it != server_listen_sockets_.end(); ++it) {
95*d9f75844SAndroid Build Coastguard Worker rtc::Socket* socket = it->first;
96*d9f75844SAndroid Build Coastguard Worker delete socket;
97*d9f75844SAndroid Build Coastguard Worker }
98*d9f75844SAndroid Build Coastguard Worker }
99*d9f75844SAndroid Build Coastguard Worker
AddInternalSocket(rtc::AsyncPacketSocket * socket,ProtocolType proto)100*d9f75844SAndroid Build Coastguard Worker void TurnServer::AddInternalSocket(rtc::AsyncPacketSocket* socket,
101*d9f75844SAndroid Build Coastguard Worker ProtocolType proto) {
102*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
103*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
104*d9f75844SAndroid Build Coastguard Worker server_sockets_[socket] = proto;
105*d9f75844SAndroid Build Coastguard Worker socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket);
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker
AddInternalServerSocket(rtc::Socket * socket,ProtocolType proto,std::unique_ptr<rtc::SSLAdapterFactory> ssl_adapter_factory)108*d9f75844SAndroid Build Coastguard Worker void TurnServer::AddInternalServerSocket(
109*d9f75844SAndroid Build Coastguard Worker rtc::Socket* socket,
110*d9f75844SAndroid Build Coastguard Worker ProtocolType proto,
111*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLAdapterFactory> ssl_adapter_factory) {
112*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
113*d9f75844SAndroid Build Coastguard Worker
114*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(server_listen_sockets_.end() ==
115*d9f75844SAndroid Build Coastguard Worker server_listen_sockets_.find(socket));
116*d9f75844SAndroid Build Coastguard Worker server_listen_sockets_[socket] = {proto, std::move(ssl_adapter_factory)};
117*d9f75844SAndroid Build Coastguard Worker socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection);
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker
SetExternalSocketFactory(rtc::PacketSocketFactory * factory,const rtc::SocketAddress & external_addr)120*d9f75844SAndroid Build Coastguard Worker void TurnServer::SetExternalSocketFactory(
121*d9f75844SAndroid Build Coastguard Worker rtc::PacketSocketFactory* factory,
122*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& external_addr) {
123*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
124*d9f75844SAndroid Build Coastguard Worker external_socket_factory_.reset(factory);
125*d9f75844SAndroid Build Coastguard Worker external_addr_ = external_addr;
126*d9f75844SAndroid Build Coastguard Worker }
127*d9f75844SAndroid Build Coastguard Worker
OnNewInternalConnection(rtc::Socket * socket)128*d9f75844SAndroid Build Coastguard Worker void TurnServer::OnNewInternalConnection(rtc::Socket* socket) {
129*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
130*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(server_listen_sockets_.find(socket) !=
131*d9f75844SAndroid Build Coastguard Worker server_listen_sockets_.end());
132*d9f75844SAndroid Build Coastguard Worker AcceptConnection(socket);
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker
AcceptConnection(rtc::Socket * server_socket)135*d9f75844SAndroid Build Coastguard Worker void TurnServer::AcceptConnection(rtc::Socket* server_socket) {
136*d9f75844SAndroid Build Coastguard Worker // Check if someone is trying to connect to us.
137*d9f75844SAndroid Build Coastguard Worker rtc::SocketAddress accept_addr;
138*d9f75844SAndroid Build Coastguard Worker rtc::Socket* accepted_socket = server_socket->Accept(&accept_addr);
139*d9f75844SAndroid Build Coastguard Worker if (accepted_socket != NULL) {
140*d9f75844SAndroid Build Coastguard Worker const ServerSocketInfo& info = server_listen_sockets_[server_socket];
141*d9f75844SAndroid Build Coastguard Worker if (info.ssl_adapter_factory) {
142*d9f75844SAndroid Build Coastguard Worker rtc::SSLAdapter* ssl_adapter =
143*d9f75844SAndroid Build Coastguard Worker info.ssl_adapter_factory->CreateAdapter(accepted_socket);
144*d9f75844SAndroid Build Coastguard Worker ssl_adapter->StartSSL("");
145*d9f75844SAndroid Build Coastguard Worker accepted_socket = ssl_adapter;
146*d9f75844SAndroid Build Coastguard Worker }
147*d9f75844SAndroid Build Coastguard Worker cricket::AsyncStunTCPSocket* tcp_socket =
148*d9f75844SAndroid Build Coastguard Worker new cricket::AsyncStunTCPSocket(accepted_socket);
149*d9f75844SAndroid Build Coastguard Worker
150*d9f75844SAndroid Build Coastguard Worker tcp_socket->SubscribeClose(this,
151*d9f75844SAndroid Build Coastguard Worker [this](rtc::AsyncPacketSocket* s, int err) {
152*d9f75844SAndroid Build Coastguard Worker OnInternalSocketClose(s, err);
153*d9f75844SAndroid Build Coastguard Worker });
154*d9f75844SAndroid Build Coastguard Worker // Finally add the socket so it can start communicating with the client.
155*d9f75844SAndroid Build Coastguard Worker AddInternalSocket(tcp_socket, info.proto);
156*d9f75844SAndroid Build Coastguard Worker }
157*d9f75844SAndroid Build Coastguard Worker }
158*d9f75844SAndroid Build Coastguard Worker
OnInternalSocketClose(rtc::AsyncPacketSocket * socket,int err)159*d9f75844SAndroid Build Coastguard Worker void TurnServer::OnInternalSocketClose(rtc::AsyncPacketSocket* socket,
160*d9f75844SAndroid Build Coastguard Worker int err) {
161*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
162*d9f75844SAndroid Build Coastguard Worker DestroyInternalSocket(socket);
163*d9f75844SAndroid Build Coastguard Worker }
164*d9f75844SAndroid Build Coastguard Worker
OnInternalPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & addr,const int64_t &)165*d9f75844SAndroid Build Coastguard Worker void TurnServer::OnInternalPacket(rtc::AsyncPacketSocket* socket,
166*d9f75844SAndroid Build Coastguard Worker const char* data,
167*d9f75844SAndroid Build Coastguard Worker size_t size,
168*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& addr,
169*d9f75844SAndroid Build Coastguard Worker const int64_t& /* packet_time_us */) {
170*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
171*d9f75844SAndroid Build Coastguard Worker // Fail if the packet is too small to even contain a channel header.
172*d9f75844SAndroid Build Coastguard Worker if (size < TURN_CHANNEL_HEADER_SIZE) {
173*d9f75844SAndroid Build Coastguard Worker return;
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker InternalSocketMap::iterator iter = server_sockets_.find(socket);
176*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(iter != server_sockets_.end());
177*d9f75844SAndroid Build Coastguard Worker TurnServerConnection conn(addr, iter->second, socket);
178*d9f75844SAndroid Build Coastguard Worker uint16_t msg_type = rtc::GetBE16(data);
179*d9f75844SAndroid Build Coastguard Worker if (!IsTurnChannelData(msg_type)) {
180*d9f75844SAndroid Build Coastguard Worker // This is a STUN message.
181*d9f75844SAndroid Build Coastguard Worker HandleStunMessage(&conn, data, size);
182*d9f75844SAndroid Build Coastguard Worker } else {
183*d9f75844SAndroid Build Coastguard Worker // This is a channel message; let the allocation handle it.
184*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* allocation = FindAllocation(&conn);
185*d9f75844SAndroid Build Coastguard Worker if (allocation) {
186*d9f75844SAndroid Build Coastguard Worker allocation->HandleChannelData(data, size);
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker if (stun_message_observer_ != nullptr) {
189*d9f75844SAndroid Build Coastguard Worker stun_message_observer_->ReceivedChannelData(data, size);
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
HandleStunMessage(TurnServerConnection * conn,const char * data,size_t size)194*d9f75844SAndroid Build Coastguard Worker void TurnServer::HandleStunMessage(TurnServerConnection* conn,
195*d9f75844SAndroid Build Coastguard Worker const char* data,
196*d9f75844SAndroid Build Coastguard Worker size_t size) {
197*d9f75844SAndroid Build Coastguard Worker TurnMessage msg;
198*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferReader buf(data, size);
199*d9f75844SAndroid Build Coastguard Worker if (!msg.Read(&buf) || (buf.Length() > 0)) {
200*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Received invalid STUN message";
201*d9f75844SAndroid Build Coastguard Worker return;
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker
204*d9f75844SAndroid Build Coastguard Worker if (stun_message_observer_ != nullptr) {
205*d9f75844SAndroid Build Coastguard Worker stun_message_observer_->ReceivedMessage(&msg);
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker
208*d9f75844SAndroid Build Coastguard Worker // If it's a STUN binding request, handle that specially.
209*d9f75844SAndroid Build Coastguard Worker if (msg.type() == STUN_BINDING_REQUEST) {
210*d9f75844SAndroid Build Coastguard Worker HandleBindingRequest(conn, &msg);
211*d9f75844SAndroid Build Coastguard Worker return;
212*d9f75844SAndroid Build Coastguard Worker }
213*d9f75844SAndroid Build Coastguard Worker
214*d9f75844SAndroid Build Coastguard Worker if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
215*d9f75844SAndroid Build Coastguard Worker rtc::SocketAddress address;
216*d9f75844SAndroid Build Coastguard Worker if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
217*d9f75844SAndroid Build Coastguard Worker SendErrorResponseWithAlternateServer(conn, &msg, address);
218*d9f75844SAndroid Build Coastguard Worker return;
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker }
221*d9f75844SAndroid Build Coastguard Worker
222*d9f75844SAndroid Build Coastguard Worker // Look up the key that we'll use to validate the M-I. If we have an
223*d9f75844SAndroid Build Coastguard Worker // existing allocation, the key will already be cached.
224*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* allocation = FindAllocation(conn);
225*d9f75844SAndroid Build Coastguard Worker std::string key;
226*d9f75844SAndroid Build Coastguard Worker if (!allocation) {
227*d9f75844SAndroid Build Coastguard Worker GetKey(&msg, &key);
228*d9f75844SAndroid Build Coastguard Worker } else {
229*d9f75844SAndroid Build Coastguard Worker key = allocation->key();
230*d9f75844SAndroid Build Coastguard Worker }
231*d9f75844SAndroid Build Coastguard Worker
232*d9f75844SAndroid Build Coastguard Worker // Ensure the message is authorized; only needed for requests.
233*d9f75844SAndroid Build Coastguard Worker if (IsStunRequestType(msg.type())) {
234*d9f75844SAndroid Build Coastguard Worker if (!CheckAuthorization(conn, &msg, data, size, key)) {
235*d9f75844SAndroid Build Coastguard Worker return;
236*d9f75844SAndroid Build Coastguard Worker }
237*d9f75844SAndroid Build Coastguard Worker }
238*d9f75844SAndroid Build Coastguard Worker
239*d9f75844SAndroid Build Coastguard Worker if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
240*d9f75844SAndroid Build Coastguard Worker HandleAllocateRequest(conn, &msg, key);
241*d9f75844SAndroid Build Coastguard Worker } else if (allocation &&
242*d9f75844SAndroid Build Coastguard Worker (msg.type() != STUN_ALLOCATE_REQUEST ||
243*d9f75844SAndroid Build Coastguard Worker msg.transaction_id() == allocation->transaction_id())) {
244*d9f75844SAndroid Build Coastguard Worker // This is a non-allocate request, or a retransmit of an allocate.
245*d9f75844SAndroid Build Coastguard Worker // Check that the username matches the previous username used.
246*d9f75844SAndroid Build Coastguard Worker if (IsStunRequestType(msg.type()) &&
247*d9f75844SAndroid Build Coastguard Worker msg.GetByteString(STUN_ATTR_USERNAME)->string_view() !=
248*d9f75844SAndroid Build Coastguard Worker allocation->username()) {
249*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
250*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_WRONG_CREDENTIALS);
251*d9f75844SAndroid Build Coastguard Worker return;
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker allocation->HandleTurnMessage(&msg);
254*d9f75844SAndroid Build Coastguard Worker } else {
255*d9f75844SAndroid Build Coastguard Worker // Allocation mismatch.
256*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH,
257*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_ALLOCATION_MISMATCH);
258*d9f75844SAndroid Build Coastguard Worker }
259*d9f75844SAndroid Build Coastguard Worker }
260*d9f75844SAndroid Build Coastguard Worker
GetKey(const StunMessage * msg,std::string * key)261*d9f75844SAndroid Build Coastguard Worker bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
262*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* username_attr =
263*d9f75844SAndroid Build Coastguard Worker msg->GetByteString(STUN_ATTR_USERNAME);
264*d9f75844SAndroid Build Coastguard Worker if (!username_attr) {
265*d9f75844SAndroid Build Coastguard Worker return false;
266*d9f75844SAndroid Build Coastguard Worker }
267*d9f75844SAndroid Build Coastguard Worker
268*d9f75844SAndroid Build Coastguard Worker return (auth_hook_ != NULL &&
269*d9f75844SAndroid Build Coastguard Worker auth_hook_->GetKey(std::string(username_attr->string_view()), realm_,
270*d9f75844SAndroid Build Coastguard Worker key));
271*d9f75844SAndroid Build Coastguard Worker }
272*d9f75844SAndroid Build Coastguard Worker
CheckAuthorization(TurnServerConnection * conn,StunMessage * msg,const char * data,size_t size,absl::string_view key)273*d9f75844SAndroid Build Coastguard Worker bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
274*d9f75844SAndroid Build Coastguard Worker StunMessage* msg,
275*d9f75844SAndroid Build Coastguard Worker const char* data,
276*d9f75844SAndroid Build Coastguard Worker size_t size,
277*d9f75844SAndroid Build Coastguard Worker absl::string_view key) {
278*d9f75844SAndroid Build Coastguard Worker // RFC 5389, 10.2.2.
279*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(IsStunRequestType(msg->type()));
280*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* mi_attr =
281*d9f75844SAndroid Build Coastguard Worker msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
282*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* username_attr =
283*d9f75844SAndroid Build Coastguard Worker msg->GetByteString(STUN_ATTR_USERNAME);
284*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* realm_attr =
285*d9f75844SAndroid Build Coastguard Worker msg->GetByteString(STUN_ATTR_REALM);
286*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* nonce_attr =
287*d9f75844SAndroid Build Coastguard Worker msg->GetByteString(STUN_ATTR_NONCE);
288*d9f75844SAndroid Build Coastguard Worker
289*d9f75844SAndroid Build Coastguard Worker // Fail if no MESSAGE_INTEGRITY.
290*d9f75844SAndroid Build Coastguard Worker if (!mi_attr) {
291*d9f75844SAndroid Build Coastguard Worker SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
292*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_UNAUTHORIZED);
293*d9f75844SAndroid Build Coastguard Worker return false;
294*d9f75844SAndroid Build Coastguard Worker }
295*d9f75844SAndroid Build Coastguard Worker
296*d9f75844SAndroid Build Coastguard Worker // Fail if there is MESSAGE_INTEGRITY but no username, nonce, or realm.
297*d9f75844SAndroid Build Coastguard Worker if (!username_attr || !realm_attr || !nonce_attr) {
298*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
299*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_BAD_REQUEST);
300*d9f75844SAndroid Build Coastguard Worker return false;
301*d9f75844SAndroid Build Coastguard Worker }
302*d9f75844SAndroid Build Coastguard Worker
303*d9f75844SAndroid Build Coastguard Worker // Fail if bad nonce.
304*d9f75844SAndroid Build Coastguard Worker if (!ValidateNonce(nonce_attr->string_view())) {
305*d9f75844SAndroid Build Coastguard Worker SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
306*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_STALE_NONCE);
307*d9f75844SAndroid Build Coastguard Worker return false;
308*d9f75844SAndroid Build Coastguard Worker }
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker // Fail if bad MESSAGE_INTEGRITY.
311*d9f75844SAndroid Build Coastguard Worker if (key.empty() || msg->ValidateMessageIntegrity(std::string(key)) !=
312*d9f75844SAndroid Build Coastguard Worker StunMessage::IntegrityStatus::kIntegrityOk) {
313*d9f75844SAndroid Build Coastguard Worker SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
314*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_UNAUTHORIZED);
315*d9f75844SAndroid Build Coastguard Worker return false;
316*d9f75844SAndroid Build Coastguard Worker }
317*d9f75844SAndroid Build Coastguard Worker
318*d9f75844SAndroid Build Coastguard Worker // Fail if one-time-use nonce feature is enabled.
319*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* allocation = FindAllocation(conn);
320*d9f75844SAndroid Build Coastguard Worker if (enable_otu_nonce_ && allocation &&
321*d9f75844SAndroid Build Coastguard Worker allocation->last_nonce() == nonce_attr->string_view()) {
322*d9f75844SAndroid Build Coastguard Worker SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
323*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_STALE_NONCE);
324*d9f75844SAndroid Build Coastguard Worker return false;
325*d9f75844SAndroid Build Coastguard Worker }
326*d9f75844SAndroid Build Coastguard Worker
327*d9f75844SAndroid Build Coastguard Worker if (allocation) {
328*d9f75844SAndroid Build Coastguard Worker allocation->set_last_nonce(nonce_attr->string_view());
329*d9f75844SAndroid Build Coastguard Worker }
330*d9f75844SAndroid Build Coastguard Worker // Success.
331*d9f75844SAndroid Build Coastguard Worker return true;
332*d9f75844SAndroid Build Coastguard Worker }
333*d9f75844SAndroid Build Coastguard Worker
HandleBindingRequest(TurnServerConnection * conn,const StunMessage * req)334*d9f75844SAndroid Build Coastguard Worker void TurnServer::HandleBindingRequest(TurnServerConnection* conn,
335*d9f75844SAndroid Build Coastguard Worker const StunMessage* req) {
336*d9f75844SAndroid Build Coastguard Worker StunMessage response(GetStunSuccessResponseTypeOrZero(*req),
337*d9f75844SAndroid Build Coastguard Worker req->transaction_id());
338*d9f75844SAndroid Build Coastguard Worker // Tell the user the address that we received their request from.
339*d9f75844SAndroid Build Coastguard Worker auto mapped_addr_attr = std::make_unique<StunXorAddressAttribute>(
340*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
341*d9f75844SAndroid Build Coastguard Worker response.AddAttribute(std::move(mapped_addr_attr));
342*d9f75844SAndroid Build Coastguard Worker
343*d9f75844SAndroid Build Coastguard Worker SendStun(conn, &response);
344*d9f75844SAndroid Build Coastguard Worker }
345*d9f75844SAndroid Build Coastguard Worker
HandleAllocateRequest(TurnServerConnection * conn,const TurnMessage * msg,absl::string_view key)346*d9f75844SAndroid Build Coastguard Worker void TurnServer::HandleAllocateRequest(TurnServerConnection* conn,
347*d9f75844SAndroid Build Coastguard Worker const TurnMessage* msg,
348*d9f75844SAndroid Build Coastguard Worker absl::string_view key) {
349*d9f75844SAndroid Build Coastguard Worker // Check the parameters in the request.
350*d9f75844SAndroid Build Coastguard Worker const StunUInt32Attribute* transport_attr =
351*d9f75844SAndroid Build Coastguard Worker msg->GetUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
352*d9f75844SAndroid Build Coastguard Worker if (!transport_attr) {
353*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
354*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_BAD_REQUEST);
355*d9f75844SAndroid Build Coastguard Worker return;
356*d9f75844SAndroid Build Coastguard Worker }
357*d9f75844SAndroid Build Coastguard Worker
358*d9f75844SAndroid Build Coastguard Worker // Only UDP is supported right now.
359*d9f75844SAndroid Build Coastguard Worker int proto = transport_attr->value() >> 24;
360*d9f75844SAndroid Build Coastguard Worker if (proto != IPPROTO_UDP) {
361*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(conn, msg, STUN_ERROR_UNSUPPORTED_PROTOCOL,
362*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL);
363*d9f75844SAndroid Build Coastguard Worker return;
364*d9f75844SAndroid Build Coastguard Worker }
365*d9f75844SAndroid Build Coastguard Worker
366*d9f75844SAndroid Build Coastguard Worker // Create the allocation and let it send the success response.
367*d9f75844SAndroid Build Coastguard Worker // If the actual socket allocation fails, send an internal error.
368*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* alloc = CreateAllocation(conn, proto, key);
369*d9f75844SAndroid Build Coastguard Worker if (alloc) {
370*d9f75844SAndroid Build Coastguard Worker alloc->HandleTurnMessage(msg);
371*d9f75844SAndroid Build Coastguard Worker } else {
372*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR,
373*d9f75844SAndroid Build Coastguard Worker "Failed to allocate socket");
374*d9f75844SAndroid Build Coastguard Worker }
375*d9f75844SAndroid Build Coastguard Worker }
376*d9f75844SAndroid Build Coastguard Worker
GenerateNonce(int64_t now) const377*d9f75844SAndroid Build Coastguard Worker std::string TurnServer::GenerateNonce(int64_t now) const {
378*d9f75844SAndroid Build Coastguard Worker // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
379*d9f75844SAndroid Build Coastguard Worker std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
380*d9f75844SAndroid Build Coastguard Worker std::string nonce = rtc::hex_encode(input);
381*d9f75844SAndroid Build Coastguard Worker nonce += rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, input);
382*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(nonce.size() == kNonceSize);
383*d9f75844SAndroid Build Coastguard Worker
384*d9f75844SAndroid Build Coastguard Worker return nonce;
385*d9f75844SAndroid Build Coastguard Worker }
386*d9f75844SAndroid Build Coastguard Worker
ValidateNonce(absl::string_view nonce) const387*d9f75844SAndroid Build Coastguard Worker bool TurnServer::ValidateNonce(absl::string_view nonce) const {
388*d9f75844SAndroid Build Coastguard Worker // Check the size.
389*d9f75844SAndroid Build Coastguard Worker if (nonce.size() != kNonceSize) {
390*d9f75844SAndroid Build Coastguard Worker return false;
391*d9f75844SAndroid Build Coastguard Worker }
392*d9f75844SAndroid Build Coastguard Worker
393*d9f75844SAndroid Build Coastguard Worker // Decode the timestamp.
394*d9f75844SAndroid Build Coastguard Worker int64_t then;
395*d9f75844SAndroid Build Coastguard Worker char* p = reinterpret_cast<char*>(&then);
396*d9f75844SAndroid Build Coastguard Worker size_t len = rtc::hex_decode(rtc::ArrayView<char>(p, sizeof(then)),
397*d9f75844SAndroid Build Coastguard Worker nonce.substr(0, sizeof(then) * 2));
398*d9f75844SAndroid Build Coastguard Worker if (len != sizeof(then)) {
399*d9f75844SAndroid Build Coastguard Worker return false;
400*d9f75844SAndroid Build Coastguard Worker }
401*d9f75844SAndroid Build Coastguard Worker
402*d9f75844SAndroid Build Coastguard Worker // Verify the HMAC.
403*d9f75844SAndroid Build Coastguard Worker if (nonce.substr(sizeof(then) * 2) !=
404*d9f75844SAndroid Build Coastguard Worker rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_,
405*d9f75844SAndroid Build Coastguard Worker std::string(p, sizeof(then)))) {
406*d9f75844SAndroid Build Coastguard Worker return false;
407*d9f75844SAndroid Build Coastguard Worker }
408*d9f75844SAndroid Build Coastguard Worker
409*d9f75844SAndroid Build Coastguard Worker // Validate the timestamp.
410*d9f75844SAndroid Build Coastguard Worker return TimeDelta::Millis(rtc::TimeMillis() - then) < kNonceTimeout;
411*d9f75844SAndroid Build Coastguard Worker }
412*d9f75844SAndroid Build Coastguard Worker
FindAllocation(TurnServerConnection * conn)413*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) {
414*d9f75844SAndroid Build Coastguard Worker AllocationMap::const_iterator it = allocations_.find(*conn);
415*d9f75844SAndroid Build Coastguard Worker return (it != allocations_.end()) ? it->second.get() : nullptr;
416*d9f75844SAndroid Build Coastguard Worker }
417*d9f75844SAndroid Build Coastguard Worker
CreateAllocation(TurnServerConnection * conn,int proto,absl::string_view key)418*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn,
419*d9f75844SAndroid Build Coastguard Worker int proto,
420*d9f75844SAndroid Build Coastguard Worker absl::string_view key) {
421*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* external_socket =
422*d9f75844SAndroid Build Coastguard Worker (external_socket_factory_)
423*d9f75844SAndroid Build Coastguard Worker ? external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0)
424*d9f75844SAndroid Build Coastguard Worker : NULL;
425*d9f75844SAndroid Build Coastguard Worker if (!external_socket) {
426*d9f75844SAndroid Build Coastguard Worker return NULL;
427*d9f75844SAndroid Build Coastguard Worker }
428*d9f75844SAndroid Build Coastguard Worker
429*d9f75844SAndroid Build Coastguard Worker // The Allocation takes ownership of the socket.
430*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation* allocation =
431*d9f75844SAndroid Build Coastguard Worker new TurnServerAllocation(this, thread_, *conn, external_socket, key);
432*d9f75844SAndroid Build Coastguard Worker allocations_[*conn].reset(allocation);
433*d9f75844SAndroid Build Coastguard Worker return allocation;
434*d9f75844SAndroid Build Coastguard Worker }
435*d9f75844SAndroid Build Coastguard Worker
SendErrorResponse(TurnServerConnection * conn,const StunMessage * req,int code,absl::string_view reason)436*d9f75844SAndroid Build Coastguard Worker void TurnServer::SendErrorResponse(TurnServerConnection* conn,
437*d9f75844SAndroid Build Coastguard Worker const StunMessage* req,
438*d9f75844SAndroid Build Coastguard Worker int code,
439*d9f75844SAndroid Build Coastguard Worker absl::string_view reason) {
440*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
441*d9f75844SAndroid Build Coastguard Worker TurnMessage resp(GetStunErrorResponseTypeOrZero(*req), req->transaction_id());
442*d9f75844SAndroid Build Coastguard Worker InitErrorResponse(code, reason, &resp);
443*d9f75844SAndroid Build Coastguard Worker
444*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Sending error response, type=" << resp.type()
445*d9f75844SAndroid Build Coastguard Worker << ", code=" << code << ", reason=" << reason;
446*d9f75844SAndroid Build Coastguard Worker SendStun(conn, &resp);
447*d9f75844SAndroid Build Coastguard Worker }
448*d9f75844SAndroid Build Coastguard Worker
SendErrorResponseWithRealmAndNonce(TurnServerConnection * conn,const StunMessage * msg,int code,absl::string_view reason)449*d9f75844SAndroid Build Coastguard Worker void TurnServer::SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn,
450*d9f75844SAndroid Build Coastguard Worker const StunMessage* msg,
451*d9f75844SAndroid Build Coastguard Worker int code,
452*d9f75844SAndroid Build Coastguard Worker absl::string_view reason) {
453*d9f75844SAndroid Build Coastguard Worker TurnMessage resp(GetStunErrorResponseTypeOrZero(*msg), msg->transaction_id());
454*d9f75844SAndroid Build Coastguard Worker InitErrorResponse(code, reason, &resp);
455*d9f75844SAndroid Build Coastguard Worker
456*d9f75844SAndroid Build Coastguard Worker int64_t timestamp = rtc::TimeMillis();
457*d9f75844SAndroid Build Coastguard Worker if (ts_for_next_nonce_) {
458*d9f75844SAndroid Build Coastguard Worker timestamp = ts_for_next_nonce_;
459*d9f75844SAndroid Build Coastguard Worker ts_for_next_nonce_ = 0;
460*d9f75844SAndroid Build Coastguard Worker }
461*d9f75844SAndroid Build Coastguard Worker resp.AddAttribute(std::make_unique<StunByteStringAttribute>(
462*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_NONCE, GenerateNonce(timestamp)));
463*d9f75844SAndroid Build Coastguard Worker resp.AddAttribute(
464*d9f75844SAndroid Build Coastguard Worker std::make_unique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
465*d9f75844SAndroid Build Coastguard Worker SendStun(conn, &resp);
466*d9f75844SAndroid Build Coastguard Worker }
467*d9f75844SAndroid Build Coastguard Worker
SendErrorResponseWithAlternateServer(TurnServerConnection * conn,const StunMessage * msg,const rtc::SocketAddress & addr)468*d9f75844SAndroid Build Coastguard Worker void TurnServer::SendErrorResponseWithAlternateServer(
469*d9f75844SAndroid Build Coastguard Worker TurnServerConnection* conn,
470*d9f75844SAndroid Build Coastguard Worker const StunMessage* msg,
471*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& addr) {
472*d9f75844SAndroid Build Coastguard Worker TurnMessage resp(GetStunErrorResponseTypeOrZero(*msg), msg->transaction_id());
473*d9f75844SAndroid Build Coastguard Worker InitErrorResponse(STUN_ERROR_TRY_ALTERNATE,
474*d9f75844SAndroid Build Coastguard Worker STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
475*d9f75844SAndroid Build Coastguard Worker resp.AddAttribute(
476*d9f75844SAndroid Build Coastguard Worker std::make_unique<StunAddressAttribute>(STUN_ATTR_ALTERNATE_SERVER, addr));
477*d9f75844SAndroid Build Coastguard Worker SendStun(conn, &resp);
478*d9f75844SAndroid Build Coastguard Worker }
479*d9f75844SAndroid Build Coastguard Worker
SendStun(TurnServerConnection * conn,StunMessage * msg)480*d9f75844SAndroid Build Coastguard Worker void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
481*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
482*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter buf;
483*d9f75844SAndroid Build Coastguard Worker // Add a SOFTWARE attribute if one is set.
484*d9f75844SAndroid Build Coastguard Worker if (!software_.empty()) {
485*d9f75844SAndroid Build Coastguard Worker msg->AddAttribute(std::make_unique<StunByteStringAttribute>(
486*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_SOFTWARE, software_));
487*d9f75844SAndroid Build Coastguard Worker }
488*d9f75844SAndroid Build Coastguard Worker msg->Write(&buf);
489*d9f75844SAndroid Build Coastguard Worker Send(conn, buf);
490*d9f75844SAndroid Build Coastguard Worker }
491*d9f75844SAndroid Build Coastguard Worker
Send(TurnServerConnection * conn,const rtc::ByteBufferWriter & buf)492*d9f75844SAndroid Build Coastguard Worker void TurnServer::Send(TurnServerConnection* conn,
493*d9f75844SAndroid Build Coastguard Worker const rtc::ByteBufferWriter& buf) {
494*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(thread_);
495*d9f75844SAndroid Build Coastguard Worker rtc::PacketOptions options;
496*d9f75844SAndroid Build Coastguard Worker conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
497*d9f75844SAndroid Build Coastguard Worker }
498*d9f75844SAndroid Build Coastguard Worker
DestroyAllocation(TurnServerAllocation * allocation)499*d9f75844SAndroid Build Coastguard Worker void TurnServer::DestroyAllocation(TurnServerAllocation* allocation) {
500*d9f75844SAndroid Build Coastguard Worker // Removing the internal socket if the connection is not udp.
501*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* socket = allocation->conn()->socket();
502*d9f75844SAndroid Build Coastguard Worker InternalSocketMap::iterator iter = server_sockets_.find(socket);
503*d9f75844SAndroid Build Coastguard Worker // Skip if the socket serving this allocation is UDP, as this will be shared
504*d9f75844SAndroid Build Coastguard Worker // by all allocations.
505*d9f75844SAndroid Build Coastguard Worker // Note: We may not find a socket if it's a TCP socket that was closed, and
506*d9f75844SAndroid Build Coastguard Worker // the allocation is only now timing out.
507*d9f75844SAndroid Build Coastguard Worker if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) {
508*d9f75844SAndroid Build Coastguard Worker DestroyInternalSocket(socket);
509*d9f75844SAndroid Build Coastguard Worker }
510*d9f75844SAndroid Build Coastguard Worker
511*d9f75844SAndroid Build Coastguard Worker allocations_.erase(*(allocation->conn()));
512*d9f75844SAndroid Build Coastguard Worker }
513*d9f75844SAndroid Build Coastguard Worker
DestroyInternalSocket(rtc::AsyncPacketSocket * socket)514*d9f75844SAndroid Build Coastguard Worker void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
515*d9f75844SAndroid Build Coastguard Worker InternalSocketMap::iterator iter = server_sockets_.find(socket);
516*d9f75844SAndroid Build Coastguard Worker if (iter != server_sockets_.end()) {
517*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* socket = iter->first;
518*d9f75844SAndroid Build Coastguard Worker socket->UnsubscribeClose(this);
519*d9f75844SAndroid Build Coastguard Worker socket->SignalReadPacket.disconnect(this);
520*d9f75844SAndroid Build Coastguard Worker server_sockets_.erase(iter);
521*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::AsyncPacketSocket> socket_to_delete =
522*d9f75844SAndroid Build Coastguard Worker absl::WrapUnique(socket);
523*d9f75844SAndroid Build Coastguard Worker // We must destroy the socket async to avoid invalidating the sigslot
524*d9f75844SAndroid Build Coastguard Worker // callback list iterator inside a sigslot callback. (In other words,
525*d9f75844SAndroid Build Coastguard Worker // deleting an object from within a callback from that object).
526*d9f75844SAndroid Build Coastguard Worker thread_->PostTask([socket_to_delete = std::move(socket_to_delete)] {});
527*d9f75844SAndroid Build Coastguard Worker }
528*d9f75844SAndroid Build Coastguard Worker }
529*d9f75844SAndroid Build Coastguard Worker
TurnServerConnection(const rtc::SocketAddress & src,ProtocolType proto,rtc::AsyncPacketSocket * socket)530*d9f75844SAndroid Build Coastguard Worker TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src,
531*d9f75844SAndroid Build Coastguard Worker ProtocolType proto,
532*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* socket)
533*d9f75844SAndroid Build Coastguard Worker : src_(src),
534*d9f75844SAndroid Build Coastguard Worker dst_(socket->GetRemoteAddress()),
535*d9f75844SAndroid Build Coastguard Worker proto_(proto),
536*d9f75844SAndroid Build Coastguard Worker socket_(socket) {}
537*d9f75844SAndroid Build Coastguard Worker
operator ==(const TurnServerConnection & c) const538*d9f75844SAndroid Build Coastguard Worker bool TurnServerConnection::operator==(const TurnServerConnection& c) const {
539*d9f75844SAndroid Build Coastguard Worker return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
540*d9f75844SAndroid Build Coastguard Worker }
541*d9f75844SAndroid Build Coastguard Worker
operator <(const TurnServerConnection & c) const542*d9f75844SAndroid Build Coastguard Worker bool TurnServerConnection::operator<(const TurnServerConnection& c) const {
543*d9f75844SAndroid Build Coastguard Worker return std::tie(src_, dst_, proto_) < std::tie(c.src_, c.dst_, c.proto_);
544*d9f75844SAndroid Build Coastguard Worker }
545*d9f75844SAndroid Build Coastguard Worker
ToString() const546*d9f75844SAndroid Build Coastguard Worker std::string TurnServerConnection::ToString() const {
547*d9f75844SAndroid Build Coastguard Worker const char* const kProtos[] = {"unknown", "udp", "tcp", "ssltcp"};
548*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder ost;
549*d9f75844SAndroid Build Coastguard Worker ost << src_.ToSensitiveString() << "-" << dst_.ToSensitiveString() << ":"
550*d9f75844SAndroid Build Coastguard Worker << kProtos[proto_];
551*d9f75844SAndroid Build Coastguard Worker return ost.Release();
552*d9f75844SAndroid Build Coastguard Worker }
553*d9f75844SAndroid Build Coastguard Worker
TurnServerAllocation(TurnServer * server,webrtc::TaskQueueBase * thread,const TurnServerConnection & conn,rtc::AsyncPacketSocket * socket,absl::string_view key)554*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation::TurnServerAllocation(TurnServer* server,
555*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase* thread,
556*d9f75844SAndroid Build Coastguard Worker const TurnServerConnection& conn,
557*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* socket,
558*d9f75844SAndroid Build Coastguard Worker absl::string_view key)
559*d9f75844SAndroid Build Coastguard Worker : server_(server),
560*d9f75844SAndroid Build Coastguard Worker thread_(thread),
561*d9f75844SAndroid Build Coastguard Worker conn_(conn),
562*d9f75844SAndroid Build Coastguard Worker external_socket_(socket),
563*d9f75844SAndroid Build Coastguard Worker key_(key) {
564*d9f75844SAndroid Build Coastguard Worker external_socket_->SignalReadPacket.connect(
565*d9f75844SAndroid Build Coastguard Worker this, &TurnServerAllocation::OnExternalPacket);
566*d9f75844SAndroid Build Coastguard Worker }
567*d9f75844SAndroid Build Coastguard Worker
~TurnServerAllocation()568*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation::~TurnServerAllocation() {
569*d9f75844SAndroid Build Coastguard Worker channels_.clear();
570*d9f75844SAndroid Build Coastguard Worker perms_.clear();
571*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << ToString() << ": Allocation destroyed";
572*d9f75844SAndroid Build Coastguard Worker }
573*d9f75844SAndroid Build Coastguard Worker
ToString() const574*d9f75844SAndroid Build Coastguard Worker std::string TurnServerAllocation::ToString() const {
575*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder ost;
576*d9f75844SAndroid Build Coastguard Worker ost << "Alloc[" << conn_.ToString() << "]";
577*d9f75844SAndroid Build Coastguard Worker return ost.Release();
578*d9f75844SAndroid Build Coastguard Worker }
579*d9f75844SAndroid Build Coastguard Worker
HandleTurnMessage(const TurnMessage * msg)580*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) {
581*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(msg != NULL);
582*d9f75844SAndroid Build Coastguard Worker switch (msg->type()) {
583*d9f75844SAndroid Build Coastguard Worker case STUN_ALLOCATE_REQUEST:
584*d9f75844SAndroid Build Coastguard Worker HandleAllocateRequest(msg);
585*d9f75844SAndroid Build Coastguard Worker break;
586*d9f75844SAndroid Build Coastguard Worker case TURN_REFRESH_REQUEST:
587*d9f75844SAndroid Build Coastguard Worker HandleRefreshRequest(msg);
588*d9f75844SAndroid Build Coastguard Worker break;
589*d9f75844SAndroid Build Coastguard Worker case TURN_SEND_INDICATION:
590*d9f75844SAndroid Build Coastguard Worker HandleSendIndication(msg);
591*d9f75844SAndroid Build Coastguard Worker break;
592*d9f75844SAndroid Build Coastguard Worker case TURN_CREATE_PERMISSION_REQUEST:
593*d9f75844SAndroid Build Coastguard Worker HandleCreatePermissionRequest(msg);
594*d9f75844SAndroid Build Coastguard Worker break;
595*d9f75844SAndroid Build Coastguard Worker case TURN_CHANNEL_BIND_REQUEST:
596*d9f75844SAndroid Build Coastguard Worker HandleChannelBindRequest(msg);
597*d9f75844SAndroid Build Coastguard Worker break;
598*d9f75844SAndroid Build Coastguard Worker default:
599*d9f75844SAndroid Build Coastguard Worker // Not sure what to do with this, just eat it.
600*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << ToString()
601*d9f75844SAndroid Build Coastguard Worker << ": Invalid TURN message type received: "
602*d9f75844SAndroid Build Coastguard Worker << msg->type();
603*d9f75844SAndroid Build Coastguard Worker }
604*d9f75844SAndroid Build Coastguard Worker }
605*d9f75844SAndroid Build Coastguard Worker
HandleAllocateRequest(const TurnMessage * msg)606*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
607*d9f75844SAndroid Build Coastguard Worker // Copy the important info from the allocate request.
608*d9f75844SAndroid Build Coastguard Worker transaction_id_ = msg->transaction_id();
609*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* username_attr =
610*d9f75844SAndroid Build Coastguard Worker msg->GetByteString(STUN_ATTR_USERNAME);
611*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(username_attr != NULL);
612*d9f75844SAndroid Build Coastguard Worker username_ = std::string(username_attr->string_view());
613*d9f75844SAndroid Build Coastguard Worker
614*d9f75844SAndroid Build Coastguard Worker // Figure out the lifetime and start the allocation timer.
615*d9f75844SAndroid Build Coastguard Worker TimeDelta lifetime = ComputeLifetime(*msg);
616*d9f75844SAndroid Build Coastguard Worker PostDeleteSelf(lifetime);
617*d9f75844SAndroid Build Coastguard Worker
618*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << ToString() << ": Created allocation with lifetime="
619*d9f75844SAndroid Build Coastguard Worker << lifetime.seconds();
620*d9f75844SAndroid Build Coastguard Worker
621*d9f75844SAndroid Build Coastguard Worker // We've already validated all the important bits; just send a response here.
622*d9f75844SAndroid Build Coastguard Worker TurnMessage response(GetStunSuccessResponseTypeOrZero(*msg),
623*d9f75844SAndroid Build Coastguard Worker msg->transaction_id());
624*d9f75844SAndroid Build Coastguard Worker
625*d9f75844SAndroid Build Coastguard Worker auto mapped_addr_attr = std::make_unique<StunXorAddressAttribute>(
626*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
627*d9f75844SAndroid Build Coastguard Worker auto relayed_addr_attr = std::make_unique<StunXorAddressAttribute>(
628*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress());
629*d9f75844SAndroid Build Coastguard Worker auto lifetime_attr = std::make_unique<StunUInt32Attribute>(
630*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_LIFETIME, lifetime.seconds());
631*d9f75844SAndroid Build Coastguard Worker response.AddAttribute(std::move(mapped_addr_attr));
632*d9f75844SAndroid Build Coastguard Worker response.AddAttribute(std::move(relayed_addr_attr));
633*d9f75844SAndroid Build Coastguard Worker response.AddAttribute(std::move(lifetime_attr));
634*d9f75844SAndroid Build Coastguard Worker
635*d9f75844SAndroid Build Coastguard Worker SendResponse(&response);
636*d9f75844SAndroid Build Coastguard Worker }
637*d9f75844SAndroid Build Coastguard Worker
HandleRefreshRequest(const TurnMessage * msg)638*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) {
639*d9f75844SAndroid Build Coastguard Worker // Figure out the new lifetime.
640*d9f75844SAndroid Build Coastguard Worker TimeDelta lifetime = ComputeLifetime(*msg);
641*d9f75844SAndroid Build Coastguard Worker
642*d9f75844SAndroid Build Coastguard Worker // Reset the expiration timer.
643*d9f75844SAndroid Build Coastguard Worker safety_.reset();
644*d9f75844SAndroid Build Coastguard Worker PostDeleteSelf(lifetime);
645*d9f75844SAndroid Build Coastguard Worker
646*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << ToString()
647*d9f75844SAndroid Build Coastguard Worker << ": Refreshed allocation, lifetime=" << lifetime.seconds();
648*d9f75844SAndroid Build Coastguard Worker
649*d9f75844SAndroid Build Coastguard Worker // Send a success response with a LIFETIME attribute.
650*d9f75844SAndroid Build Coastguard Worker TurnMessage response(GetStunSuccessResponseTypeOrZero(*msg),
651*d9f75844SAndroid Build Coastguard Worker msg->transaction_id());
652*d9f75844SAndroid Build Coastguard Worker
653*d9f75844SAndroid Build Coastguard Worker auto lifetime_attr = std::make_unique<StunUInt32Attribute>(
654*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_LIFETIME, lifetime.seconds());
655*d9f75844SAndroid Build Coastguard Worker response.AddAttribute(std::move(lifetime_attr));
656*d9f75844SAndroid Build Coastguard Worker
657*d9f75844SAndroid Build Coastguard Worker SendResponse(&response);
658*d9f75844SAndroid Build Coastguard Worker }
659*d9f75844SAndroid Build Coastguard Worker
HandleSendIndication(const TurnMessage * msg)660*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) {
661*d9f75844SAndroid Build Coastguard Worker // Check mandatory attributes.
662*d9f75844SAndroid Build Coastguard Worker const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
663*d9f75844SAndroid Build Coastguard Worker const StunAddressAttribute* peer_attr =
664*d9f75844SAndroid Build Coastguard Worker msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
665*d9f75844SAndroid Build Coastguard Worker if (!data_attr || !peer_attr) {
666*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << ToString() << ": Received invalid send indication";
667*d9f75844SAndroid Build Coastguard Worker return;
668*d9f75844SAndroid Build Coastguard Worker }
669*d9f75844SAndroid Build Coastguard Worker
670*d9f75844SAndroid Build Coastguard Worker // If a permission exists, send the data on to the peer.
671*d9f75844SAndroid Build Coastguard Worker if (HasPermission(peer_attr->GetAddress().ipaddr())) {
672*d9f75844SAndroid Build Coastguard Worker SendExternal(data_attr->bytes(), data_attr->length(),
673*d9f75844SAndroid Build Coastguard Worker peer_attr->GetAddress());
674*d9f75844SAndroid Build Coastguard Worker } else {
675*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << ToString()
676*d9f75844SAndroid Build Coastguard Worker << ": Received send indication without permission"
677*d9f75844SAndroid Build Coastguard Worker " peer="
678*d9f75844SAndroid Build Coastguard Worker << peer_attr->GetAddress().ToSensitiveString();
679*d9f75844SAndroid Build Coastguard Worker }
680*d9f75844SAndroid Build Coastguard Worker }
681*d9f75844SAndroid Build Coastguard Worker
HandleCreatePermissionRequest(const TurnMessage * msg)682*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleCreatePermissionRequest(
683*d9f75844SAndroid Build Coastguard Worker const TurnMessage* msg) {
684*d9f75844SAndroid Build Coastguard Worker // Check mandatory attributes.
685*d9f75844SAndroid Build Coastguard Worker const StunAddressAttribute* peer_attr =
686*d9f75844SAndroid Build Coastguard Worker msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
687*d9f75844SAndroid Build Coastguard Worker if (!peer_attr) {
688*d9f75844SAndroid Build Coastguard Worker SendBadRequestResponse(msg);
689*d9f75844SAndroid Build Coastguard Worker return;
690*d9f75844SAndroid Build Coastguard Worker }
691*d9f75844SAndroid Build Coastguard Worker
692*d9f75844SAndroid Build Coastguard Worker if (server_->reject_private_addresses_ &&
693*d9f75844SAndroid Build Coastguard Worker rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) {
694*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN);
695*d9f75844SAndroid Build Coastguard Worker return;
696*d9f75844SAndroid Build Coastguard Worker }
697*d9f75844SAndroid Build Coastguard Worker
698*d9f75844SAndroid Build Coastguard Worker // Add this permission.
699*d9f75844SAndroid Build Coastguard Worker AddPermission(peer_attr->GetAddress().ipaddr());
700*d9f75844SAndroid Build Coastguard Worker
701*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << ToString() << ": Created permission, peer="
702*d9f75844SAndroid Build Coastguard Worker << peer_attr->GetAddress().ToSensitiveString();
703*d9f75844SAndroid Build Coastguard Worker
704*d9f75844SAndroid Build Coastguard Worker // Send a success response.
705*d9f75844SAndroid Build Coastguard Worker TurnMessage response(GetStunSuccessResponseTypeOrZero(*msg),
706*d9f75844SAndroid Build Coastguard Worker msg->transaction_id());
707*d9f75844SAndroid Build Coastguard Worker SendResponse(&response);
708*d9f75844SAndroid Build Coastguard Worker }
709*d9f75844SAndroid Build Coastguard Worker
HandleChannelBindRequest(const TurnMessage * msg)710*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) {
711*d9f75844SAndroid Build Coastguard Worker // Check mandatory attributes.
712*d9f75844SAndroid Build Coastguard Worker const StunUInt32Attribute* channel_attr =
713*d9f75844SAndroid Build Coastguard Worker msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
714*d9f75844SAndroid Build Coastguard Worker const StunAddressAttribute* peer_attr =
715*d9f75844SAndroid Build Coastguard Worker msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
716*d9f75844SAndroid Build Coastguard Worker if (!channel_attr || !peer_attr) {
717*d9f75844SAndroid Build Coastguard Worker SendBadRequestResponse(msg);
718*d9f75844SAndroid Build Coastguard Worker return;
719*d9f75844SAndroid Build Coastguard Worker }
720*d9f75844SAndroid Build Coastguard Worker
721*d9f75844SAndroid Build Coastguard Worker // Check that channel id is valid.
722*d9f75844SAndroid Build Coastguard Worker int channel_id = channel_attr->value() >> 16;
723*d9f75844SAndroid Build Coastguard Worker if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) {
724*d9f75844SAndroid Build Coastguard Worker SendBadRequestResponse(msg);
725*d9f75844SAndroid Build Coastguard Worker return;
726*d9f75844SAndroid Build Coastguard Worker }
727*d9f75844SAndroid Build Coastguard Worker
728*d9f75844SAndroid Build Coastguard Worker // Check that this channel id isn't bound to another transport address, and
729*d9f75844SAndroid Build Coastguard Worker // that this transport address isn't bound to another channel id.
730*d9f75844SAndroid Build Coastguard Worker auto channel1 = FindChannel(channel_id);
731*d9f75844SAndroid Build Coastguard Worker auto channel2 = FindChannel(peer_attr->GetAddress());
732*d9f75844SAndroid Build Coastguard Worker if (channel1 != channel2) {
733*d9f75844SAndroid Build Coastguard Worker SendBadRequestResponse(msg);
734*d9f75844SAndroid Build Coastguard Worker return;
735*d9f75844SAndroid Build Coastguard Worker }
736*d9f75844SAndroid Build Coastguard Worker
737*d9f75844SAndroid Build Coastguard Worker // Add or refresh this channel.
738*d9f75844SAndroid Build Coastguard Worker if (channel1 == channels_.end()) {
739*d9f75844SAndroid Build Coastguard Worker channel1 = channels_.insert(
740*d9f75844SAndroid Build Coastguard Worker channels_.end(), {.id = channel_id, .peer = peer_attr->GetAddress()});
741*d9f75844SAndroid Build Coastguard Worker } else {
742*d9f75844SAndroid Build Coastguard Worker channel1->pending_delete.reset();
743*d9f75844SAndroid Build Coastguard Worker }
744*d9f75844SAndroid Build Coastguard Worker thread_->PostDelayedTask(
745*d9f75844SAndroid Build Coastguard Worker SafeTask(channel1->pending_delete.flag(),
746*d9f75844SAndroid Build Coastguard Worker [this, channel1] { channels_.erase(channel1); }),
747*d9f75844SAndroid Build Coastguard Worker kChannelTimeout);
748*d9f75844SAndroid Build Coastguard Worker
749*d9f75844SAndroid Build Coastguard Worker // Channel binds also refresh permissions.
750*d9f75844SAndroid Build Coastguard Worker AddPermission(peer_attr->GetAddress().ipaddr());
751*d9f75844SAndroid Build Coastguard Worker
752*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << ToString() << ": Bound channel, id=" << channel_id
753*d9f75844SAndroid Build Coastguard Worker << ", peer=" << peer_attr->GetAddress().ToSensitiveString();
754*d9f75844SAndroid Build Coastguard Worker
755*d9f75844SAndroid Build Coastguard Worker // Send a success response.
756*d9f75844SAndroid Build Coastguard Worker TurnMessage response(GetStunSuccessResponseTypeOrZero(*msg),
757*d9f75844SAndroid Build Coastguard Worker msg->transaction_id());
758*d9f75844SAndroid Build Coastguard Worker SendResponse(&response);
759*d9f75844SAndroid Build Coastguard Worker }
760*d9f75844SAndroid Build Coastguard Worker
HandleChannelData(const char * data,size_t size)761*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::HandleChannelData(const char* data, size_t size) {
762*d9f75844SAndroid Build Coastguard Worker // Extract the channel number from the data.
763*d9f75844SAndroid Build Coastguard Worker uint16_t channel_id = rtc::GetBE16(data);
764*d9f75844SAndroid Build Coastguard Worker auto channel = FindChannel(channel_id);
765*d9f75844SAndroid Build Coastguard Worker if (channel != channels_.end()) {
766*d9f75844SAndroid Build Coastguard Worker // Send the data to the peer address.
767*d9f75844SAndroid Build Coastguard Worker SendExternal(data + TURN_CHANNEL_HEADER_SIZE,
768*d9f75844SAndroid Build Coastguard Worker size - TURN_CHANNEL_HEADER_SIZE, channel->peer);
769*d9f75844SAndroid Build Coastguard Worker } else {
770*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << ToString()
771*d9f75844SAndroid Build Coastguard Worker << ": Received channel data for invalid channel, id="
772*d9f75844SAndroid Build Coastguard Worker << channel_id;
773*d9f75844SAndroid Build Coastguard Worker }
774*d9f75844SAndroid Build Coastguard Worker }
775*d9f75844SAndroid Build Coastguard Worker
OnExternalPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & addr,const int64_t &)776*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::OnExternalPacket(
777*d9f75844SAndroid Build Coastguard Worker rtc::AsyncPacketSocket* socket,
778*d9f75844SAndroid Build Coastguard Worker const char* data,
779*d9f75844SAndroid Build Coastguard Worker size_t size,
780*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& addr,
781*d9f75844SAndroid Build Coastguard Worker const int64_t& /* packet_time_us */) {
782*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(external_socket_.get() == socket);
783*d9f75844SAndroid Build Coastguard Worker auto channel = FindChannel(addr);
784*d9f75844SAndroid Build Coastguard Worker if (channel != channels_.end()) {
785*d9f75844SAndroid Build Coastguard Worker // There is a channel bound to this address. Send as a channel message.
786*d9f75844SAndroid Build Coastguard Worker rtc::ByteBufferWriter buf;
787*d9f75844SAndroid Build Coastguard Worker buf.WriteUInt16(channel->id);
788*d9f75844SAndroid Build Coastguard Worker buf.WriteUInt16(static_cast<uint16_t>(size));
789*d9f75844SAndroid Build Coastguard Worker buf.WriteBytes(data, size);
790*d9f75844SAndroid Build Coastguard Worker server_->Send(&conn_, buf);
791*d9f75844SAndroid Build Coastguard Worker } else if (!server_->enable_permission_checks_ ||
792*d9f75844SAndroid Build Coastguard Worker HasPermission(addr.ipaddr())) {
793*d9f75844SAndroid Build Coastguard Worker // No channel, but a permission exists. Send as a data indication.
794*d9f75844SAndroid Build Coastguard Worker TurnMessage msg(TURN_DATA_INDICATION);
795*d9f75844SAndroid Build Coastguard Worker msg.AddAttribute(std::make_unique<StunXorAddressAttribute>(
796*d9f75844SAndroid Build Coastguard Worker STUN_ATTR_XOR_PEER_ADDRESS, addr));
797*d9f75844SAndroid Build Coastguard Worker msg.AddAttribute(
798*d9f75844SAndroid Build Coastguard Worker std::make_unique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
799*d9f75844SAndroid Build Coastguard Worker server_->SendStun(&conn_, &msg);
800*d9f75844SAndroid Build Coastguard Worker } else {
801*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
802*d9f75844SAndroid Build Coastguard Worker << ToString() << ": Received external packet without permission, peer="
803*d9f75844SAndroid Build Coastguard Worker << addr.ToSensitiveString();
804*d9f75844SAndroid Build Coastguard Worker }
805*d9f75844SAndroid Build Coastguard Worker }
806*d9f75844SAndroid Build Coastguard Worker
ComputeLifetime(const TurnMessage & msg)807*d9f75844SAndroid Build Coastguard Worker TimeDelta TurnServerAllocation::ComputeLifetime(const TurnMessage& msg) {
808*d9f75844SAndroid Build Coastguard Worker if (const StunUInt32Attribute* attr = msg.GetUInt32(STUN_ATTR_LIFETIME)) {
809*d9f75844SAndroid Build Coastguard Worker return std::min(TimeDelta::Seconds(static_cast<int>(attr->value())),
810*d9f75844SAndroid Build Coastguard Worker kDefaultAllocationTimeout);
811*d9f75844SAndroid Build Coastguard Worker }
812*d9f75844SAndroid Build Coastguard Worker return kDefaultAllocationTimeout;
813*d9f75844SAndroid Build Coastguard Worker }
814*d9f75844SAndroid Build Coastguard Worker
HasPermission(const rtc::IPAddress & addr)815*d9f75844SAndroid Build Coastguard Worker bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) {
816*d9f75844SAndroid Build Coastguard Worker return FindPermission(addr) != perms_.end();
817*d9f75844SAndroid Build Coastguard Worker }
818*d9f75844SAndroid Build Coastguard Worker
AddPermission(const rtc::IPAddress & addr)819*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) {
820*d9f75844SAndroid Build Coastguard Worker auto perm = FindPermission(addr);
821*d9f75844SAndroid Build Coastguard Worker if (perm == perms_.end()) {
822*d9f75844SAndroid Build Coastguard Worker perm = perms_.insert(perms_.end(), {.peer = addr});
823*d9f75844SAndroid Build Coastguard Worker } else {
824*d9f75844SAndroid Build Coastguard Worker perm->pending_delete.reset();
825*d9f75844SAndroid Build Coastguard Worker }
826*d9f75844SAndroid Build Coastguard Worker thread_->PostDelayedTask(SafeTask(perm->pending_delete.flag(),
827*d9f75844SAndroid Build Coastguard Worker [this, perm] { perms_.erase(perm); }),
828*d9f75844SAndroid Build Coastguard Worker kPermissionTimeout);
829*d9f75844SAndroid Build Coastguard Worker }
830*d9f75844SAndroid Build Coastguard Worker
831*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation::PermissionList::iterator
FindPermission(const rtc::IPAddress & addr)832*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation::FindPermission(const rtc::IPAddress& addr) {
833*d9f75844SAndroid Build Coastguard Worker return absl::c_find_if(perms_,
834*d9f75844SAndroid Build Coastguard Worker [&](const Permission& p) { return p.peer == addr; });
835*d9f75844SAndroid Build Coastguard Worker }
836*d9f75844SAndroid Build Coastguard Worker
FindChannel(int channel_id)837*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation::ChannelList::iterator TurnServerAllocation::FindChannel(
838*d9f75844SAndroid Build Coastguard Worker int channel_id) {
839*d9f75844SAndroid Build Coastguard Worker return absl::c_find_if(channels_,
840*d9f75844SAndroid Build Coastguard Worker [&](const Channel& c) { return c.id == channel_id; });
841*d9f75844SAndroid Build Coastguard Worker }
842*d9f75844SAndroid Build Coastguard Worker
FindChannel(const rtc::SocketAddress & addr)843*d9f75844SAndroid Build Coastguard Worker TurnServerAllocation::ChannelList::iterator TurnServerAllocation::FindChannel(
844*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& addr) {
845*d9f75844SAndroid Build Coastguard Worker return absl::c_find_if(channels_,
846*d9f75844SAndroid Build Coastguard Worker [&](const Channel& c) { return c.peer == addr; });
847*d9f75844SAndroid Build Coastguard Worker }
848*d9f75844SAndroid Build Coastguard Worker
SendResponse(TurnMessage * msg)849*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::SendResponse(TurnMessage* msg) {
850*d9f75844SAndroid Build Coastguard Worker // Success responses always have M-I.
851*d9f75844SAndroid Build Coastguard Worker msg->AddMessageIntegrity(key_);
852*d9f75844SAndroid Build Coastguard Worker server_->SendStun(&conn_, msg);
853*d9f75844SAndroid Build Coastguard Worker }
854*d9f75844SAndroid Build Coastguard Worker
SendBadRequestResponse(const TurnMessage * req)855*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) {
856*d9f75844SAndroid Build Coastguard Worker SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
857*d9f75844SAndroid Build Coastguard Worker }
858*d9f75844SAndroid Build Coastguard Worker
SendErrorResponse(const TurnMessage * req,int code,absl::string_view reason)859*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::SendErrorResponse(const TurnMessage* req,
860*d9f75844SAndroid Build Coastguard Worker int code,
861*d9f75844SAndroid Build Coastguard Worker absl::string_view reason) {
862*d9f75844SAndroid Build Coastguard Worker server_->SendErrorResponse(&conn_, req, code, reason);
863*d9f75844SAndroid Build Coastguard Worker }
864*d9f75844SAndroid Build Coastguard Worker
SendExternal(const void * data,size_t size,const rtc::SocketAddress & peer)865*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::SendExternal(const void* data,
866*d9f75844SAndroid Build Coastguard Worker size_t size,
867*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& peer) {
868*d9f75844SAndroid Build Coastguard Worker rtc::PacketOptions options;
869*d9f75844SAndroid Build Coastguard Worker external_socket_->SendTo(data, size, peer, options);
870*d9f75844SAndroid Build Coastguard Worker }
871*d9f75844SAndroid Build Coastguard Worker
PostDeleteSelf(TimeDelta delay)872*d9f75844SAndroid Build Coastguard Worker void TurnServerAllocation::PostDeleteSelf(TimeDelta delay) {
873*d9f75844SAndroid Build Coastguard Worker auto delete_self = [this] {
874*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(server_->thread_);
875*d9f75844SAndroid Build Coastguard Worker server_->DestroyAllocation(this);
876*d9f75844SAndroid Build Coastguard Worker };
877*d9f75844SAndroid Build Coastguard Worker thread_->PostDelayedTask(SafeTask(safety_.flag(), std::move(delete_self)),
878*d9f75844SAndroid Build Coastguard Worker delay);
879*d9f75844SAndroid Build Coastguard Worker }
880*d9f75844SAndroid Build Coastguard Worker
881*d9f75844SAndroid Build Coastguard Worker } // namespace cricket
882