summaryrefslogtreecommitdiff
path: root/p2p/base/turnserver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'p2p/base/turnserver.cc')
-rw-r--r--p2p/base/turnserver.cc56
1 files changed, 39 insertions, 17 deletions
diff --git a/p2p/base/turnserver.cc b/p2p/base/turnserver.cc
index abc065a..dbcbcd4 100644
--- a/p2p/base/turnserver.cc
+++ b/p2p/base/turnserver.cc
@@ -62,9 +62,9 @@ inline bool IsTurnChannelData(uint16 msg_type) {
return ((msg_type & 0xC000) == 0x4000);
}
-// IDs used for posted messages.
+// IDs used for posted messages for TurnServer::Allocation.
enum {
- MSG_TIMEOUT,
+ MSG_ALLOCATION_TIMEOUT,
};
// Encapsulates a TURN allocation.
@@ -208,6 +208,7 @@ TurnServer::TurnServer(rtc::Thread* thread)
: thread_(thread),
nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
auth_hook_(NULL),
+ redirect_hook_(NULL),
enable_otu_nonce_(false) {
}
@@ -316,6 +317,15 @@ void TurnServer::HandleStunMessage(Connection* conn, const char* data,
return;
}
+ if (redirect_hook_ != NULL && msg.type() == STUN_ALLOCATE_REQUEST) {
+ rtc::SocketAddress address;
+ if (redirect_hook_->ShouldRedirect(conn->src(), &address)) {
+ SendErrorResponseWithAlternateServer(
+ conn, &msg, address);
+ return;
+ }
+ }
+
// Look up the key that we'll use to validate the M-I. If we have an
// existing allocation, the key will already be cached.
Allocation* allocation = FindAllocation(conn);
@@ -334,7 +344,6 @@ void TurnServer::HandleStunMessage(Connection* conn, const char* data,
}
if (!allocation && msg.type() == STUN_ALLOCATE_REQUEST) {
- // This is a new allocate request.
HandleAllocateRequest(conn, &msg, key);
} else if (allocation &&
(msg.type() != STUN_ALLOCATE_REQUEST ||
@@ -551,6 +560,17 @@ void TurnServer::SendErrorResponseWithRealmAndNonce(
SendStun(conn, &resp);
}
+void TurnServer::SendErrorResponseWithAlternateServer(
+ Connection* conn, const StunMessage* msg,
+ const rtc::SocketAddress& addr) {
+ TurnMessage resp;
+ InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
+ STUN_ERROR_REASON_TRY_ALTERNATE_SERVER, &resp);
+ VERIFY(resp.AddAttribute(new StunAddressAttribute(
+ STUN_ATTR_ALTERNATE_SERVER, addr)));
+ SendStun(conn, &resp);
+}
+
void TurnServer::SendStun(Connection* conn, StunMessage* msg) {
rtc::ByteBuffer buf;
// Add a SOFTWARE attribute if one is set.
@@ -588,7 +608,9 @@ void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) {
InternalSocketMap::iterator iter = server_sockets_.find(socket);
if (iter != server_sockets_.end()) {
rtc::AsyncPacketSocket* socket = iter->first;
- delete socket;
+ // We must destroy the socket async to avoid invalidating the sigslot
+ // callback list iterator inside a sigslot callback.
+ rtc::Thread::Current()->Dispose(socket);
server_sockets_.erase(iter);
}
}
@@ -642,7 +664,7 @@ TurnServer::Allocation::~Allocation() {
it != perms_.end(); ++it) {
delete *it;
}
- thread_->Clear(this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
LOG_J(LS_INFO, this) << "Allocation destroyed";
}
@@ -687,7 +709,7 @@ void TurnServer::Allocation::HandleAllocateRequest(const TurnMessage* msg) {
// Figure out the lifetime and start the allocation timer.
int lifetime_secs = ComputeLifetime(msg);
- thread_->PostDelayed(lifetime_secs * 1000, this, MSG_TIMEOUT);
+ thread_->PostDelayed(lifetime_secs * 1000, this, MSG_ALLOCATION_TIMEOUT);
LOG_J(LS_INFO, this) << "Created allocation, lifetime=" << lifetime_secs;
@@ -714,8 +736,8 @@ void TurnServer::Allocation::HandleRefreshRequest(const TurnMessage* msg) {
int lifetime_secs = ComputeLifetime(msg);
// Reset the expiration timer.
- thread_->Clear(this, MSG_TIMEOUT);
- thread_->PostDelayed(lifetime_secs * 1000, this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
+ thread_->PostDelayed(lifetime_secs * 1000, this, MSG_ALLOCATION_TIMEOUT);
LOG_J(LS_INFO, this) << "Refreshed allocation, lifetime=" << lifetime_secs;
@@ -943,7 +965,7 @@ void TurnServer::Allocation::SendExternal(const void* data, size_t size,
}
void TurnServer::Allocation::OnMessage(rtc::Message* msg) {
- ASSERT(msg->message_id == MSG_TIMEOUT);
+ ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
SignalDestroyed(this);
delete this;
}
@@ -968,16 +990,16 @@ TurnServer::Permission::Permission(rtc::Thread* thread,
}
TurnServer::Permission::~Permission() {
- thread_->Clear(this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Permission::Refresh() {
- thread_->Clear(this, MSG_TIMEOUT);
- thread_->PostDelayed(kPermissionTimeout, this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
+ thread_->PostDelayed(kPermissionTimeout, this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Permission::OnMessage(rtc::Message* msg) {
- ASSERT(msg->message_id == MSG_TIMEOUT);
+ ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
SignalDestroyed(this);
delete this;
}
@@ -989,16 +1011,16 @@ TurnServer::Channel::Channel(rtc::Thread* thread, int id,
}
TurnServer::Channel::~Channel() {
- thread_->Clear(this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Channel::Refresh() {
- thread_->Clear(this, MSG_TIMEOUT);
- thread_->PostDelayed(kChannelTimeout, this, MSG_TIMEOUT);
+ thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
+ thread_->PostDelayed(kChannelTimeout, this, MSG_ALLOCATION_TIMEOUT);
}
void TurnServer::Channel::OnMessage(rtc::Message* msg) {
- ASSERT(msg->message_id == MSG_TIMEOUT);
+ ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
SignalDestroyed(this);
delete this;
}