Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / p2p / base / turnserver.cc
index abc065a..dbcbcd4 100644 (file)
@@ -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;
 }