blob: 0f7d81551d3746e3b8c10b4c480a405293da12bd [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
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "p2p/base/asyncstuntcpsocket.h"
16#include "p2p/base/common.h"
17#include "p2p/base/packetsocketfactory.h"
18#include "p2p/base/stun.h"
19#include "rtc_base/bind.h"
20#include "rtc_base/bytebuffer.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/helpers.h"
23#include "rtc_base/logging.h"
24#include "rtc_base/messagedigest.h"
25#include "rtc_base/ptr_util.h"
26#include "rtc_base/socketadapters.h"
27#include "rtc_base/stringencode.h"
28#include "rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000029
30namespace cricket {
31
32// TODO(juberti): Move this all to a future turnmessage.h
33//static const int IPPROTO_UDP = 17;
34static const int kNonceTimeout = 60 * 60 * 1000; // 60 minutes
35static const int kDefaultAllocationTimeout = 10 * 60 * 1000; // 10 minutes
36static const int kPermissionTimeout = 5 * 60 * 1000; // 5 minutes
37static const int kChannelTimeout = 10 * 60 * 1000; // 10 minutes
38
39static const int kMinChannelNumber = 0x4000;
40static const int kMaxChannelNumber = 0x7FFF;
41
42static const size_t kNonceKeySize = 16;
honghaiz34b11eb2016-03-16 08:55:44 -070043static const size_t kNonceSize = 48;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000044
45static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
46
47// TODO(mallinath) - Move these to a common place.
Peter Boström0c4e06b2015-10-07 12:23:21 +020048inline bool IsTurnChannelData(uint16_t msg_type) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000049 // The first two bits of a channel data message are 0b01.
50 return ((msg_type & 0xC000) == 0x4000);
51}
52
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000053// IDs used for posted messages for TurnServerAllocation.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000054enum {
55 MSG_ALLOCATION_TIMEOUT,
56};
57
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000058// Encapsulates a TURN permission.
59// The object is created when a create permission request is received by an
60// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000061class TurnServerAllocation::Permission : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000062 public:
63 Permission(rtc::Thread* thread, const rtc::IPAddress& peer);
64 ~Permission();
65
66 const rtc::IPAddress& peer() const { return peer_; }
67 void Refresh();
68
69 sigslot::signal1<Permission*> SignalDestroyed;
70
71 private:
72 virtual void OnMessage(rtc::Message* msg);
73
74 rtc::Thread* thread_;
75 rtc::IPAddress peer_;
76};
77
78// Encapsulates a TURN channel binding.
79// The object is created when a channel bind request is received by an
80// allocation, and self-deletes when its lifetime timer expires.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000081class TurnServerAllocation::Channel : public rtc::MessageHandler {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000082 public:
83 Channel(rtc::Thread* thread, int id,
84 const rtc::SocketAddress& peer);
85 ~Channel();
86
87 int id() const { return id_; }
88 const rtc::SocketAddress& peer() const { return peer_; }
89 void Refresh();
90
91 sigslot::signal1<Channel*> SignalDestroyed;
92
93 private:
94 virtual void OnMessage(rtc::Message* msg);
95
96 rtc::Thread* thread_;
97 int id_;
98 rtc::SocketAddress peer_;
99};
100
101static bool InitResponse(const StunMessage* req, StunMessage* resp) {
102 int resp_type = (req) ? GetStunSuccessResponseType(req->type()) : -1;
103 if (resp_type == -1)
104 return false;
105 resp->SetType(resp_type);
106 resp->SetTransactionID(req->transaction_id());
107 return true;
108}
109
110static bool InitErrorResponse(const StunMessage* req, int code,
111 const std::string& reason, StunMessage* resp) {
112 int resp_type = (req) ? GetStunErrorResponseType(req->type()) : -1;
113 if (resp_type == -1)
114 return false;
115 resp->SetType(resp_type);
116 resp->SetTransactionID(req->transaction_id());
zsteinf42cc9d2017-03-27 16:17:19 -0700117 resp->AddAttribute(rtc::MakeUnique<cricket::StunErrorCodeAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800118 STUN_ATTR_ERROR_CODE, code, reason));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000119 return true;
120}
121
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000122
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000123TurnServer::TurnServer(rtc::Thread* thread)
124 : thread_(thread),
125 nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
126 auth_hook_(NULL),
127 redirect_hook_(NULL),
128 enable_otu_nonce_(false) {
129}
130
131TurnServer::~TurnServer() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000132 for (InternalSocketMap::iterator it = server_sockets_.begin();
133 it != server_sockets_.end(); ++it) {
134 rtc::AsyncPacketSocket* socket = it->first;
135 delete socket;
136 }
137
138 for (ServerSocketMap::iterator it = server_listen_sockets_.begin();
139 it != server_listen_sockets_.end(); ++it) {
140 rtc::AsyncSocket* socket = it->first;
141 delete socket;
142 }
143}
144
145void TurnServer::AddInternalSocket(rtc::AsyncPacketSocket* socket,
146 ProtocolType proto) {
nisseede5da42017-01-12 05:15:36 -0800147 RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000148 server_sockets_[socket] = proto;
149 socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket);
150}
151
152void TurnServer::AddInternalServerSocket(rtc::AsyncSocket* socket,
153 ProtocolType proto) {
nisseede5da42017-01-12 05:15:36 -0800154 RTC_DCHECK(server_listen_sockets_.end() ==
155 server_listen_sockets_.find(socket));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000156 server_listen_sockets_[socket] = proto;
157 socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection);
158}
159
160void TurnServer::SetExternalSocketFactory(
161 rtc::PacketSocketFactory* factory,
162 const rtc::SocketAddress& external_addr) {
163 external_socket_factory_.reset(factory);
164 external_addr_ = external_addr;
165}
166
167void TurnServer::OnNewInternalConnection(rtc::AsyncSocket* socket) {
nisseede5da42017-01-12 05:15:36 -0800168 RTC_DCHECK(server_listen_sockets_.find(socket) !=
169 server_listen_sockets_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000170 AcceptConnection(socket);
171}
172
173void TurnServer::AcceptConnection(rtc::AsyncSocket* server_socket) {
174 // Check if someone is trying to connect to us.
175 rtc::SocketAddress accept_addr;
176 rtc::AsyncSocket* accepted_socket = server_socket->Accept(&accept_addr);
177 if (accepted_socket != NULL) {
178 ProtocolType proto = server_listen_sockets_[server_socket];
179 cricket::AsyncStunTCPSocket* tcp_socket =
180 new cricket::AsyncStunTCPSocket(accepted_socket, false);
181
182 tcp_socket->SignalClose.connect(this, &TurnServer::OnInternalSocketClose);
183 // Finally add the socket so it can start communicating with the client.
184 AddInternalSocket(tcp_socket, proto);
185 }
186}
187
188void TurnServer::OnInternalSocketClose(rtc::AsyncPacketSocket* socket,
189 int err) {
190 DestroyInternalSocket(socket);
191}
192
193void TurnServer::OnInternalPacket(rtc::AsyncPacketSocket* socket,
194 const char* data, size_t size,
195 const rtc::SocketAddress& addr,
196 const rtc::PacketTime& packet_time) {
197 // Fail if the packet is too small to even contain a channel header.
198 if (size < TURN_CHANNEL_HEADER_SIZE) {
199 return;
200 }
201 InternalSocketMap::iterator iter = server_sockets_.find(socket);
nisseede5da42017-01-12 05:15:36 -0800202 RTC_DCHECK(iter != server_sockets_.end());
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000203 TurnServerConnection conn(addr, iter->second, socket);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200204 uint16_t msg_type = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000205 if (!IsTurnChannelData(msg_type)) {
206 // This is a STUN message.
207 HandleStunMessage(&conn, data, size);
208 } else {
209 // This is a channel message; let the allocation handle it.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000210 TurnServerAllocation* allocation = FindAllocation(&conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000211 if (allocation) {
212 allocation->HandleChannelData(data, size);
213 }
Jonas Orelandbdcee282017-10-10 14:01:40 +0200214 if (stun_message_observer_ != nullptr) {
215 stun_message_observer_->ReceivedChannelData(data, size);
216 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000217 }
218}
219
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000220void TurnServer::HandleStunMessage(TurnServerConnection* conn, const char* data,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000221 size_t size) {
222 TurnMessage msg;
jbauchf1f87202016-03-30 06:43:37 -0700223 rtc::ByteBufferReader buf(data, size);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000224 if (!msg.Read(&buf) || (buf.Length() > 0)) {
225 LOG(LS_WARNING) << "Received invalid STUN message";
226 return;
227 }
228
Jonas Orelandbdcee282017-10-10 14:01:40 +0200229 if (stun_message_observer_ != nullptr) {
230 stun_message_observer_->ReceivedMessage(&msg);
231 }
232
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000233 // If it's a STUN binding request, handle that specially.
234 if (msg.type() == STUN_BINDING_REQUEST) {
235 HandleBindingRequest(conn, &msg);
236 return;
237 }
238
239 if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
240 rtc::SocketAddress address;
241 if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
242 SendErrorResponseWithAlternateServer(
243 conn, &msg, address);
244 return;
245 }
246 }
247
248 // Look up the key that we'll use to validate the M-I. If we have an
249 // existing allocation, the key will already be cached.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000250 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000251 std::string key;
252 if (!allocation) {
253 GetKey(&msg, &key);
254 } else {
255 key = allocation->key();
256 }
257
258 // Ensure the message is authorized; only needed for requests.
259 if (IsStunRequestType(msg.type())) {
260 if (!CheckAuthorization(conn, &msg, data, size, key)) {
261 return;
262 }
263 }
264
265 if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
266 HandleAllocateRequest(conn, &msg, key);
267 } else if (allocation &&
268 (msg.type() != STUN_ALLOCATE_REQUEST ||
269 msg.transaction_id() == allocation->transaction_id())) {
270 // This is a non-allocate request, or a retransmit of an allocate.
271 // Check that the username matches the previous username used.
272 if (IsStunRequestType(msg.type()) &&
273 msg.GetByteString(STUN_ATTR_USERNAME)->GetString() !=
274 allocation->username()) {
275 SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
276 STUN_ERROR_REASON_WRONG_CREDENTIALS);
277 return;
278 }
279 allocation->HandleTurnMessage(&msg);
280 } else {
281 // Allocation mismatch.
282 SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH,
283 STUN_ERROR_REASON_ALLOCATION_MISMATCH);
284 }
285}
286
287bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
288 const StunByteStringAttribute* username_attr =
289 msg->GetByteString(STUN_ATTR_USERNAME);
290 if (!username_attr) {
291 return false;
292 }
293
294 std::string username = username_attr->GetString();
295 return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key));
296}
297
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000298bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000299 const StunMessage* msg,
300 const char* data, size_t size,
301 const std::string& key) {
302 // RFC 5389, 10.2.2.
nisseede5da42017-01-12 05:15:36 -0800303 RTC_DCHECK(IsStunRequestType(msg->type()));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000304 const StunByteStringAttribute* mi_attr =
305 msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
306 const StunByteStringAttribute* username_attr =
307 msg->GetByteString(STUN_ATTR_USERNAME);
308 const StunByteStringAttribute* realm_attr =
309 msg->GetByteString(STUN_ATTR_REALM);
310 const StunByteStringAttribute* nonce_attr =
311 msg->GetByteString(STUN_ATTR_NONCE);
312
313 // Fail if no M-I.
314 if (!mi_attr) {
315 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
316 STUN_ERROR_REASON_UNAUTHORIZED);
317 return false;
318 }
319
320 // Fail if there is M-I but no username, nonce, or realm.
321 if (!username_attr || !realm_attr || !nonce_attr) {
322 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
323 STUN_ERROR_REASON_BAD_REQUEST);
324 return false;
325 }
326
327 // Fail if bad nonce.
328 if (!ValidateNonce(nonce_attr->GetString())) {
329 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
330 STUN_ERROR_REASON_STALE_NONCE);
331 return false;
332 }
333
334 // Fail if bad username or M-I.
335 // We need |data| and |size| for the call to ValidateMessageIntegrity.
336 if (key.empty() || !StunMessage::ValidateMessageIntegrity(data, size, key)) {
337 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
338 STUN_ERROR_REASON_UNAUTHORIZED);
339 return false;
340 }
341
342 // Fail if one-time-use nonce feature is enabled.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000343 TurnServerAllocation* allocation = FindAllocation(conn);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000344 if (enable_otu_nonce_ && allocation &&
345 allocation->last_nonce() == nonce_attr->GetString()) {
346 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
347 STUN_ERROR_REASON_STALE_NONCE);
348 return false;
349 }
350
351 if (allocation) {
352 allocation->set_last_nonce(nonce_attr->GetString());
353 }
354 // Success.
355 return true;
356}
357
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000358void TurnServer::HandleBindingRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000359 const StunMessage* req) {
360 StunMessage response;
361 InitResponse(req, &response);
362
363 // Tell the user the address that we received their request from.
zsteinf42cc9d2017-03-27 16:17:19 -0700364 auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000365 STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
zsteinf42cc9d2017-03-27 16:17:19 -0700366 response.AddAttribute(std::move(mapped_addr_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000367
368 SendStun(conn, &response);
369}
370
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000371void TurnServer::HandleAllocateRequest(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000372 const TurnMessage* msg,
373 const std::string& key) {
374 // Check the parameters in the request.
375 const StunUInt32Attribute* transport_attr =
376 msg->GetUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
377 if (!transport_attr) {
378 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
379 STUN_ERROR_REASON_BAD_REQUEST);
380 return;
381 }
382
383 // Only UDP is supported right now.
384 int proto = transport_attr->value() >> 24;
385 if (proto != IPPROTO_UDP) {
386 SendErrorResponse(conn, msg, STUN_ERROR_UNSUPPORTED_PROTOCOL,
387 STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL);
388 return;
389 }
390
391 // Create the allocation and let it send the success response.
392 // If the actual socket allocation fails, send an internal error.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000393 TurnServerAllocation* alloc = CreateAllocation(conn, proto, key);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000394 if (alloc) {
395 alloc->HandleTurnMessage(msg);
396 } else {
397 SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR,
398 "Failed to allocate socket");
399 }
400}
401
honghaiz34b11eb2016-03-16 08:55:44 -0700402std::string TurnServer::GenerateNonce(int64_t now) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000403 // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000404 std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
405 std::string nonce = rtc::hex_encode(input.c_str(), input.size());
406 nonce += rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, input);
nisseede5da42017-01-12 05:15:36 -0800407 RTC_DCHECK(nonce.size() == kNonceSize);
honghaiz34b11eb2016-03-16 08:55:44 -0700408
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000409 return nonce;
410}
411
412bool TurnServer::ValidateNonce(const std::string& nonce) const {
413 // Check the size.
414 if (nonce.size() != kNonceSize) {
415 return false;
416 }
417
418 // Decode the timestamp.
honghaiz34b11eb2016-03-16 08:55:44 -0700419 int64_t then;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000420 char* p = reinterpret_cast<char*>(&then);
421 size_t len = rtc::hex_decode(p, sizeof(then),
422 nonce.substr(0, sizeof(then) * 2));
423 if (len != sizeof(then)) {
424 return false;
425 }
426
427 // Verify the HMAC.
428 if (nonce.substr(sizeof(then) * 2) != rtc::ComputeHmac(
429 rtc::DIGEST_MD5, nonce_key_, std::string(p, sizeof(then)))) {
430 return false;
431 }
432
433 // Validate the timestamp.
nisse1bffc1d2016-05-02 08:18:55 -0700434 return rtc::TimeMillis() - then < kNonceTimeout;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000435}
436
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000437TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000438 AllocationMap::const_iterator it = allocations_.find(*conn);
deadbeef97943662016-07-12 11:04:50 -0700439 return (it != allocations_.end()) ? it->second.get() : nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000440}
441
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000442TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn,
443 int proto,
444 const std::string& key) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000445 rtc::AsyncPacketSocket* external_socket = (external_socket_factory_) ?
446 external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) : NULL;
447 if (!external_socket) {
448 return NULL;
449 }
450
451 // The Allocation takes ownership of the socket.
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000452 TurnServerAllocation* allocation = new TurnServerAllocation(this,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000453 thread_, *conn, external_socket, key);
454 allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed);
deadbeef97943662016-07-12 11:04:50 -0700455 allocations_[*conn].reset(allocation);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000456 return allocation;
457}
458
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000459void TurnServer::SendErrorResponse(TurnServerConnection* conn,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000460 const StunMessage* req,
461 int code, const std::string& reason) {
462 TurnMessage resp;
463 InitErrorResponse(req, code, reason, &resp);
464 LOG(LS_INFO) << "Sending error response, type=" << resp.type()
465 << ", code=" << code << ", reason=" << reason;
466 SendStun(conn, &resp);
467}
468
469void TurnServer::SendErrorResponseWithRealmAndNonce(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000470 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000471 int code, const std::string& reason) {
472 TurnMessage resp;
473 InitErrorResponse(msg, code, reason, &resp);
honghaizc463e202016-02-01 15:19:08 -0800474
nisse1bffc1d2016-05-02 08:18:55 -0700475 int64_t timestamp = rtc::TimeMillis();
honghaizc463e202016-02-01 15:19:08 -0800476 if (ts_for_next_nonce_) {
477 timestamp = ts_for_next_nonce_;
478 ts_for_next_nonce_ = 0;
479 }
zsteinf42cc9d2017-03-27 16:17:19 -0700480 resp.AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
481 STUN_ATTR_NONCE, GenerateNonce(timestamp)));
nissecc99bc22017-02-02 01:31:30 -0800482 resp.AddAttribute(
zsteinf42cc9d2017-03-27 16:17:19 -0700483 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000484 SendStun(conn, &resp);
485}
486
487void TurnServer::SendErrorResponseWithAlternateServer(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000488 TurnServerConnection* conn, const StunMessage* msg,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000489 const rtc::SocketAddress& addr) {
490 TurnMessage resp;
491 InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
492 STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
zsteinf42cc9d2017-03-27 16:17:19 -0700493 resp.AddAttribute(
494 rtc::MakeUnique<StunAddressAttribute>(STUN_ATTR_ALTERNATE_SERVER, addr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000495 SendStun(conn, &resp);
496}
497
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000498void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
jbauchf1f87202016-03-30 06:43:37 -0700499 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000500 // Add a SOFTWARE attribute if one is set.
501 if (!software_.empty()) {
zsteinf42cc9d2017-03-27 16:17:19 -0700502 msg->AddAttribute(rtc::MakeUnique<StunByteStringAttribute>(
503 STUN_ATTR_SOFTWARE, software_));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000504 }
505 msg->Write(&buf);
506 Send(conn, buf);
507}
508
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000509void TurnServer::Send(TurnServerConnection* conn,
jbauchf1f87202016-03-30 06:43:37 -0700510 const rtc::ByteBufferWriter& buf) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000511 rtc::PacketOptions options;
512 conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
513}
514
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000515void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000516 // Removing the internal socket if the connection is not udp.
517 rtc::AsyncPacketSocket* socket = allocation->conn()->socket();
518 InternalSocketMap::iterator iter = server_sockets_.find(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000519 // Skip if the socket serving this allocation is UDP, as this will be shared
520 // by all allocations.
Taylor Brandstetter716d07a2016-06-27 14:07:41 -0700521 // Note: We may not find a socket if it's a TCP socket that was closed, and
522 // the allocation is only now timing out.
523 if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000524 DestroyInternalSocket(socket);
525 }
526
527 AllocationMap::iterator it = allocations_.find(*(allocation->conn()));
deadbeef97943662016-07-12 11:04:50 -0700528 if (it != allocations_.end()) {
529 it->second.release();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000530 allocations_.erase(it);
deadbeef97943662016-07-12 11:04:50 -0700531 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000532}
533
534void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
535 InternalSocketMap::iterator iter = server_sockets_.find(socket);
536 if (iter != server_sockets_.end()) {
537 rtc::AsyncPacketSocket* socket = iter->first;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000538 server_sockets_.erase(iter);
deadbeef824f5862016-08-24 15:06:53 -0700539 // We must destroy the socket async to avoid invalidating the sigslot
540 // callback list iterator inside a sigslot callback. (In other words,
541 // deleting an object from within a callback from that object).
542 sockets_to_delete_.push_back(
543 std::unique_ptr<rtc::AsyncPacketSocket>(socket));
544 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, rtc::Thread::Current(),
545 rtc::Bind(&TurnServer::FreeSockets, this));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000546 }
547}
548
deadbeef824f5862016-08-24 15:06:53 -0700549void TurnServer::FreeSockets() {
550 sockets_to_delete_.clear();
551}
552
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000553TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src,
554 ProtocolType proto,
555 rtc::AsyncPacketSocket* socket)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000556 : src_(src),
557 dst_(socket->GetRemoteAddress()),
558 proto_(proto),
559 socket_(socket) {
560}
561
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000562bool TurnServerConnection::operator==(const TurnServerConnection& c) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000563 return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
564}
565
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000566bool TurnServerConnection::operator<(const TurnServerConnection& c) const {
Taylor Brandstetter734262c2016-08-01 16:37:14 -0700567 return std::tie(src_, dst_, proto_) < std::tie(c.src_, c.dst_, c.proto_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000568}
569
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000570std::string TurnServerConnection::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000571 const char* const kProtos[] = {
572 "unknown", "udp", "tcp", "ssltcp"
573 };
574 std::ostringstream ost;
575 ost << src_.ToString() << "-" << dst_.ToString() << ":"<< kProtos[proto_];
576 return ost.str();
577}
578
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000579TurnServerAllocation::TurnServerAllocation(TurnServer* server,
580 rtc::Thread* thread,
581 const TurnServerConnection& conn,
582 rtc::AsyncPacketSocket* socket,
583 const std::string& key)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000584 : server_(server),
585 thread_(thread),
586 conn_(conn),
587 external_socket_(socket),
588 key_(key) {
589 external_socket_->SignalReadPacket.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000590 this, &TurnServerAllocation::OnExternalPacket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000591}
592
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000593TurnServerAllocation::~TurnServerAllocation() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000594 for (ChannelList::iterator it = channels_.begin();
595 it != channels_.end(); ++it) {
596 delete *it;
597 }
598 for (PermissionList::iterator it = perms_.begin();
599 it != perms_.end(); ++it) {
600 delete *it;
601 }
602 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
603 LOG_J(LS_INFO, this) << "Allocation destroyed";
604}
605
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000606std::string TurnServerAllocation::ToString() const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000607 std::ostringstream ost;
608 ost << "Alloc[" << conn_.ToString() << "]";
609 return ost.str();
610}
611
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000612void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) {
nisseede5da42017-01-12 05:15:36 -0800613 RTC_DCHECK(msg != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000614 switch (msg->type()) {
615 case STUN_ALLOCATE_REQUEST:
616 HandleAllocateRequest(msg);
617 break;
618 case TURN_REFRESH_REQUEST:
619 HandleRefreshRequest(msg);
620 break;
621 case TURN_SEND_INDICATION:
622 HandleSendIndication(msg);
623 break;
624 case TURN_CREATE_PERMISSION_REQUEST:
625 HandleCreatePermissionRequest(msg);
626 break;
627 case TURN_CHANNEL_BIND_REQUEST:
628 HandleChannelBindRequest(msg);
629 break;
630 default:
631 // Not sure what to do with this, just eat it.
632 LOG_J(LS_WARNING, this) << "Invalid TURN message type received: "
633 << msg->type();
634 }
635}
636
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000637void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000638 // Copy the important info from the allocate request.
639 transaction_id_ = msg->transaction_id();
640 const StunByteStringAttribute* username_attr =
641 msg->GetByteString(STUN_ATTR_USERNAME);
nisseede5da42017-01-12 05:15:36 -0800642 RTC_DCHECK(username_attr != NULL);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000643 username_ = username_attr->GetString();
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000644 const StunByteStringAttribute* origin_attr =
645 msg->GetByteString(STUN_ATTR_ORIGIN);
646 if (origin_attr) {
647 origin_ = origin_attr->GetString();
648 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000649
650 // Figure out the lifetime and start the allocation timer.
651 int lifetime_secs = ComputeLifetime(msg);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700652 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
653 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000654
655 LOG_J(LS_INFO, this) << "Created allocation, lifetime=" << lifetime_secs;
656
657 // We've already validated all the important bits; just send a response here.
658 TurnMessage response;
659 InitResponse(msg, &response);
660
zsteinf42cc9d2017-03-27 16:17:19 -0700661 auto mapped_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
662 STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
663 auto relayed_addr_attr = rtc::MakeUnique<StunXorAddressAttribute>(
664 STUN_ATTR_XOR_RELAYED_ADDRESS, external_socket_->GetLocalAddress());
665 auto lifetime_attr =
666 rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
667 response.AddAttribute(std::move(mapped_addr_attr));
668 response.AddAttribute(std::move(relayed_addr_attr));
669 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000670
671 SendResponse(&response);
672}
673
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000674void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000675 // Figure out the new lifetime.
676 int lifetime_secs = ComputeLifetime(msg);
677
678 // Reset the expiration timer.
679 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700680 thread_->PostDelayed(RTC_FROM_HERE, lifetime_secs * 1000, this,
681 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000682
683 LOG_J(LS_INFO, this) << "Refreshed allocation, lifetime=" << lifetime_secs;
684
685 // Send a success response with a LIFETIME attribute.
686 TurnMessage response;
687 InitResponse(msg, &response);
688
zsteinf42cc9d2017-03-27 16:17:19 -0700689 auto lifetime_attr =
690 rtc::MakeUnique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_secs);
691 response.AddAttribute(std::move(lifetime_attr));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000692
693 SendResponse(&response);
694}
695
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000696void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000697 // Check mandatory attributes.
698 const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
699 const StunAddressAttribute* peer_attr =
700 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
701 if (!data_attr || !peer_attr) {
702 LOG_J(LS_WARNING, this) << "Received invalid send indication";
703 return;
704 }
705
706 // If a permission exists, send the data on to the peer.
707 if (HasPermission(peer_attr->GetAddress().ipaddr())) {
708 SendExternal(data_attr->bytes(), data_attr->length(),
709 peer_attr->GetAddress());
710 } else {
711 LOG_J(LS_WARNING, this) << "Received send indication without permission"
712 << "peer=" << peer_attr->GetAddress();
713 }
714}
715
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000716void TurnServerAllocation::HandleCreatePermissionRequest(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000717 const TurnMessage* msg) {
718 // Check mandatory attributes.
719 const StunAddressAttribute* peer_attr =
720 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
721 if (!peer_attr) {
722 SendBadRequestResponse(msg);
723 return;
724 }
725
deadbeef376e1232015-11-25 09:00:08 -0800726 if (server_->reject_private_addresses_ &&
727 rtc::IPIsPrivate(peer_attr->GetAddress().ipaddr())) {
728 SendErrorResponse(msg, STUN_ERROR_FORBIDDEN, STUN_ERROR_REASON_FORBIDDEN);
729 return;
730 }
731
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000732 // Add this permission.
733 AddPermission(peer_attr->GetAddress().ipaddr());
734
735 LOG_J(LS_INFO, this) << "Created permission, peer="
736 << peer_attr->GetAddress();
737
738 // Send a success response.
739 TurnMessage response;
740 InitResponse(msg, &response);
741 SendResponse(&response);
742}
743
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000744void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000745 // Check mandatory attributes.
746 const StunUInt32Attribute* channel_attr =
747 msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
748 const StunAddressAttribute* peer_attr =
749 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
750 if (!channel_attr || !peer_attr) {
751 SendBadRequestResponse(msg);
752 return;
753 }
754
755 // Check that channel id is valid.
756 int channel_id = channel_attr->value() >> 16;
757 if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) {
758 SendBadRequestResponse(msg);
759 return;
760 }
761
762 // Check that this channel id isn't bound to another transport address, and
763 // that this transport address isn't bound to another channel id.
764 Channel* channel1 = FindChannel(channel_id);
765 Channel* channel2 = FindChannel(peer_attr->GetAddress());
766 if (channel1 != channel2) {
767 SendBadRequestResponse(msg);
768 return;
769 }
770
771 // Add or refresh this channel.
772 if (!channel1) {
773 channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress());
774 channel1->SignalDestroyed.connect(this,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000775 &TurnServerAllocation::OnChannelDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000776 channels_.push_back(channel1);
777 } else {
778 channel1->Refresh();
779 }
780
781 // Channel binds also refresh permissions.
782 AddPermission(peer_attr->GetAddress().ipaddr());
783
784 LOG_J(LS_INFO, this) << "Bound channel, id=" << channel_id
785 << ", peer=" << peer_attr->GetAddress();
786
787 // Send a success response.
788 TurnMessage response;
789 InitResponse(msg, &response);
790 SendResponse(&response);
791}
792
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000793void TurnServerAllocation::HandleChannelData(const char* data, size_t size) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000794 // Extract the channel number from the data.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200795 uint16_t channel_id = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000796 Channel* channel = FindChannel(channel_id);
797 if (channel) {
798 // Send the data to the peer address.
799 SendExternal(data + TURN_CHANNEL_HEADER_SIZE,
800 size - TURN_CHANNEL_HEADER_SIZE, channel->peer());
801 } else {
802 LOG_J(LS_WARNING, this) << "Received channel data for invalid channel, id="
803 << channel_id;
804 }
805}
806
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000807void TurnServerAllocation::OnExternalPacket(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000808 rtc::AsyncPacketSocket* socket,
809 const char* data, size_t size,
810 const rtc::SocketAddress& addr,
811 const rtc::PacketTime& packet_time) {
nisseede5da42017-01-12 05:15:36 -0800812 RTC_DCHECK(external_socket_.get() == socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000813 Channel* channel = FindChannel(addr);
814 if (channel) {
815 // There is a channel bound to this address. Send as a channel message.
jbauchf1f87202016-03-30 06:43:37 -0700816 rtc::ByteBufferWriter buf;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000817 buf.WriteUInt16(channel->id());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200818 buf.WriteUInt16(static_cast<uint16_t>(size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000819 buf.WriteBytes(data, size);
820 server_->Send(&conn_, buf);
Taylor Brandstetteref184702016-06-23 17:35:47 -0700821 } else if (!server_->enable_permission_checks_ ||
822 HasPermission(addr.ipaddr())) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000823 // No channel, but a permission exists. Send as a data indication.
824 TurnMessage msg;
825 msg.SetType(TURN_DATA_INDICATION);
826 msg.SetTransactionID(
827 rtc::CreateRandomString(kStunTransactionIdLength));
zsteinf42cc9d2017-03-27 16:17:19 -0700828 msg.AddAttribute(rtc::MakeUnique<StunXorAddressAttribute>(
nissecc99bc22017-02-02 01:31:30 -0800829 STUN_ATTR_XOR_PEER_ADDRESS, addr));
zsteinf42cc9d2017-03-27 16:17:19 -0700830 msg.AddAttribute(
831 rtc::MakeUnique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000832 server_->SendStun(&conn_, &msg);
833 } else {
834 LOG_J(LS_WARNING, this) << "Received external packet without permission, "
835 << "peer=" << addr;
836 }
837}
838
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000839int TurnServerAllocation::ComputeLifetime(const TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000840 // Return the smaller of our default lifetime and the requested lifetime.
honghaiz34b11eb2016-03-16 08:55:44 -0700841 int lifetime = kDefaultAllocationTimeout / 1000; // convert to seconds
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000842 const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME);
honghaiz34b11eb2016-03-16 08:55:44 -0700843 if (lifetime_attr && static_cast<int>(lifetime_attr->value()) < lifetime) {
844 lifetime = static_cast<int>(lifetime_attr->value());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000845 }
846 return lifetime;
847}
848
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000849bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000850 return (FindPermission(addr) != NULL);
851}
852
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000853void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000854 Permission* perm = FindPermission(addr);
855 if (!perm) {
856 perm = new Permission(thread_, addr);
857 perm->SignalDestroyed.connect(
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000858 this, &TurnServerAllocation::OnPermissionDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000859 perms_.push_back(perm);
860 } else {
861 perm->Refresh();
862 }
863}
864
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000865TurnServerAllocation::Permission* TurnServerAllocation::FindPermission(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000866 const rtc::IPAddress& addr) const {
867 for (PermissionList::const_iterator it = perms_.begin();
868 it != perms_.end(); ++it) {
869 if ((*it)->peer() == addr)
870 return *it;
871 }
872 return NULL;
873}
874
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000875TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
876 int channel_id) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000877 for (ChannelList::const_iterator it = channels_.begin();
878 it != channels_.end(); ++it) {
879 if ((*it)->id() == channel_id)
880 return *it;
881 }
882 return NULL;
883}
884
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000885TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000886 const rtc::SocketAddress& addr) const {
887 for (ChannelList::const_iterator it = channels_.begin();
888 it != channels_.end(); ++it) {
889 if ((*it)->peer() == addr)
890 return *it;
891 }
892 return NULL;
893}
894
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000895void TurnServerAllocation::SendResponse(TurnMessage* msg) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000896 // Success responses always have M-I.
897 msg->AddMessageIntegrity(key_);
898 server_->SendStun(&conn_, msg);
899}
900
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000901void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000902 SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
903}
904
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000905void TurnServerAllocation::SendErrorResponse(const TurnMessage* req, int code,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000906 const std::string& reason) {
907 server_->SendErrorResponse(&conn_, req, code, reason);
908}
909
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000910void TurnServerAllocation::SendExternal(const void* data, size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000911 const rtc::SocketAddress& peer) {
912 rtc::PacketOptions options;
913 external_socket_->SendTo(data, size, peer, options);
914}
915
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000916void TurnServerAllocation::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800917 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000918 SignalDestroyed(this);
919 delete this;
920}
921
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000922void TurnServerAllocation::OnPermissionDestroyed(Permission* perm) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000923 PermissionList::iterator it = std::find(perms_.begin(), perms_.end(), perm);
nisseede5da42017-01-12 05:15:36 -0800924 RTC_DCHECK(it != perms_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000925 perms_.erase(it);
926}
927
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000928void TurnServerAllocation::OnChannelDestroyed(Channel* channel) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000929 ChannelList::iterator it =
930 std::find(channels_.begin(), channels_.end(), channel);
nisseede5da42017-01-12 05:15:36 -0800931 RTC_DCHECK(it != channels_.end());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000932 channels_.erase(it);
933}
934
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000935TurnServerAllocation::Permission::Permission(rtc::Thread* thread,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936 const rtc::IPAddress& peer)
937 : thread_(thread), peer_(peer) {
938 Refresh();
939}
940
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000941TurnServerAllocation::Permission::~Permission() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000942 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
943}
944
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000945void TurnServerAllocation::Permission::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000946 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700947 thread_->PostDelayed(RTC_FROM_HERE, kPermissionTimeout, this,
948 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000949}
950
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000951void TurnServerAllocation::Permission::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800952 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000953 SignalDestroyed(this);
954 delete this;
955}
956
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000957TurnServerAllocation::Channel::Channel(rtc::Thread* thread, int id,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000958 const rtc::SocketAddress& peer)
959 : thread_(thread), id_(id), peer_(peer) {
960 Refresh();
961}
962
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000963TurnServerAllocation::Channel::~Channel() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000964 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
965}
966
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000967void TurnServerAllocation::Channel::Refresh() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000968 thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700969 thread_->PostDelayed(RTC_FROM_HERE, kChannelTimeout, this,
970 MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000971}
972
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000973void TurnServerAllocation::Channel::OnMessage(rtc::Message* msg) {
nisseede5da42017-01-12 05:15:36 -0800974 RTC_DCHECK(msg->message_id == MSG_ALLOCATION_TIMEOUT);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000975 SignalDestroyed(this);
976 delete this;
977}
978
979} // namespace cricket