blob: 4d7f39e8f1cf105e83182f47dfba2d6115464ba5 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2012, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/p2p/base/turnserver.h"
29
30#include "talk/base/bytebuffer.h"
31#include "talk/base/helpers.h"
32#include "talk/base/logging.h"
33#include "talk/base/messagedigest.h"
34#include "talk/base/socketadapters.h"
35#include "talk/base/stringencode.h"
36#include "talk/base/thread.h"
37#include "talk/p2p/base/asyncstuntcpsocket.h"
38#include "talk/p2p/base/common.h"
39#include "talk/p2p/base/packetsocketfactory.h"
40#include "talk/p2p/base/stun.h"
41
42namespace cricket {
43
44// TODO(juberti): Move this all to a future turnmessage.h
45//static const int IPPROTO_UDP = 17;
46static const int kNonceTimeout = 60 * 60 * 1000; // 60 minutes
47static const int kDefaultAllocationTimeout = 10 * 60 * 1000; // 10 minutes
48static const int kPermissionTimeout = 5 * 60 * 1000; // 5 minutes
49static const int kChannelTimeout = 10 * 60 * 1000; // 10 minutes
50
51static const int kMinChannelNumber = 0x4000;
52static const int kMaxChannelNumber = 0x7FFF;
53
54static const size_t kNonceKeySize = 16;
55static const size_t kNonceSize = 40;
56
57static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
58
59// TODO(mallinath) - Move these to a common place.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060inline bool IsTurnChannelData(uint16 msg_type) {
61 // The first two bits of a channel data message are 0b01.
62 return ((msg_type & 0xC000) == 0x4000);
63}
64
65// IDs used for posted messages.
66enum {
67 MSG_TIMEOUT,
68};
69
70// Encapsulates a TURN allocation.
71// The object is created when an allocation request is received, and then
72// handles TURN messages (via HandleTurnMessage) and channel data messages
73// (via HandleChannelData) for this allocation when received by the server.
74// The object self-deletes and informs the server if its lifetime timer expires.
75class TurnServer::Allocation : public talk_base::MessageHandler,
76 public sigslot::has_slots<> {
77 public:
78 Allocation(TurnServer* server_,
79 talk_base::Thread* thread, const Connection& conn,
80 talk_base::AsyncPacketSocket* server_socket,
81 const std::string& key);
82 virtual ~Allocation();
83
84 Connection* conn() { return &conn_; }
85 const std::string& key() const { return key_; }
86 const std::string& transaction_id() const { return transaction_id_; }
87 const std::string& username() const { return username_; }
88 const std::string& last_nonce() const { return last_nonce_; }
89 void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; }
90
91 std::string ToString() const;
92
93 void HandleTurnMessage(const TurnMessage* msg);
94 void HandleChannelData(const char* data, size_t size);
95
96 sigslot::signal1<Allocation*> SignalDestroyed;
97
98 private:
99 typedef std::list<Permission*> PermissionList;
100 typedef std::list<Channel*> ChannelList;
101
102 void HandleAllocateRequest(const TurnMessage* msg);
103 void HandleRefreshRequest(const TurnMessage* msg);
104 void HandleSendIndication(const TurnMessage* msg);
105 void HandleCreatePermissionRequest(const TurnMessage* msg);
106 void HandleChannelBindRequest(const TurnMessage* msg);
107
108 void OnExternalPacket(talk_base::AsyncPacketSocket* socket,
109 const char* data, size_t size,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000110 const talk_base::SocketAddress& addr,
111 const talk_base::PacketTime& packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112
113 static int ComputeLifetime(const TurnMessage* msg);
114 bool HasPermission(const talk_base::IPAddress& addr);
115 void AddPermission(const talk_base::IPAddress& addr);
116 Permission* FindPermission(const talk_base::IPAddress& addr) const;
117 Channel* FindChannel(int channel_id) const;
118 Channel* FindChannel(const talk_base::SocketAddress& addr) const;
119
120 void SendResponse(TurnMessage* msg);
121 void SendBadRequestResponse(const TurnMessage* req);
122 void SendErrorResponse(const TurnMessage* req, int code,
123 const std::string& reason);
124 void SendExternal(const void* data, size_t size,
125 const talk_base::SocketAddress& peer);
126
127 void OnPermissionDestroyed(Permission* perm);
128 void OnChannelDestroyed(Channel* channel);
129 virtual void OnMessage(talk_base::Message* msg);
130
131 TurnServer* server_;
132 talk_base::Thread* thread_;
133 Connection conn_;
134 talk_base::scoped_ptr<talk_base::AsyncPacketSocket> external_socket_;
135 std::string key_;
136 std::string transaction_id_;
137 std::string username_;
138 std::string last_nonce_;
139 PermissionList perms_;
140 ChannelList channels_;
141};
142
143// Encapsulates a TURN permission.
144// The object is created when a create permission request is received by an
145// allocation, and self-deletes when its lifetime timer expires.
146class TurnServer::Permission : public talk_base::MessageHandler {
147 public:
148 Permission(talk_base::Thread* thread, const talk_base::IPAddress& peer);
149 ~Permission();
150
151 const talk_base::IPAddress& peer() const { return peer_; }
152 void Refresh();
153
154 sigslot::signal1<Permission*> SignalDestroyed;
155
156 private:
157 virtual void OnMessage(talk_base::Message* msg);
158
159 talk_base::Thread* thread_;
160 talk_base::IPAddress peer_;
161};
162
163// Encapsulates a TURN channel binding.
164// The object is created when a channel bind request is received by an
165// allocation, and self-deletes when its lifetime timer expires.
166class TurnServer::Channel : public talk_base::MessageHandler {
167 public:
168 Channel(talk_base::Thread* thread, int id,
169 const talk_base::SocketAddress& peer);
170 ~Channel();
171
172 int id() const { return id_; }
173 const talk_base::SocketAddress& peer() const { return peer_; }
174 void Refresh();
175
176 sigslot::signal1<Channel*> SignalDestroyed;
177
178 private:
179 virtual void OnMessage(talk_base::Message* msg);
180
181 talk_base::Thread* thread_;
182 int id_;
183 talk_base::SocketAddress peer_;
184};
185
186static bool InitResponse(const StunMessage* req, StunMessage* resp) {
187 int resp_type = (req) ? GetStunSuccessResponseType(req->type()) : -1;
188 if (resp_type == -1)
189 return false;
190 resp->SetType(resp_type);
191 resp->SetTransactionID(req->transaction_id());
192 return true;
193}
194
195static bool InitErrorResponse(const StunMessage* req, int code,
196 const std::string& reason, StunMessage* resp) {
197 int resp_type = (req) ? GetStunErrorResponseType(req->type()) : -1;
198 if (resp_type == -1)
199 return false;
200 resp->SetType(resp_type);
201 resp->SetTransactionID(req->transaction_id());
202 VERIFY(resp->AddAttribute(new cricket::StunErrorCodeAttribute(
203 STUN_ATTR_ERROR_CODE, code, reason)));
204 return true;
205}
206
207TurnServer::TurnServer(talk_base::Thread* thread)
208 : thread_(thread),
209 nonce_key_(talk_base::CreateRandomString(kNonceKeySize)),
210 auth_hook_(NULL),
211 enable_otu_nonce_(false) {
212}
213
214TurnServer::~TurnServer() {
215 for (AllocationMap::iterator it = allocations_.begin();
216 it != allocations_.end(); ++it) {
217 delete it->second;
218 }
219
220 for (InternalSocketMap::iterator it = server_sockets_.begin();
221 it != server_sockets_.end(); ++it) {
222 talk_base::AsyncPacketSocket* socket = it->first;
223 delete socket;
224 }
225
226 for (ServerSocketMap::iterator it = server_listen_sockets_.begin();
227 it != server_listen_sockets_.end(); ++it) {
228 talk_base::AsyncSocket* socket = it->first;
229 delete socket;
230 }
231}
232
233void TurnServer::AddInternalSocket(talk_base::AsyncPacketSocket* socket,
234 ProtocolType proto) {
235 ASSERT(server_sockets_.end() == server_sockets_.find(socket));
236 server_sockets_[socket] = proto;
237 socket->SignalReadPacket.connect(this, &TurnServer::OnInternalPacket);
238}
239
240void TurnServer::AddInternalServerSocket(talk_base::AsyncSocket* socket,
241 ProtocolType proto) {
242 ASSERT(server_listen_sockets_.end() ==
243 server_listen_sockets_.find(socket));
244 server_listen_sockets_[socket] = proto;
245 socket->SignalReadEvent.connect(this, &TurnServer::OnNewInternalConnection);
246}
247
248void TurnServer::SetExternalSocketFactory(
249 talk_base::PacketSocketFactory* factory,
250 const talk_base::SocketAddress& external_addr) {
251 external_socket_factory_.reset(factory);
252 external_addr_ = external_addr;
253}
254
255void TurnServer::OnNewInternalConnection(talk_base::AsyncSocket* socket) {
256 ASSERT(server_listen_sockets_.find(socket) != server_listen_sockets_.end());
257 AcceptConnection(socket);
258}
259
260void TurnServer::AcceptConnection(talk_base::AsyncSocket* server_socket) {
261 // Check if someone is trying to connect to us.
262 talk_base::SocketAddress accept_addr;
263 talk_base::AsyncSocket* accepted_socket = server_socket->Accept(&accept_addr);
264 if (accepted_socket != NULL) {
265 ProtocolType proto = server_listen_sockets_[server_socket];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000266 cricket::AsyncStunTCPSocket* tcp_socket =
267 new cricket::AsyncStunTCPSocket(accepted_socket, false);
268
269 tcp_socket->SignalClose.connect(this, &TurnServer::OnInternalSocketClose);
270 // Finally add the socket so it can start communicating with the client.
271 AddInternalSocket(tcp_socket, proto);
272 }
273}
274
275void TurnServer::OnInternalSocketClose(talk_base::AsyncPacketSocket* socket,
276 int err) {
277 DestroyInternalSocket(socket);
278}
279
280void TurnServer::OnInternalPacket(talk_base::AsyncPacketSocket* socket,
281 const char* data, size_t size,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000282 const talk_base::SocketAddress& addr,
283 const talk_base::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 // Fail if the packet is too small to even contain a channel header.
285 if (size < TURN_CHANNEL_HEADER_SIZE) {
286 return;
287 }
288 InternalSocketMap::iterator iter = server_sockets_.find(socket);
289 ASSERT(iter != server_sockets_.end());
290 Connection conn(addr, iter->second, socket);
291 uint16 msg_type = talk_base::GetBE16(data);
292 if (!IsTurnChannelData(msg_type)) {
293 // This is a STUN message.
294 HandleStunMessage(&conn, data, size);
295 } else {
296 // This is a channel message; let the allocation handle it.
297 Allocation* allocation = FindAllocation(&conn);
298 if (allocation) {
299 allocation->HandleChannelData(data, size);
300 }
301 }
302}
303
304void TurnServer::HandleStunMessage(Connection* conn, const char* data,
305 size_t size) {
306 TurnMessage msg;
307 talk_base::ByteBuffer buf(data, size);
308 if (!msg.Read(&buf) || (buf.Length() > 0)) {
309 LOG(LS_WARNING) << "Received invalid STUN message";
310 return;
311 }
312
313 // If it's a STUN binding request, handle that specially.
314 if (msg.type() == STUN_BINDING_REQUEST) {
315 HandleBindingRequest(conn, &msg);
316 return;
317 }
318
319 // Look up the key that we'll use to validate the M-I. If we have an
320 // existing allocation, the key will already be cached.
321 Allocation* allocation = FindAllocation(conn);
322 std::string key;
323 if (!allocation) {
324 GetKey(&msg, &key);
325 } else {
326 key = allocation->key();
327 }
328
329 // Ensure the message is authorized; only needed for requests.
330 if (IsStunRequestType(msg.type())) {
331 if (!CheckAuthorization(conn, &msg, data, size, key)) {
332 return;
333 }
334 }
335
336 if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
337 // This is a new allocate request.
338 HandleAllocateRequest(conn, &msg, key);
339 } else if (allocation &&
340 (msg.type() != STUN_ALLOCATE_REQUEST ||
341 msg.transaction_id() == allocation->transaction_id())) {
342 // This is a non-allocate request, or a retransmit of an allocate.
343 // Check that the username matches the previous username used.
344 if (IsStunRequestType(msg.type()) &&
345 msg.GetByteString(STUN_ATTR_USERNAME)->GetString() !=
346 allocation->username()) {
347 SendErrorResponse(conn, &msg, STUN_ERROR_WRONG_CREDENTIALS,
348 STUN_ERROR_REASON_WRONG_CREDENTIALS);
349 return;
350 }
351 allocation->HandleTurnMessage(&msg);
352 } else {
353 // Allocation mismatch.
354 SendErrorResponse(conn, &msg, STUN_ERROR_ALLOCATION_MISMATCH,
355 STUN_ERROR_REASON_ALLOCATION_MISMATCH);
356 }
357}
358
359bool TurnServer::GetKey(const StunMessage* msg, std::string* key) {
360 const StunByteStringAttribute* username_attr =
361 msg->GetByteString(STUN_ATTR_USERNAME);
362 if (!username_attr) {
363 return false;
364 }
365
366 std::string username = username_attr->GetString();
367 return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key));
368}
369
370bool TurnServer::CheckAuthorization(Connection* conn,
371 const StunMessage* msg,
372 const char* data, size_t size,
373 const std::string& key) {
374 // RFC 5389, 10.2.2.
375 ASSERT(IsStunRequestType(msg->type()));
376 const StunByteStringAttribute* mi_attr =
377 msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY);
378 const StunByteStringAttribute* username_attr =
379 msg->GetByteString(STUN_ATTR_USERNAME);
380 const StunByteStringAttribute* realm_attr =
381 msg->GetByteString(STUN_ATTR_REALM);
382 const StunByteStringAttribute* nonce_attr =
383 msg->GetByteString(STUN_ATTR_NONCE);
384
385 // Fail if no M-I.
386 if (!mi_attr) {
387 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
388 STUN_ERROR_REASON_UNAUTHORIZED);
389 return false;
390 }
391
392 // Fail if there is M-I but no username, nonce, or realm.
393 if (!username_attr || !realm_attr || !nonce_attr) {
394 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
395 STUN_ERROR_REASON_BAD_REQUEST);
396 return false;
397 }
398
399 // Fail if bad nonce.
400 if (!ValidateNonce(nonce_attr->GetString())) {
401 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
402 STUN_ERROR_REASON_STALE_NONCE);
403 return false;
404 }
405
406 // Fail if bad username or M-I.
407 // We need |data| and |size| for the call to ValidateMessageIntegrity.
408 if (key.empty() || !StunMessage::ValidateMessageIntegrity(data, size, key)) {
409 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_UNAUTHORIZED,
410 STUN_ERROR_REASON_UNAUTHORIZED);
411 return false;
412 }
413
414 // Fail if one-time-use nonce feature is enabled.
415 Allocation* allocation = FindAllocation(conn);
416 if (enable_otu_nonce_ && allocation &&
417 allocation->last_nonce() == nonce_attr->GetString()) {
418 SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
419 STUN_ERROR_REASON_STALE_NONCE);
420 return false;
421 }
422
423 if (allocation) {
424 allocation->set_last_nonce(nonce_attr->GetString());
425 }
426 // Success.
427 return true;
428}
429
430void TurnServer::HandleBindingRequest(Connection* conn,
431 const StunMessage* req) {
432 StunMessage response;
433 InitResponse(req, &response);
434
435 // Tell the user the address that we received their request from.
436 StunAddressAttribute* mapped_addr_attr;
437 mapped_addr_attr = new StunXorAddressAttribute(
438 STUN_ATTR_XOR_MAPPED_ADDRESS, conn->src());
439 VERIFY(response.AddAttribute(mapped_addr_attr));
440
441 SendStun(conn, &response);
442}
443
444void TurnServer::HandleAllocateRequest(Connection* conn,
445 const TurnMessage* msg,
446 const std::string& key) {
447 // Check the parameters in the request.
448 const StunUInt32Attribute* transport_attr =
449 msg->GetUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
450 if (!transport_attr) {
451 SendErrorResponse(conn, msg, STUN_ERROR_BAD_REQUEST,
452 STUN_ERROR_REASON_BAD_REQUEST);
453 return;
454 }
455
456 // Only UDP is supported right now.
457 int proto = transport_attr->value() >> 24;
458 if (proto != IPPROTO_UDP) {
459 SendErrorResponse(conn, msg, STUN_ERROR_UNSUPPORTED_PROTOCOL,
460 STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL);
461 return;
462 }
463
464 // Create the allocation and let it send the success response.
465 // If the actual socket allocation fails, send an internal error.
466 Allocation* alloc = CreateAllocation(conn, proto, key);
467 if (alloc) {
468 alloc->HandleTurnMessage(msg);
469 } else {
470 SendErrorResponse(conn, msg, STUN_ERROR_SERVER_ERROR,
471 "Failed to allocate socket");
472 }
473}
474
475std::string TurnServer::GenerateNonce() const {
476 // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
477 uint32 now = talk_base::Time();
478 std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
479 std::string nonce = talk_base::hex_encode(input.c_str(), input.size());
480 nonce += talk_base::ComputeHmac(talk_base::DIGEST_MD5, nonce_key_, input);
481 ASSERT(nonce.size() == kNonceSize);
482 return nonce;
483}
484
485bool TurnServer::ValidateNonce(const std::string& nonce) const {
486 // Check the size.
487 if (nonce.size() != kNonceSize) {
488 return false;
489 }
490
491 // Decode the timestamp.
492 uint32 then;
493 char* p = reinterpret_cast<char*>(&then);
494 size_t len = talk_base::hex_decode(p, sizeof(then),
495 nonce.substr(0, sizeof(then) * 2));
496 if (len != sizeof(then)) {
497 return false;
498 }
499
500 // Verify the HMAC.
501 if (nonce.substr(sizeof(then) * 2) != talk_base::ComputeHmac(
502 talk_base::DIGEST_MD5, nonce_key_, std::string(p, sizeof(then)))) {
503 return false;
504 }
505
506 // Validate the timestamp.
507 return talk_base::TimeSince(then) < kNonceTimeout;
508}
509
510TurnServer::Allocation* TurnServer::FindAllocation(Connection* conn) {
511 AllocationMap::const_iterator it = allocations_.find(*conn);
512 return (it != allocations_.end()) ? it->second : NULL;
513}
514
515TurnServer::Allocation* TurnServer::CreateAllocation(Connection* conn,
516 int proto,
517 const std::string& key) {
518 talk_base::AsyncPacketSocket* external_socket = (external_socket_factory_) ?
519 external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) : NULL;
520 if (!external_socket) {
521 return NULL;
522 }
523
524 // The Allocation takes ownership of the socket.
525 Allocation* allocation = new Allocation(this,
526 thread_, *conn, external_socket, key);
527 allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed);
528 allocations_[*conn] = allocation;
529 return allocation;
530}
531
532void TurnServer::SendErrorResponse(Connection* conn,
533 const StunMessage* req,
534 int code, const std::string& reason) {
535 TurnMessage resp;
536 InitErrorResponse(req, code, reason, &resp);
537 LOG(LS_INFO) << "Sending error response, type=" << resp.type()
538 << ", code=" << code << ", reason=" << reason;
539 SendStun(conn, &resp);
540}
541
542void TurnServer::SendErrorResponseWithRealmAndNonce(
543 Connection* conn, const StunMessage* msg,
544 int code, const std::string& reason) {
545 TurnMessage resp;
546 InitErrorResponse(msg, code, reason, &resp);
547 VERIFY(resp.AddAttribute(new StunByteStringAttribute(
548 STUN_ATTR_NONCE, GenerateNonce())));
549 VERIFY(resp.AddAttribute(new StunByteStringAttribute(
550 STUN_ATTR_REALM, realm_)));
551 SendStun(conn, &resp);
552}
553
554void TurnServer::SendStun(Connection* conn, StunMessage* msg) {
555 talk_base::ByteBuffer buf;
556 // Add a SOFTWARE attribute if one is set.
557 if (!software_.empty()) {
558 VERIFY(msg->AddAttribute(
559 new StunByteStringAttribute(STUN_ATTR_SOFTWARE, software_)));
560 }
561 msg->Write(&buf);
562 Send(conn, buf);
563}
564
565void TurnServer::Send(Connection* conn,
566 const talk_base::ByteBuffer& buf) {
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000567 talk_base::PacketOptions options;
568 conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000569}
570
571void TurnServer::OnAllocationDestroyed(Allocation* allocation) {
572 // Removing the internal socket if the connection is not udp.
573 talk_base::AsyncPacketSocket* socket = allocation->conn()->socket();
574 InternalSocketMap::iterator iter = server_sockets_.find(socket);
575 ASSERT(iter != server_sockets_.end());
576 // Skip if the socket serving this allocation is UDP, as this will be shared
577 // by all allocations.
578 if (iter->second != cricket::PROTO_UDP) {
579 DestroyInternalSocket(socket);
580 }
581
582 AllocationMap::iterator it = allocations_.find(*(allocation->conn()));
583 if (it != allocations_.end())
584 allocations_.erase(it);
585}
586
587void TurnServer::DestroyInternalSocket(talk_base::AsyncPacketSocket* socket) {
588 InternalSocketMap::iterator iter = server_sockets_.find(socket);
589 if (iter != server_sockets_.end()) {
590 talk_base::AsyncPacketSocket* socket = iter->first;
591 delete socket;
592 server_sockets_.erase(iter);
593 }
594}
595
596TurnServer::Connection::Connection(const talk_base::SocketAddress& src,
597 ProtocolType proto,
598 talk_base::AsyncPacketSocket* socket)
599 : src_(src),
600 dst_(socket->GetRemoteAddress()),
601 proto_(proto),
602 socket_(socket) {
603}
604
605bool TurnServer::Connection::operator==(const Connection& c) const {
606 return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
607}
608
609bool TurnServer::Connection::operator<(const Connection& c) const {
610 return src_ < c.src_ || dst_ < c.dst_ || proto_ < c.proto_;
611}
612
613std::string TurnServer::Connection::ToString() const {
614 const char* const kProtos[] = {
615 "unknown", "udp", "tcp", "ssltcp"
616 };
617 std::ostringstream ost;
618 ost << src_.ToString() << "-" << dst_.ToString() << ":"<< kProtos[proto_];
619 return ost.str();
620}
621
622TurnServer::Allocation::Allocation(TurnServer* server,
623 talk_base::Thread* thread,
624 const Connection& conn,
625 talk_base::AsyncPacketSocket* socket,
626 const std::string& key)
627 : server_(server),
628 thread_(thread),
629 conn_(conn),
630 external_socket_(socket),
631 key_(key) {
632 external_socket_->SignalReadPacket.connect(
633 this, &TurnServer::Allocation::OnExternalPacket);
634}
635
636TurnServer::Allocation::~Allocation() {
637 for (ChannelList::iterator it = channels_.begin();
638 it != channels_.end(); ++it) {
639 delete *it;
640 }
641 for (PermissionList::iterator it = perms_.begin();
642 it != perms_.end(); ++it) {
643 delete *it;
644 }
645 thread_->Clear(this, MSG_TIMEOUT);
646 LOG_J(LS_INFO, this) << "Allocation destroyed";
647}
648
649std::string TurnServer::Allocation::ToString() const {
650 std::ostringstream ost;
651 ost << "Alloc[" << conn_.ToString() << "]";
652 return ost.str();
653}
654
655void TurnServer::Allocation::HandleTurnMessage(const TurnMessage* msg) {
656 ASSERT(msg != NULL);
657 switch (msg->type()) {
658 case STUN_ALLOCATE_REQUEST:
659 HandleAllocateRequest(msg);
660 break;
661 case TURN_REFRESH_REQUEST:
662 HandleRefreshRequest(msg);
663 break;
664 case TURN_SEND_INDICATION:
665 HandleSendIndication(msg);
666 break;
667 case TURN_CREATE_PERMISSION_REQUEST:
668 HandleCreatePermissionRequest(msg);
669 break;
670 case TURN_CHANNEL_BIND_REQUEST:
671 HandleChannelBindRequest(msg);
672 break;
673 default:
674 // Not sure what to do with this, just eat it.
675 LOG_J(LS_WARNING, this) << "Invalid TURN message type received: "
676 << msg->type();
677 }
678}
679
680void TurnServer::Allocation::HandleAllocateRequest(const TurnMessage* msg) {
681 // Copy the important info from the allocate request.
682 transaction_id_ = msg->transaction_id();
683 const StunByteStringAttribute* username_attr =
684 msg->GetByteString(STUN_ATTR_USERNAME);
685 ASSERT(username_attr != NULL);
686 username_ = username_attr->GetString();
687
688 // Figure out the lifetime and start the allocation timer.
689 int lifetime_secs = ComputeLifetime(msg);
690 thread_->PostDelayed(lifetime_secs * 1000, this, MSG_TIMEOUT);
691
692 LOG_J(LS_INFO, this) << "Created allocation, lifetime=" << lifetime_secs;
693
694 // We've already validated all the important bits; just send a response here.
695 TurnMessage response;
696 InitResponse(msg, &response);
697
698 StunAddressAttribute* mapped_addr_attr =
699 new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, conn_.src());
700 StunAddressAttribute* relayed_addr_attr =
701 new StunXorAddressAttribute(STUN_ATTR_XOR_RELAYED_ADDRESS,
702 external_socket_->GetLocalAddress());
703 StunUInt32Attribute* lifetime_attr =
704 new StunUInt32Attribute(STUN_ATTR_LIFETIME, lifetime_secs);
705 VERIFY(response.AddAttribute(mapped_addr_attr));
706 VERIFY(response.AddAttribute(relayed_addr_attr));
707 VERIFY(response.AddAttribute(lifetime_attr));
708
709 SendResponse(&response);
710}
711
712void TurnServer::Allocation::HandleRefreshRequest(const TurnMessage* msg) {
713 // Figure out the new lifetime.
714 int lifetime_secs = ComputeLifetime(msg);
715
716 // Reset the expiration timer.
717 thread_->Clear(this, MSG_TIMEOUT);
718 thread_->PostDelayed(lifetime_secs * 1000, this, MSG_TIMEOUT);
719
720 LOG_J(LS_INFO, this) << "Refreshed allocation, lifetime=" << lifetime_secs;
721
722 // Send a success response with a LIFETIME attribute.
723 TurnMessage response;
724 InitResponse(msg, &response);
725
726 StunUInt32Attribute* lifetime_attr =
727 new StunUInt32Attribute(STUN_ATTR_LIFETIME, lifetime_secs);
728 VERIFY(response.AddAttribute(lifetime_attr));
729
730 SendResponse(&response);
731}
732
733void TurnServer::Allocation::HandleSendIndication(const TurnMessage* msg) {
734 // Check mandatory attributes.
735 const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
736 const StunAddressAttribute* peer_attr =
737 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
738 if (!data_attr || !peer_attr) {
739 LOG_J(LS_WARNING, this) << "Received invalid send indication";
740 return;
741 }
742
743 // If a permission exists, send the data on to the peer.
744 if (HasPermission(peer_attr->GetAddress().ipaddr())) {
745 SendExternal(data_attr->bytes(), data_attr->length(),
746 peer_attr->GetAddress());
747 } else {
748 LOG_J(LS_WARNING, this) << "Received send indication without permission"
749 << "peer=" << peer_attr->GetAddress();
750 }
751}
752
753void TurnServer::Allocation::HandleCreatePermissionRequest(
754 const TurnMessage* msg) {
755 // Check mandatory attributes.
756 const StunAddressAttribute* peer_attr =
757 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
758 if (!peer_attr) {
759 SendBadRequestResponse(msg);
760 return;
761 }
762
763 // Add this permission.
764 AddPermission(peer_attr->GetAddress().ipaddr());
765
766 LOG_J(LS_INFO, this) << "Created permission, peer="
767 << peer_attr->GetAddress();
768
769 // Send a success response.
770 TurnMessage response;
771 InitResponse(msg, &response);
772 SendResponse(&response);
773}
774
775void TurnServer::Allocation::HandleChannelBindRequest(const TurnMessage* msg) {
776 // Check mandatory attributes.
777 const StunUInt32Attribute* channel_attr =
778 msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
779 const StunAddressAttribute* peer_attr =
780 msg->GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
781 if (!channel_attr || !peer_attr) {
782 SendBadRequestResponse(msg);
783 return;
784 }
785
786 // Check that channel id is valid.
787 int channel_id = channel_attr->value() >> 16;
788 if (channel_id < kMinChannelNumber || channel_id > kMaxChannelNumber) {
789 SendBadRequestResponse(msg);
790 return;
791 }
792
793 // Check that this channel id isn't bound to another transport address, and
794 // that this transport address isn't bound to another channel id.
795 Channel* channel1 = FindChannel(channel_id);
796 Channel* channel2 = FindChannel(peer_attr->GetAddress());
797 if (channel1 != channel2) {
798 SendBadRequestResponse(msg);
799 return;
800 }
801
802 // Add or refresh this channel.
803 if (!channel1) {
804 channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress());
805 channel1->SignalDestroyed.connect(this,
806 &TurnServer::Allocation::OnChannelDestroyed);
807 channels_.push_back(channel1);
808 } else {
809 channel1->Refresh();
810 }
811
812 // Channel binds also refresh permissions.
813 AddPermission(peer_attr->GetAddress().ipaddr());
814
815 LOG_J(LS_INFO, this) << "Bound channel, id=" << channel_id
816 << ", peer=" << peer_attr->GetAddress();
817
818 // Send a success response.
819 TurnMessage response;
820 InitResponse(msg, &response);
821 SendResponse(&response);
822}
823
824void TurnServer::Allocation::HandleChannelData(const char* data, size_t size) {
825 // Extract the channel number from the data.
826 uint16 channel_id = talk_base::GetBE16(data);
827 Channel* channel = FindChannel(channel_id);
828 if (channel) {
829 // Send the data to the peer address.
830 SendExternal(data + TURN_CHANNEL_HEADER_SIZE,
831 size - TURN_CHANNEL_HEADER_SIZE, channel->peer());
832 } else {
833 LOG_J(LS_WARNING, this) << "Received channel data for invalid channel, id="
834 << channel_id;
835 }
836}
837
838void TurnServer::Allocation::OnExternalPacket(
839 talk_base::AsyncPacketSocket* socket,
840 const char* data, size_t size,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000841 const talk_base::SocketAddress& addr,
842 const talk_base::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000843 ASSERT(external_socket_.get() == socket);
844 Channel* channel = FindChannel(addr);
845 if (channel) {
846 // There is a channel bound to this address. Send as a channel message.
847 talk_base::ByteBuffer buf;
848 buf.WriteUInt16(channel->id());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000849 buf.WriteUInt16(static_cast<uint16>(size));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000850 buf.WriteBytes(data, size);
851 server_->Send(&conn_, buf);
852 } else if (HasPermission(addr.ipaddr())) {
853 // No channel, but a permission exists. Send as a data indication.
854 TurnMessage msg;
855 msg.SetType(TURN_DATA_INDICATION);
856 msg.SetTransactionID(
857 talk_base::CreateRandomString(kStunTransactionIdLength));
858 VERIFY(msg.AddAttribute(new StunXorAddressAttribute(
859 STUN_ATTR_XOR_PEER_ADDRESS, addr)));
860 VERIFY(msg.AddAttribute(new StunByteStringAttribute(
861 STUN_ATTR_DATA, data, size)));
862 server_->SendStun(&conn_, &msg);
863 } else {
864 LOG_J(LS_WARNING, this) << "Received external packet without permission, "
865 << "peer=" << addr;
866 }
867}
868
869int TurnServer::Allocation::ComputeLifetime(const TurnMessage* msg) {
870 // Return the smaller of our default lifetime and the requested lifetime.
871 uint32 lifetime = kDefaultAllocationTimeout / 1000; // convert to seconds
872 const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME);
873 if (lifetime_attr && lifetime_attr->value() < lifetime) {
874 lifetime = lifetime_attr->value();
875 }
876 return lifetime;
877}
878
879bool TurnServer::Allocation::HasPermission(const talk_base::IPAddress& addr) {
880 return (FindPermission(addr) != NULL);
881}
882
883void TurnServer::Allocation::AddPermission(const talk_base::IPAddress& addr) {
884 Permission* perm = FindPermission(addr);
885 if (!perm) {
886 perm = new Permission(thread_, addr);
887 perm->SignalDestroyed.connect(
888 this, &TurnServer::Allocation::OnPermissionDestroyed);
889 perms_.push_back(perm);
890 } else {
891 perm->Refresh();
892 }
893}
894
895TurnServer::Permission* TurnServer::Allocation::FindPermission(
896 const talk_base::IPAddress& addr) const {
897 for (PermissionList::const_iterator it = perms_.begin();
898 it != perms_.end(); ++it) {
899 if ((*it)->peer() == addr)
900 return *it;
901 }
902 return NULL;
903}
904
905TurnServer::Channel* TurnServer::Allocation::FindChannel(int channel_id) const {
906 for (ChannelList::const_iterator it = channels_.begin();
907 it != channels_.end(); ++it) {
908 if ((*it)->id() == channel_id)
909 return *it;
910 }
911 return NULL;
912}
913
914TurnServer::Channel* TurnServer::Allocation::FindChannel(
915 const talk_base::SocketAddress& addr) const {
916 for (ChannelList::const_iterator it = channels_.begin();
917 it != channels_.end(); ++it) {
918 if ((*it)->peer() == addr)
919 return *it;
920 }
921 return NULL;
922}
923
924void TurnServer::Allocation::SendResponse(TurnMessage* msg) {
925 // Success responses always have M-I.
926 msg->AddMessageIntegrity(key_);
927 server_->SendStun(&conn_, msg);
928}
929
930void TurnServer::Allocation::SendBadRequestResponse(const TurnMessage* req) {
931 SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
932}
933
934void TurnServer::Allocation::SendErrorResponse(const TurnMessage* req, int code,
935 const std::string& reason) {
936 server_->SendErrorResponse(&conn_, req, code, reason);
937}
938
939void TurnServer::Allocation::SendExternal(const void* data, size_t size,
940 const talk_base::SocketAddress& peer) {
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000941 talk_base::PacketOptions options;
942 external_socket_->SendTo(data, size, peer, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943}
944
945void TurnServer::Allocation::OnMessage(talk_base::Message* msg) {
946 ASSERT(msg->message_id == MSG_TIMEOUT);
947 SignalDestroyed(this);
948 delete this;
949}
950
951void TurnServer::Allocation::OnPermissionDestroyed(Permission* perm) {
952 PermissionList::iterator it = std::find(perms_.begin(), perms_.end(), perm);
953 ASSERT(it != perms_.end());
954 perms_.erase(it);
955}
956
957void TurnServer::Allocation::OnChannelDestroyed(Channel* channel) {
958 ChannelList::iterator it =
959 std::find(channels_.begin(), channels_.end(), channel);
960 ASSERT(it != channels_.end());
961 channels_.erase(it);
962}
963
964TurnServer::Permission::Permission(talk_base::Thread* thread,
965 const talk_base::IPAddress& peer)
966 : thread_(thread), peer_(peer) {
967 Refresh();
968}
969
970TurnServer::Permission::~Permission() {
971 thread_->Clear(this, MSG_TIMEOUT);
972}
973
974void TurnServer::Permission::Refresh() {
975 thread_->Clear(this, MSG_TIMEOUT);
976 thread_->PostDelayed(kPermissionTimeout, this, MSG_TIMEOUT);
977}
978
979void TurnServer::Permission::OnMessage(talk_base::Message* msg) {
980 ASSERT(msg->message_id == MSG_TIMEOUT);
981 SignalDestroyed(this);
982 delete this;
983}
984
985TurnServer::Channel::Channel(talk_base::Thread* thread, int id,
986 const talk_base::SocketAddress& peer)
987 : thread_(thread), id_(id), peer_(peer) {
988 Refresh();
989}
990
991TurnServer::Channel::~Channel() {
992 thread_->Clear(this, MSG_TIMEOUT);
993}
994
995void TurnServer::Channel::Refresh() {
996 thread_->Clear(this, MSG_TIMEOUT);
997 thread_->PostDelayed(kChannelTimeout, this, MSG_TIMEOUT);
998}
999
1000void TurnServer::Channel::OnMessage(talk_base::Message* msg) {
1001 ASSERT(msg->message_id == MSG_TIMEOUT);
1002 SignalDestroyed(this);
1003 delete this;
1004}
1005
1006} // namespace cricket