blob: 902e889057b501df13860161bdc0a4b6ddd23dea [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "p2p/base/turnserver.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000012
Taylor Brandstetter734262c2016-08-01 16:37:14 -070013#include <tuple> // for std::tie
Steve Anton6c38cc72017-11-29 10:25:58 -080014#include <utility>
Taylor Brandstetter734262c2016-08-01 16:37:14 -070015
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "p2p/base/asyncstuntcpsocket.h"
17#include "p2p/base/common.h"
18#include "p2p/base/packetsocketfactory.h"
19#include "p2p/base/stun.h"
20#include "rtc_base/bind.h"
21#include "rtc_base/bytebuffer.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/helpers.h"
24#include "rtc_base/logging.h"
25#include "rtc_base/messagedigest.h"
26#include "rtc_base/ptr_util.h"
27#include "rtc_base/socketadapters.h"
28#include "rtc_base/stringencode.h"
29#include "rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000030
31namespace cricket {
32
33// TODO(juberti): Move this all to a future turnmessage.h
Steve Anton6c38cc72017-11-29 10:25:58 -080034// static const int IPPROTO_UDP = 17;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000035static const int kNonceTimeout = 60 * 60 * 1000; // 60 minutes
36static const int kDefaultAllocationTimeout = 10 * 60 * 1000; // 10 minutes
37static const int kPermissionTimeout = 5 * 60 * 1000; // 5 minutes
38static const int kChannelTimeout = 10 * 60 * 1000; // 10 minutes
39
40static const int kMinChannelNumber = 0x4000;
41static const int kMaxChannelNumber = 0x7FFF;
42
43static const size_t kNonceKeySize = 16;
honghaiz34b11eb2016-03-16 08:55:44 -070044static const size_t kNonceSize = 48;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000045
46static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
47
48// TODO(mallinath) - Move these to a common place.
Peter Boström0c4e06b2015-10-07 12:23:21 +020049inline bool IsTurnChannelData(uint16_t msg_type) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 // The first two bits of a channel data message are 0b01.
51 return ((msg_type & 0xC000) == 0x4000);
52}
53
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000054// IDs used for posted messages for TurnServerAllocation.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000055enum {
56 MSG_ALLOCATION_TIMEOUT,
57};
58
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000059// Encapsulates a TURN permission.
60// The object is created when a create permission request is received by an
61// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000062class TurnServerAllocation::Permission : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000063 public:
64 Permission(rtc::Thread* thread, const rtc::IPAddress& peer);
Steve Antonf2737d22017-10-31 16:27:34 -070065 ~Permission() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066
67 const rtc::IPAddress& peer() const { return peer_; }
68 void Refresh();
69
70 sigslot::signal1<Permission*> SignalDestroyed;
71
72 private:
Steve Antonf2737d22017-10-31 16:27:34 -070073 void OnMessage(rtc::Message* msg) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000074
75 rtc::Thread* thread_;
76 rtc::IPAddress peer_;
77};
78
79// Encapsulates a TURN channel binding.
80// The object is created when a channel bind request is received by an
81// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000082class TurnServerAllocation::Channel : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083 public:
84 Channel(rtc::Thread* thread, int id,
85 const rtc::SocketAddress& peer);
Steve Antonf2737d22017-10-31 16:27:34 -070086 ~Channel() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000087
88 int id() const { return id_; }
89 const rtc::SocketAddress& peer() const { return peer_; }
90 void Refresh();
91
92 sigslot::signal1<Channel*> SignalDestroyed;
93
94 private:
Steve Antonf2737d22017-10-31 16:27:34 -070095 void OnMessage(rtc::Message* msg) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000096
97 rtc::Thread* thread_;
98 int id_;
99 rtc::SocketAddress peer_;
100};
101
102static bool InitResponse(const StunMessage* req, StunMessage* resp) {
103 int resp_type = (req) ? GetStunSuccessResponseType(req->type()) : -1;
104 if (resp_type == -1)
105 return false;
106 resp->SetType(resp_type);
107 resp->SetTransactionID(req->transaction_id());
108 return true;
109}
110
111static bool InitErrorResponse(const StunMessage* req, int code,
112 const std::string& reason, StunMessage* resp) {
113 int resp_type = (req) ? GetStunErrorResponseType(req->type()) : -1;
114 if (resp_type == -1)
115 return false;
116 resp->SetType(resp_type);
117 resp->SetTransactionID(req->transaction_id());
zsteinf42cc9d2017-03-27 16:17:19 -0700118 resp->AddAttribute(rtc::MakeUnique<cricket::StunErrorCodeAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800119 STUN_ATTR_ERROR_CODE, code, reason));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000120 return true;
121}
122
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000123
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000124TurnServer::TurnServer(rtc::Thread* thread)
125 : thread_(thread),
126 nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
127 auth_hook_(NULL),
128 redirect_hook_(NULL),
129 enable_otu_nonce_(false) {
130}
131
132TurnServer::~TurnServer() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000133 for (InternalSocketMap::iterator it = server_sockets_.begin();
134 it != server_sockets_.end(); ++it) {
135 rtc::AsyncPacketSocket* socket = it->first;
136 delete socket;
137 }
138
139 for (ServerSocketMap::iterator it = server_listen_sockets_.begin();
140 it != server_listen_sockets_.end(); ++it) {
141 rtc::AsyncSocket* socket = it->first;
142 delete socket;
143 }
144}
145
146void TurnServer::AddInternalSocket(rtc::AsyncPacketSocket* socket,
147 ProtocolType proto) {
nisseede5da42017-01-12 05:15:36 -0800148 RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000149 server_sockets_[socket] = proto;
150 socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket);
151}
152
153void TurnServer::AddInternalServerSocket(rtc::AsyncSocket* socket,
154 ProtocolType proto) {
nisseede5da42017-01-12 05:15:36 -0800155 RTC_DCHECK(server_listen_sockets_.end() ==
156 server_listen_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000157 server_listen_sockets_[socket] = proto;
158 socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection);
159}
160
161void TurnServer::SetExternalSocketFactory(
162 rtc::PacketSocketFactory* factory,
163 const rtc::SocketAddress& external_addr) {
164 external_socket_factory_.reset(factory);
165 external_addr_ = external_addr;
166}
167
168void TurnServer::OnNewInternalConnection(rtc::AsyncSocket* socket) {
nisseede5da42017-01-12 05:15:36 -0800169 RTC_DCHECK(server_listen_sockets_.find(socket) !=
170 server_listen_sockets_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000171 AcceptConnection(socket);
172}
173
174void TurnServer::AcceptConnection(rtc::AsyncSocket* server_socket) {
175 // Check if someone is trying to connect to us.
176 rtc::SocketAddress accept_addr;
177 rtc::AsyncSocket* accepted_socket = server_socket->Accept(&accept_addr);
178 if (accepted_socket != NULL) {
179 ProtocolType proto = server_listen_sockets_[server_socket];
180 cricket::AsyncStunTCPSocket* tcp_socket =
181 new cricket::AsyncStunTCPSocket(accepted_socket, false);
182
183 tcp_socket->SignalClose.connect(this, &TurnServer::OnInternalSocketClose);
184 // Finally add the socket so it can start communicating with the client.
185 AddInternalSocket(tcp_socket, proto);
186 }
187}
188
189void TurnServer::OnInternalSocketClose(rtc::AsyncPacketSocket* socket,
190 int err) {
191 DestroyInternalSocket(socket);
192}
193
194void TurnServer::OnInternalPacket(rtc::AsyncPacketSocket* socket,
195 const char* data, size_t size,
196 const rtc::SocketAddress& addr,
197 const rtc::PacketTime& packet_time) {
198 // Fail if the packet is too small to even contain a channel header.
199 if (size < TURN_CHANNEL_HEADER_SIZE) {
Steve Anton6c38cc72017-11-29 10:25:58 -0800200 return;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000201 }
202 InternalSocketMap::iterator iter = server_sockets_.find(socket);
nisseede5da42017-01-12 05:15:36 -0800203 RTC_DCHECK(iter != server_sockets_.end());
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000204 TurnServerConnection conn(addr, iter->second, socket);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200205 uint16_t msg_type = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000206 if (!IsTurnChannelData(msg_type)) {
207 // This is a STUN message.
208 HandleStunMessage(&conn, data, size);
209 } else {
210 // This is a channel message; let the allocation handle it.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000211 TurnServerAllocation* allocation = FindAllocation(&conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000212 if (allocation) {
213 allocation->HandleChannelData(data, size);
214 }
Jonas Orelandbdcee282017-10-10 14:01:40 +0200215 if (stun_message_observer_ != nullptr) {
216 stun_message_observer_->ReceivedChannelData(data, size);
217 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000218 }
219}
220
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000221void TurnServer::HandleStunMessage(TurnServerConnection* conn, const char* data,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000222 size_t size) {
223 TurnMessage msg;
jbauchf1f87202016-03-30 06:43:37 -0700224 rtc::ByteBufferReader buf(data, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000225 if (!msg.Read(&buf) || (buf.Length() > 0)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100226 RTC_LOG(LS_WARNING) << "Received invalid STUN message";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000227 return;
228 }
229
Jonas Orelandbdcee282017-10-10 14:01:40 +0200230 if (stun_message_observer_ != nullptr) {
231 stun_message_observer_->ReceivedMessage(&msg);
232 }
233
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000234 // If it's a STUN binding request, handle that specially.
235 if (msg.type() == STUN_BINDING_REQUEST) {
236 HandleBindingRequest(conn, &msg);
237 return;
238 }
239
240 if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
241 rtc::SocketAddress address;
242 if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
243 SendErrorResponseWithAlternateServer(
244 conn, &msg, address);
245 return;
246 }
247 }
248
249 // Look up the key that we'll use to validate the M-I. If we have an
250 // existing allocation, the key will already be cached.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000251 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000252 std::string key;
253 if (!allocation) {
254 GetKey(&msg, &key);
255 } else {
256 key = allocation->key();
257 }
258
259 // Ensure the message is authorized; only needed for requests.
260 if (IsStunRequestType(msg.type())) {
261 if (!CheckAuthorization(conn, &msg, data, size, key)) {
262 return;
263 }
264 }
265
266 if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
267 HandleAllocateRequest(conn, &msg, key);
268 } else if (allocation &&
269 (msg.type() != STUN_ALLOCATE_REQUEST ||
270 msg.transaction_id() == allocation->transaction_id())) {
271 // This is a non-allocate request, or a retransmit of an allocate.
272 // Check that the username matches the previous username used.
273 if (IsStunRequestType(msg.type()) &&
274 msg.GetByteString(STUN_ATTR_USERNAME)->GetString() !=
275 allocation->username()) {
276 SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
277 STUN_ERROR_REASON_WRONG_CREDENTIALS);
278 return;
279 }
280 allocation->HandleTurnMessage(&msg);
281 } else {
282 // Allocation mismatch.
283 SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH,
284 STUN_ERROR_REASON_ALLOCATION_MISMATCH);
285 }
286}
287
288bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
289 const StunByteStringAttribute* username_attr =
290 msg->GetByteString(STUN_ATTR_USERNAME);
291 if (!username_attr) {
292 return false;
293 }
294
295 std::string username = username_attr->GetString();
296 return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key));
297}
298
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000299bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000300 const StunMessage* msg,
301 const char* data, size_t size,
302 const std::string& key) {
303 // RFC 5389, 10.2.2.
nisseede5da42017-01-12 05:15:36 -0800304 RTC_DCHECK(IsStunRequestType(msg->type()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000305 const StunByteStringAttribute* mi_attr =
306 msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
307 const StunByteStringAttribute* username_attr =
308 msg->GetByteString(STUN_ATTR_USERNAME);
309 const StunByteStringAttribute* realm_attr =
310 msg->GetByteString(STUN_ATTR_REALM);
311 const StunByteStringAttribute* nonce_attr =
312 msg->GetByteString(STUN_ATTR_NONCE);
313
314 // Fail if no M-I.
315 if (!mi_attr) {
316 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
317 STUN_ERROR_REASON_UNAUTHORIZED);
318 return false;
319 }
320
321 // Fail if there is M-I but no username, nonce, or realm.
322 if (!username_attr || !realm_attr || !nonce_attr) {
323 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
324 STUN_ERROR_REASON_BAD_REQUEST);
325 return false;
326 }
327
328 // Fail if bad nonce.
329 if (!ValidateNonce(nonce_attr->GetString())) {
330 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
331 STUN_ERROR_REASON_STALE_NONCE);
332 return false;
333 }
334
335 // Fail if bad username or M-I.
336 // We need |data| and |size| for the call to ValidateMessageIntegrity.
337 if (key.empty() || !StunMessage::ValidateMessageIntegrity(data, size, key)) {
338 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
339 STUN_ERROR_REASON_UNAUTHORIZED);
340 return false;
341 }
342
343 // Fail if one-time-use nonce feature is enabled.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000344 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000345 if (enable_otu_nonce_ && allocation &&
346 allocation->last_nonce() == nonce_attr->GetString()) {
347 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
348 STUN_ERROR_REASON_STALE_NONCE);
349 return false;
350 }
351
352 if (allocation) {
353 allocation->set_last_nonce(nonce_attr->GetString());
354 }
355 // Success.
356 return true;
357}
358
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000359void TurnServer::HandleBindingRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000360 const StunMessage* req) {
361 StunMessage response;
362 InitResponse(req, &response);
363
364 // Tell the user the address that we received their request from.
zsteinf42cc9d2017-03-27 16:17:19 -0700365 auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000366 STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
zsteinf42cc9d2017-03-27 16:17:19 -0700367 response.AddAttribute(std::move(mapped_addr_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000368
369 SendStun(conn, &response);
370}
371
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000372void TurnServer::HandleAllocateRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000373 const TurnMessage* msg,
374 const std::string& key) {
375 // Check the parameters in the request.
376 const StunUInt32Attribute* transport_attr =
377 msg->GetUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
378 if (!transport_attr) {
379 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
380 STUN_ERROR_REASON_BAD_REQUEST);
381 return;
382 }
383
384 // Only UDP is supported right now.
385 int proto = transport_attr->value() >> 24;
386 if (proto != IPPROTO_UDP) {
387 SendErrorResponse(conn, msg, STUN_ERROR_UNSUPPORTED_PROTOCOL,
388 STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL);
389 return;
390 }
391
392 // Create the allocation and let it send the success response.
393 // If the actual socket allocation fails, send an internal error.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000394 TurnServerAllocation* alloc = CreateAllocation(conn, proto, key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000395 if (alloc) {
396 alloc->HandleTurnMessage(msg);
397 } else {
398 SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR,
399 "Failed to allocate socket");
400 }
401}
402
honghaiz34b11eb2016-03-16 08:55:44 -0700403std::string TurnServer::GenerateNonce(int64_t now) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000404 // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000405 std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
406 std::string nonce = rtc::hex_encode(input.c_str(), input.size());
407 nonce += rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, input);
nisseede5da42017-01-12 05:15:36 -0800408 RTC_DCHECK(nonce.size() == kNonceSize);
honghaiz34b11eb2016-03-16 08:55:44 -0700409
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000410 return nonce;
411}
412
413bool TurnServer::ValidateNonce(const std::string& nonce) const {
414 // Check the size.
415 if (nonce.size() != kNonceSize) {
416 return false;
417 }
418
419 // Decode the timestamp.
honghaiz34b11eb2016-03-16 08:55:44 -0700420 int64_t then;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000421 char* p = reinterpret_cast<char*>(&then);
422 size_t len = rtc::hex_decode(p, sizeof(then),
423 nonce.substr(0, sizeof(then) * 2));
424 if (len != sizeof(then)) {
425 return false;
426 }
427
428 // Verify the HMAC.
429 if (nonce.substr(sizeof(then) * 2) != rtc::ComputeHmac(
430 rtc::DIGEST_MD5, nonce_key_, std::string(p, sizeof(then)))) {
431 return false;
432 }
433
434 // Validate the timestamp.
nisse1bffc1d2016-05-02 08:18:55 -0700435 return rtc::TimeMillis() - then < kNonceTimeout;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000436}
437
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000438TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000439 AllocationMap::const_iterator it = allocations_.find(*conn);
deadbeef97943662016-07-12 11:04:50 -0700440 return (it != allocations_.end()) ? it->second.get() : nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000441}
442
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000443TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn,
444 int proto,
445 const std::string& key) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000446 rtc::AsyncPacketSocket* external_socket = (external_socket_factory_) ?
447 external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) : NULL;
448 if (!external_socket) {
449 return NULL;
450 }
451
452 // The Allocation takes ownership of the socket.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000453 TurnServerAllocation* allocation = new TurnServerAllocation(this,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000454 thread_, *conn, external_socket, key);
455 allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed);
deadbeef97943662016-07-12 11:04:50 -0700456 allocations_[*conn].reset(allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000457 return allocation;
458}
459
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000460void TurnServer::SendErrorResponse(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000461 const StunMessage* req,
462 int code, const std::string& reason) {
463 TurnMessage resp;
464 InitErrorResponse(req, code, reason, &resp);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100465 RTC_LOG(LS_INFO) << "Sending error response, type=" << resp.type()
466 << ", code=" << code << ", reason=" << reason;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000467 SendStun(conn, &resp);
468}
469
470void TurnServer::SendErrorResponseWithRealmAndNonce(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000471 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000472 int code, const std::string& reason) {
473 TurnMessage resp;
474 InitErrorResponse(msg, code, reason, &resp);
honghaizc463e202016-02-01 15:19:08 -0800475
nisse1bffc1d2016-05-02 08:18:55 -0700476 int64_t timestamp = rtc::TimeMillis();
honghaizc463e202016-02-01 15:19:08 -0800477 if (ts_for_next_nonce_) {
478 timestamp = ts_for_next_nonce_;
479 ts_for_next_nonce_ = 0;
480 }
zsteinf42cc9d2017-03-27 16:17:19 -0700481 resp.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
482 STUN_ATTR_NONCE, GenerateNonce(timestamp)));
nissecc99bc22017-02-02 01:31:30 -0800483 resp.AddAttribute(
zsteinf42cc9d2017-03-27 16:17:19 -0700484 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000485 SendStun(conn, &resp);
486}
487
488void TurnServer::SendErrorResponseWithAlternateServer(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000489 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000490 const rtc::SocketAddress& addr) {
491 TurnMessage resp;
492 InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
493 STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
zsteinf42cc9d2017-03-27 16:17:19 -0700494 resp.AddAttribute(
495 rtc::MakeUnique<StunAddressAttribute>(STUN_ATTR_ALTERNATE_SERVER, addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000496 SendStun(conn, &resp);
497}
498
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000499void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
jbauchf1f87202016-03-30 06:43:37 -0700500 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000501 // Add a SOFTWARE attribute if one is set.
502 if (!software_.empty()) {
zsteinf42cc9d2017-03-27 16:17:19 -0700503 msg->AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
504 STUN_ATTR_SOFTWARE, software_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000505 }
506 msg->Write(&buf);
507 Send(conn, buf);
508}
509
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000510void TurnServer::Send(TurnServerConnection* conn,
jbauchf1f87202016-03-30 06:43:37 -0700511 const rtc::ByteBufferWriter& buf) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000512 rtc::PacketOptions options;
513 conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
514}
515
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000516void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000517 // Removing the internal socket if the connection is not udp.
518 rtc::AsyncPacketSocket* socket = allocation->conn()->socket();
519 InternalSocketMap::iterator iter = server_sockets_.find(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000520 // Skip if the socket serving this allocation is UDP, as this will be shared
521 // by all allocations.
Taylor Brandstetter716d07a2016-06-27 14:07:41 -0700522 // Note: We may not find a socket if it's a TCP socket that was closed, and
523 // the allocation is only now timing out.
524 if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000525 DestroyInternalSocket(socket);
526 }
527
528 AllocationMap::iterator it = allocations_.find(*(allocation->conn()));
deadbeef97943662016-07-12 11:04:50 -0700529 if (it != allocations_.end()) {
530 it->second.release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000531 allocations_.erase(it);
deadbeef97943662016-07-12 11:04:50 -0700532 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000533}
534
535void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
536 InternalSocketMap::iterator iter = server_sockets_.find(socket);
537 if (iter != server_sockets_.end()) {
538 rtc::AsyncPacketSocket* socket = iter->first;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000539 server_sockets_.erase(iter);
deadbeef824f5862016-08-24 15:06:53 -0700540 // We must destroy the socket async to avoid invalidating the sigslot
541 // callback list iterator inside a sigslot callback. (In other words,
542 // deleting an object from within a callback from that object).
543 sockets_to_delete_.push_back(
544 std::unique_ptr<rtc::AsyncPacketSocket>(socket));
545 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, rtc::Thread::Current(),
546 rtc::Bind(&TurnServer::FreeSockets, this));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000547 }
548}
549
deadbeef824f5862016-08-24 15:06:53 -0700550void TurnServer::FreeSockets() {
551 sockets_to_delete_.clear();
552}
553
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000554TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src,
555 ProtocolType proto,
556 rtc::AsyncPacketSocket* socket)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000557 : src_(src),
558 dst_(socket->GetRemoteAddress()),
559 proto_(proto),
560 socket_(socket) {
561}
562
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000563bool TurnServerConnection::operator==(const TurnServerConnection& c) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000564 return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
565}
566
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000567bool TurnServerConnection::operator<(const TurnServerConnection& c) const {
Taylor Brandstetter734262c2016-08-01 16:37:14 -0700568 return std::tie(src_, dst_, proto_) < std::tie(c.src_, c.dst_, c.proto_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000569}
570
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000571std::string TurnServerConnection::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000572 const char* const kProtos[] = {
573 "unknown", "udp", "tcp", "ssltcp"
574 };
575 std::ostringstream ost;
576 ost << src_.ToString() << "-" << dst_.ToString() << ":"<< kProtos[proto_];
577 return ost.str();
578}
579
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000580TurnServerAllocation::TurnServerAllocation(TurnServer* server,
581 rtc::Thread* thread,
582 const TurnServerConnection& conn,
583 rtc::AsyncPacketSocket* socket,
584 const std::string& key)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000585 : server_(server),
586 thread_(thread),
587 conn_(conn),
588 external_socket_(socket),
589 key_(key) {
590 external_socket_->SignalReadPacket.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000591 this, &TurnServerAllocation::OnExternalPacket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000592}
593
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000594TurnServerAllocation::~TurnServerAllocation() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000595 for (ChannelList::iterator it = channels_.begin();
596 it != channels_.end(); ++it) {
597 delete *it;
598 }
599 for (PermissionList::iterator it = perms_.begin();
600 it != perms_.end(); ++it) {
601 delete *it;
602 }
603 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
604 LOG_J(LS_INFO, this) << "Allocation destroyed";
605}
606
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000607std::string TurnServerAllocation::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000608 std::ostringstream ost;
609 ost << "Alloc[" << conn_.ToString() << "]";
610 return ost.str();
611}
612
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000613void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) {
nisseede5da42017-01-12 05:15:36 -0800614 RTC_DCHECK(msg != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000615 switch (msg->type()) {
616 case STUN_ALLOCATE_REQUEST:
617 HandleAllocateRequest(msg);
618 break;
619 case TURN_REFRESH_REQUEST:
620 HandleRefreshRequest(msg);
621 break;
622 case TURN_SEND_INDICATION:
623 HandleSendIndication(msg);
624 break;
625 case TURN_CREATE_PERMISSION_REQUEST:
626 HandleCreatePermissionRequest(msg);
627 break;
628 case TURN_CHANNEL_BIND_REQUEST:
629 HandleChannelBindRequest(msg);
630 break;
631 default:
632 // Not sure what to do with this, just eat it.
633 LOG_J(LS_WARNING, this) << "Invalid TURN message type received: "
634 << msg->type();
635 }
636}
637
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000638void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000639 // Copy the important info from the allocate request.
640 transaction_id_ = msg->transaction_id();
641 const StunByteStringAttribute* username_attr =
642 msg->GetByteString(STUN_ATTR_USERNAME);
nisseede5da42017-01-12 05:15:36 -0800643 RTC_DCHECK(username_attr != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000644 username_ = username_attr->GetString();
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000645 const StunByteStringAttribute* origin_attr =
646 msg->GetByteString(STUN_ATTR_ORIGIN);
647 if (origin_attr) {
648 origin_ = origin_attr->GetString();
649 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000650
651 // Figure out the lifetime and start the allocation timer.
652 int lifetime_secs = ComputeLifetime(msg);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700653 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
654 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000655
656 LOG_J(LS_INFO, this) << "Created allocation, lifetime=" << lifetime_secs;
657
658 // We've already validated all the important bits; just send a response here.
659 TurnMessage response;
660 InitResponse(msg, &response);
661
zsteinf42cc9d2017-03-27 16:17:19 -0700662 auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
663 STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
664 auto relayed_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
665 STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress());
666 auto lifetime_attr =
667 rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
668 response.AddAttribute(std::move(mapped_addr_attr));
669 response.AddAttribute(std::move(relayed_addr_attr));
670 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000671
672 SendResponse(&response);
673}
674
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000675void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000676 // Figure out the new lifetime.
677 int lifetime_secs = ComputeLifetime(msg);
678
679 // Reset the expiration timer.
680 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700681 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
682 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000683
684 LOG_J(LS_INFO, this) << "Refreshed allocation, lifetime=" << lifetime_secs;
685
686 // Send a success response with a LIFETIME attribute.
687 TurnMessage response;
688 InitResponse(msg, &response);
689
zsteinf42cc9d2017-03-27 16:17:19 -0700690 auto lifetime_attr =
691 rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
692 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000693
694 SendResponse(&response);
695}
696
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000697void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000698 // Check mandatory attributes.
699 const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
700 const StunAddressAttribute* peer_attr =
701 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
702 if (!data_attr || !peer_attr) {
703 LOG_J(LS_WARNING, this) << "Received invalid send indication";
704 return;
705 }
706
707 // If a permission exists, send the data on to the peer.
708 if (HasPermission(peer_attr->GetAddress().ipaddr())) {
709 SendExternal(data_attr->bytes(), data_attr->length(),
710 peer_attr->GetAddress());
711 } else {
712 LOG_J(LS_WARNING, this) << "Received send indication without permission"
713 << "peer=" << peer_attr->GetAddress();
714 }
715}
716
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000717void TurnServerAllocation::HandleCreatePermissionRequest(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000718 const TurnMessage* msg) {
719 // Check mandatory attributes.
720 const StunAddressAttribute* peer_attr =
721 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
722 if (!peer_attr) {
723 SendBadRequestResponse(msg);
724 return;
725 }
726
deadbeef376e1232015-11-25 09:00:08 -0800727 if (server_->reject_private_addresses_ &&
728 rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) {
729 SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN);
730 return;
731 }
732
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000733 // Add this permission.
734 AddPermission(peer_attr->GetAddress().ipaddr());
735
736 LOG_J(LS_INFO, this) << "Created permission, peer="
737 << peer_attr->GetAddress();
738
739 // Send a success response.
740 TurnMessage response;
741 InitResponse(msg, &response);
742 SendResponse(&response);
743}
744
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000745void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000746 // Check mandatory attributes.
747 const StunUInt32Attribute* channel_attr =
748 msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
749 const StunAddressAttribute* peer_attr =
750 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
751 if (!channel_attr || !peer_attr) {
752 SendBadRequestResponse(msg);
753 return;
754 }
755
756 // Check that channel id is valid.
757 int channel_id = channel_attr->value() >> 16;
758 if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) {
759 SendBadRequestResponse(msg);
760 return;
761 }
762
763 // Check that this channel id isn't bound to another transport address, and
764 // that this transport address isn't bound to another channel id.
765 Channel* channel1 = FindChannel(channel_id);
766 Channel* channel2 = FindChannel(peer_attr->GetAddress());
767 if (channel1 != channel2) {
768 SendBadRequestResponse(msg);
769 return;
770 }
771
772 // Add or refresh this channel.
773 if (!channel1) {
774 channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress());
775 channel1->SignalDestroyed.connect(this,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000776 &TurnServerAllocation::OnChannelDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000777 channels_.push_back(channel1);
778 } else {
779 channel1->Refresh();
780 }
781
782 // Channel binds also refresh permissions.
783 AddPermission(peer_attr->GetAddress().ipaddr());
784
785 LOG_J(LS_INFO, this) << "Bound channel, id=" << channel_id
786 << ", peer=" << peer_attr->GetAddress();
787
788 // Send a success response.
789 TurnMessage response;
790 InitResponse(msg, &response);
791 SendResponse(&response);
792}
793
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000794void TurnServerAllocation::HandleChannelData(const char* data, size_t size) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000795 // Extract the channel number from the data.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200796 uint16_t channel_id = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000797 Channel* channel = FindChannel(channel_id);
798 if (channel) {
799 // Send the data to the peer address.
800 SendExternal(data + TURN_CHANNEL_HEADER_SIZE,
801 size - TURN_CHANNEL_HEADER_SIZE, channel->peer());
802 } else {
803 LOG_J(LS_WARNING, this) << "Received channel data for invalid channel, id="
804 << channel_id;
805 }
806}
807
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000808void TurnServerAllocation::OnExternalPacket(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000809 rtc::AsyncPacketSocket* socket,
810 const char* data, size_t size,
811 const rtc::SocketAddress& addr,
812 const rtc::PacketTime& packet_time) {
nisseede5da42017-01-12 05:15:36 -0800813 RTC_DCHECK(external_socket_.get() == socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000814 Channel* channel = FindChannel(addr);
815 if (channel) {
816 // There is a channel bound to this address. Send as a channel message.
jbauchf1f87202016-03-30 06:43:37 -0700817 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000818 buf.WriteUInt16(channel->id());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200819 buf.WriteUInt16(static_cast<uint16_t>(size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000820 buf.WriteBytes(data, size);
821 server_->Send(&conn_, buf);
Taylor Brandstetteref184702016-06-23 17:35:47 -0700822 } else if (!server_->enable_permission_checks_ ||
823 HasPermission(addr.ipaddr())) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000824 // No channel, but a permission exists. Send as a data indication.
825 TurnMessage msg;
826 msg.SetType(TURN_DATA_INDICATION);
827 msg.SetTransactionID(
828 rtc::CreateRandomString(kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -0700829 msg.AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800830 STUN_ATTR_XOR_PEER_ADDRESS, addr));
zsteinf42cc9d2017-03-27 16:17:19 -0700831 msg.AddAttribute(
832 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000833 server_->SendStun(&conn_, &msg);
834 } else {
835 LOG_J(LS_WARNING, this) << "Received external packet without permission, "
836 << "peer=" << addr;
837 }
838}
839
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000840int TurnServerAllocation::ComputeLifetime(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000841 // Return the smaller of our default lifetime and the requested lifetime.
honghaiz34b11eb2016-03-16 08:55:44 -0700842 int lifetime = kDefaultAllocationTimeout / 1000; // convert to seconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000843 const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME);
honghaiz34b11eb2016-03-16 08:55:44 -0700844 if (lifetime_attr && static_cast<int>(lifetime_attr->value()) < lifetime) {
845 lifetime = static_cast<int>(lifetime_attr->value());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000846 }
847 return lifetime;
848}
849
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000850bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000851 return (FindPermission(addr) != NULL);
852}
853
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000854void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000855 Permission* perm = FindPermission(addr);
856 if (!perm) {
857 perm = new Permission(thread_, addr);
858 perm->SignalDestroyed.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000859 this, &TurnServerAllocation::OnPermissionDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000860 perms_.push_back(perm);
861 } else {
862 perm->Refresh();
863 }
864}
865
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000866TurnServerAllocation::Permission* TurnServerAllocation::FindPermission(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000867 const rtc::IPAddress& addr) const {
868 for (PermissionList::const_iterator it = perms_.begin();
869 it != perms_.end(); ++it) {
870 if ((*it)->peer() == addr)
871 return *it;
872 }
873 return NULL;
874}
875
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000876TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
877 int channel_id) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000878 for (ChannelList::const_iterator it = channels_.begin();
879 it != channels_.end(); ++it) {
880 if ((*it)->id() == channel_id)
881 return *it;
882 }
883 return NULL;
884}
885
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000886TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000887 const rtc::SocketAddress& addr) const {
888 for (ChannelList::const_iterator it = channels_.begin();
889 it != channels_.end(); ++it) {
890 if ((*it)->peer() == addr)
891 return *it;
892 }
893 return NULL;
894}
895
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000896void TurnServerAllocation::SendResponse(TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000897 // Success responses always have M-I.
898 msg->AddMessageIntegrity(key_);
899 server_->SendStun(&conn_, msg);
900}
901
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000902void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000903 SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
904}
905
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000906void TurnServerAllocation::SendErrorResponse(const TurnMessage* req, int code,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000907 const std::string& reason) {
908 server_->SendErrorResponse(&conn_, req, code, reason);
909}
910
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000911void TurnServerAllocation::SendExternal(const void* data, size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000912 const rtc::SocketAddress& peer) {
913 rtc::PacketOptions options;
914 external_socket_->SendTo(data, size, peer, options);
915}
916
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000917void TurnServerAllocation::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800918 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000919 SignalDestroyed(this);
920 delete this;
921}
922
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000923void TurnServerAllocation::OnPermissionDestroyed(Permission* perm) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000924 PermissionList::iterator it = std::find(perms_.begin(), perms_.end(), perm);
nisseede5da42017-01-12 05:15:36 -0800925 RTC_DCHECK(it != perms_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000926 perms_.erase(it);
927}
928
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000929void TurnServerAllocation::OnChannelDestroyed(Channel* channel) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000930 ChannelList::iterator it =
931 std::find(channels_.begin(), channels_.end(), channel);
nisseede5da42017-01-12 05:15:36 -0800932 RTC_DCHECK(it != channels_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000933 channels_.erase(it);
934}
935
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000936TurnServerAllocation::Permission::Permission(rtc::Thread* thread,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000937 const rtc::IPAddress& peer)
938 : thread_(thread), peer_(peer) {
939 Refresh();
940}
941
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000942TurnServerAllocation::Permission::~Permission() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000943 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
944}
945
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000946void TurnServerAllocation::Permission::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000947 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700948 thread_->PostDelayed(RTC_FROM_HERE, kPermissionTimeout, this,
949 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000950}
951
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000952void TurnServerAllocation::Permission::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800953 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000954 SignalDestroyed(this);
955 delete this;
956}
957
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000958TurnServerAllocation::Channel::Channel(rtc::Thread* thread, int id,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000959 const rtc::SocketAddress& peer)
960 : thread_(thread), id_(id), peer_(peer) {
961 Refresh();
962}
963
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000964TurnServerAllocation::Channel::~Channel() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000965 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
966}
967
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000968void TurnServerAllocation::Channel::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000969 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700970 thread_->PostDelayed(RTC_FROM_HERE, kChannelTimeout, this,
971 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000972}
973
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000974void TurnServerAllocation::Channel::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800975 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000976 SignalDestroyed(this);
977 delete this;
978}
979
980} // namespace cricket