1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/* 2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * Copyright 2012 The WebRTC Project Authors. All rights reserved. 3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * 4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * Use of this source code is governed by a BSD-style license 5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * in the file PATENTS. All contributing project authors may 8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */ 10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/turnport.h" 12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 13269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include <functional> 14269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/common.h" 16269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/stun.h" 17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/asyncpacketsocket.h" 18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/byteorder.h" 19269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/common.h" 20269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h" 21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/nethelpers.h" 22269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/socketaddress.h" 23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/stringencode.h" 24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace cricket { 26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 27269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// TODO(juberti): Move to stun.h when relay messages have been renamed. 28269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int TURN_ALLOCATE_REQUEST = STUN_ALLOCATE_REQUEST; 29269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 30269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// TODO(juberti): Extract to turnmessage.h 31269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int TURN_DEFAULT_PORT = 3478; 32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int TURN_CHANNEL_NUMBER_START = 0x4000; 33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000; // 5 minutes 34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const size_t TURN_CHANNEL_HEADER_SIZE = 4U; 36269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 37269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Retry at most twice (i.e. three different ALLOCATE requests) on 38269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// STUN_ERROR_ALLOCATION_MISMATCH error per rfc5766. 39269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic const size_t MAX_ALLOCATE_MISMATCH_RETRIES = 2; 40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 41f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhangstatic const int TURN_SUCCESS_RESULT_CODE = 0; 42f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang 430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströminline bool IsTurnChannelData(uint16_t msg_type) { 44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return ((msg_type & 0xC000) == 0x4000); // MSB are 0b01 45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 47269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic int GetRelayPreference(cricket::ProtocolType proto, bool secure) { 48269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int relay_preference = ICE_TYPE_PREFERENCE_RELAY; 49269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (proto == cricket::PROTO_TCP) { 50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org relay_preference -= 1; 51269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (secure) 52269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org relay_preference -= 1; 53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(relay_preference >= 0); 56269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return relay_preference; 57269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 58269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TurnAllocateRequest : public StunRequest { 60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public: 61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org explicit TurnAllocateRequest(TurnPort* port); 621cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void Prepare(StunMessage* request) override; 631cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnSent() override; 641cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnResponse(StunMessage* response) override; 651cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnErrorResponse(StunMessage* response) override; 661cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnTimeout() override; 67269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 68269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private: 69269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Handles authentication challenge from the server. 70269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnAuthChallenge(StunMessage* response, int code); 71269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnTryAlternate(StunMessage* response, int code); 72269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnUnknownAttribute(StunMessage* response); 73269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 74269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port_; 75269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}; 76269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 77269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TurnRefreshRequest : public StunRequest { 78269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public: 79269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org explicit TurnRefreshRequest(TurnPort* port); 801cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void Prepare(StunMessage* request) override; 811cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnSent() override; 821cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnResponse(StunMessage* response) override; 831cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnErrorResponse(StunMessage* response) override; 841cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnTimeout() override; 85fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org void set_lifetime(int lifetime) { lifetime_ = lifetime; } 86269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 87269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private: 88269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port_; 89fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org int lifetime_; 90269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}; 91269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 92269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TurnCreatePermissionRequest : public StunRequest, 93269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public sigslot::has_slots<> { 94269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public: 95269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnCreatePermissionRequest(TurnPort* port, TurnEntry* entry, 96269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& ext_addr); 971cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void Prepare(StunMessage* request) override; 981cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnSent() override; 991cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnResponse(StunMessage* response) override; 1001cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnErrorResponse(StunMessage* response) override; 1011cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnTimeout() override; 102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private: 104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnEntryDestroyed(TurnEntry* entry); 105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port_; 107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnEntry* entry_; 108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress ext_addr_; 109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}; 110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TurnChannelBindRequest : public StunRequest, 112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public sigslot::has_slots<> { 113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public: 114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnChannelBindRequest(TurnPort* port, TurnEntry* entry, int channel_id, 115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& ext_addr); 1161cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void Prepare(StunMessage* request) override; 1171cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnSent() override; 1181cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnResponse(StunMessage* response) override; 1191cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnErrorResponse(StunMessage* response) override; 1201cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher void OnTimeout() override; 121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private: 123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnEntryDestroyed(TurnEntry* entry); 124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port_; 126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnEntry* entry_; 127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int channel_id_; 128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress ext_addr_; 129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}; 130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Manages a "connection" to a remote destination. We will attempt to bring up 132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// a channel for this remote destination to reduce the overhead of sending data. 133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgclass TurnEntry : public sigslot::has_slots<> { 134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org public: 135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND }; 136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnEntry(TurnPort* port, int channel_id, 137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& ext_addr); 138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port() { return port_; } 140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int channel_id() const { return channel_id_; } 142f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // For testing only. 143f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang void set_channel_id(int channel_id) { channel_id_ = channel_id; } 144f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang 145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& address() const { return ext_addr_; } 146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org BindState state() const { return state_; } 147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 14832f39968ce79cfca5146069e410ded2f104bba23honghaiz uint32_t destruction_timestamp() { return destruction_timestamp_; } 14932f39968ce79cfca5146069e410ded2f104bba23honghaiz void set_destruction_timestamp(uint32_t destruction_timestamp) { 15032f39968ce79cfca5146069e410ded2f104bba23honghaiz destruction_timestamp_ = destruction_timestamp; 15132f39968ce79cfca5146069e410ded2f104bba23honghaiz } 15232f39968ce79cfca5146069e410ded2f104bba23honghaiz 153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Helper methods to send permission and channel bind requests. 1548597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang void SendCreatePermissionRequest(int delay); 155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void SendChannelBindRequest(int delay); 156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Sends a packet to the given destination address. 157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // This will wrap the packet in STUN if necessary. 158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int Send(const void* data, size_t size, bool payload, 159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketOptions& options); 160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnCreatePermissionSuccess(); 162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnCreatePermissionError(StunMessage* response, int code); 163f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang void OnCreatePermissionTimeout(); 164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnChannelBindSuccess(); 165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org void OnChannelBindError(StunMessage* response, int code); 166f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang void OnChannelBindTimeout(); 167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Signal sent when TurnEntry is destroyed. 168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org sigslot::signal1<TurnEntry*> SignalDestroyed; 169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org private: 171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port_; 172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int channel_id_; 173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress ext_addr_; 174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org BindState state_; 17532f39968ce79cfca5146069e410ded2f104bba23honghaiz // A non-zero value indicates that this entry is scheduled to be destroyed. 17632f39968ce79cfca5146069e410ded2f104bba23honghaiz // It is also used as an ID of the event scheduling. When the destruction 17732f39968ce79cfca5146069e410ded2f104bba23honghaiz // event actually fires, the TurnEntry will be destroyed only if the 17832f39968ce79cfca5146069e410ded2f104bba23honghaiz // timestamp here matches the one in the firing event. 17932f39968ce79cfca5146069e410ded2f104bba23honghaiz uint32_t destruction_timestamp_ = 0; 180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}; 181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnPort::TurnPort(rtc::Thread* thread, 183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketSocketFactory* factory, 184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::Network* network, 185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::AsyncPacketSocket* socket, 186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const std::string& username, 187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const std::string& password, 188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const ProtocolAddress& server_address, 189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const RelayCredentials& credentials, 1900ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org int server_priority, 1910ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org const std::string& origin) 192b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz : Port(thread, 193b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz factory, 194b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz network, 195b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz socket->GetLocalAddress().ipaddr(), 196b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz username, 197b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz password), 198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_(server_address), 199269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org credentials_(credentials), 200269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_(socket), 201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_(NULL), 202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_(0), 203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request_manager_(thread), 204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org next_channel_number_(TURN_CHANNEL_NUMBER_START), 205b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz state_(STATE_CONNECTING), 206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_priority_(server_priority), 207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org allocate_mismatch_retries_(0) { 208269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket); 2090ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org request_manager_.set_origin(origin); 210269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 211269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnPort::TurnPort(rtc::Thread* thread, 213269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketSocketFactory* factory, 214269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::Network* network, 215269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::IPAddress& ip, 2160c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint16_t min_port, 2170c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint16_t max_port, 218269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const std::string& username, 219269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const std::string& password, 220269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const ProtocolAddress& server_address, 221269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const RelayCredentials& credentials, 2220ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org int server_priority, 2230ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org const std::string& origin) 224b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz : Port(thread, 225b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz RELAY_PORT_TYPE, 226b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz factory, 227b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz network, 228b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz ip, 229b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz min_port, 230b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz max_port, 231b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz username, 232b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz password), 233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_(server_address), 234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org credentials_(credentials), 235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_(NULL), 236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_(NULL), 237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_(0), 238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request_manager_(thread), 239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org next_channel_number_(TURN_CHANNEL_NUMBER_START), 240b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz state_(STATE_CONNECTING), 241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_priority_(server_priority), 242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org allocate_mismatch_retries_(0) { 243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket); 2440ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org request_manager_.set_origin(origin); 245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnPort::~TurnPort() { 248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // TODO(juberti): Should this even be necessary? 249fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org 250fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org // release the allocation by sending a refresh with 251fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org // lifetime 0. 252b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz if (ready()) { 253fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org TurnRefreshRequest bye(this); 254fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org bye.set_lifetime(0); 255fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org SendRequest(&bye, 0); 256fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org } 257fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org 258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org while (!entries_.empty()) { 25932f39968ce79cfca5146069e410ded2f104bba23honghaiz DestroyEntry(entries_.front()); 260269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 261269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (resolver_) { 262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_->Destroy(false); 263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!SharedSocket()) { 265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org delete socket_; 266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 268269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 2690ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.orgrtc::SocketAddress TurnPort::GetLocalAddress() const { 2700ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org return socket_ ? socket_->GetLocalAddress() : rtc::SocketAddress(); 2710ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org} 2720ba1533fdbe4a098723da8262f1374d71c3a1806pthatcher@webrtc.org 273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::PrepareAddress() { 274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (credentials_.username.empty() || 275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org credentials_.password.empty()) { 276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Allocation can't be started without setting the" 277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " TURN server credentials for the user."; 278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!server_address_.address.port()) { 283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // We will set default TURN port, if no port is set in the address. 284269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_.address.SetPort(TURN_DEFAULT_PORT); 285269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 286269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 28720a34619080005c3b0e49d85b307113ea2b180c3tfarina if (server_address_.address.IsUnresolvedIP()) { 288269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ResolveTurnAddress(server_address_.address); 289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If protocol family of server address doesn't match with local, return. 291269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!IsCompatibleAddress(server_address_.address)) { 292b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz LOG(LS_ERROR) << "IP address family does not match: " 293b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz << "server: " << server_address_.address.family() 294b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz << "local: " << ip().family(); 295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Insert the current address to prevent redirection pingpong. 300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org attempted_server_addresses_.insert(server_address_.address); 301269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 302269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, this) << "Trying to connect to TURN server via " 303269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << ProtoToString(server_address_.proto) << " @ " 304269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << server_address_.address.ToSensitiveString(); 305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!CreateTurnClientSocket()) { 306b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz LOG(LS_ERROR) << "Failed to create TURN client socket"; 307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 308b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz return; 309b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz } 310b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz if (server_address_.proto == PROTO_UDP) { 311269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If its UDP, send AllocateRequest now. 312269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // For TCP and TLS AllcateRequest will be sent by OnSocketConnect. 313269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendRequest(new TurnAllocateRequest(this), 0); 314269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 315269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 316269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool TurnPort::CreateTurnClientSocket() { 319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(!socket_ || SharedSocket()); 320269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_address_.proto == PROTO_UDP && !SharedSocket()) { 322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_ = socket_factory()->CreateUdpSocket( 323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress(ip(), 0), min_port(), max_port()); 324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else if (server_address_.proto == PROTO_TCP) { 325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(!SharedSocket()); 326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int opts = rtc::PacketSocketFactory::OPT_STUN; 327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If secure bit is enabled in server address, use TLS over TCP. 328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_address_.secure) { 329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org opts |= rtc::PacketSocketFactory::OPT_TLS; 330269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_ = socket_factory()->CreateClientTcpSocket( 332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress(ip(), 0), server_address_.address, 333269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org proxy(), user_agent(), opts); 334269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 336269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!socket_) { 337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_ = SOCKET_ERROR; 338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 339269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 340269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 341269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Apply options if any. 342269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org for (SocketOptionsMap::iterator iter = socket_options_.begin(); 343269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org iter != socket_options_.end(); ++iter) { 344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SetOption(iter->first, iter->second); 345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 346269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 347269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!SharedSocket()) { 348269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If socket is shared, AllocationSequence will receive the packet. 349269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket); 350269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 351269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend); 353269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 35455674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer socket_->SignalSentPacket.connect(this, &TurnPort::OnSentPacket); 35555674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer 356b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz // TCP port is ready to send stun requests after the socket is connected, 357b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz // while UDP port is ready to do so once the socket is created. 358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (server_address_.proto == PROTO_TCP) { 359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect); 360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_->SignalClose.connect(this, &TurnPort::OnSocketClose); 361b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz } else { 362b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz state_ = STATE_CONNECTED; 363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 364269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return true; 365269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 366269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) { 368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(server_address_.proto == PROTO_TCP); 369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Do not use this port if the socket bound to a different address than 370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // the one we asked for. This is seen in Chrome, where TCP sockets cannot be 371269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // given a binding address, and the platform is expected to pick the 372269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // correct local address. 3734fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org 3747f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh // However, there are two situations in which we allow the bound address to 3757f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh // differ from the requested address: 1. The bound address is the loopback 3767f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh // address. This happens when a proxy forces TCP to bind to only the 3777f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh // localhost address (see issue 3927). 2. The bound address is the "any 3787f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh // address". This happens when multiple_routes is disabled (see issue 4780). 379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (socket->GetLocalAddress().ipaddr() != ip()) { 3804fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org if (socket->GetLocalAddress().IsLoopbackIP()) { 3814fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org LOG(LS_WARNING) << "Socket is bound to a different address:" 3824fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org << socket->GetLocalAddress().ipaddr().ToString() 3834fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org << ", rather then the local port:" << ip().ToString() 3844fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org << ". Still allowing it since it's localhost."; 3857f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh } else if (IPIsAny(ip())) { 3867f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh LOG(LS_WARNING) << "Socket is bound to a different address:" 3877f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh << socket->GetLocalAddress().ipaddr().ToString() 3887f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh << ", rather then the local port:" << ip().ToString() 3897f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh << ". Still allowing it since it's any address" 3907f04b08d3b31c732c66965a09803f6c3e4210a65Guo-wei Shieh << ", possibly caused by multiple_routes being disabled."; 3914fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org } else { 3924fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org LOG(LS_WARNING) << "Socket is bound to a different address:" 3934fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org << socket->GetLocalAddress().ipaddr().ToString() 3944fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org << ", rather then the local port:" << ip().ToString() 3954fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org << ". Discarding TURN port."; 3964fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org OnAllocateError(); 3974fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org return; 3984fba293c87c366a3fd38ea94e88c3d38021f0dfaguoweis@webrtc.org } 399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 401b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz state_ = STATE_CONNECTED; // It is ready to send stun requests. 40220a34619080005c3b0e49d85b307113ea2b180c3tfarina if (server_address_.address.IsUnresolvedIP()) { 403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_.address = socket_->GetRemoteAddress(); 404269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 405269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 406269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress() 407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " using tcp."; 408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendRequest(new TurnAllocateRequest(this), 0); 409269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 411269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) { 412269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error; 41319e4e8d751478d34c05bc2d73e065429ed65a1c1guoweis@webrtc.org ASSERT(socket == socket_); 4146b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz Close(); 415269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 416269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 417269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnAllocateMismatch() { 418269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) { 419269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Giving up on the port after " 420269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << allocate_mismatch_retries_ 421269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " retries for STUN_ERROR_ALLOCATION_MISMATCH"; 422269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 423269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 424269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 425269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 426269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, this) << "Allocating a new socket after " 427269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "STUN_ERROR_ALLOCATION_MISMATCH, retry = " 428269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << allocate_mismatch_retries_ + 1; 429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (SharedSocket()) { 430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ResetSharedSocket(); 431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org delete socket_; 433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_ = NULL; 435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org PrepareAddress(); 437269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ++allocate_mismatch_retries_; 438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgConnection* TurnPort::CreateConnection(const Candidate& address, 441269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org CandidateOrigin origin) { 442269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // TURN-UDP can only connect to UDP candidates. 443f9945b2d1aa2d78b19987219ea872605167d7b5fHonghai Zhang if (!SupportsProtocol(address.protocol())) { 444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return NULL; 445269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 446269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 447269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!IsCompatibleAddress(address.address())) { 448269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return NULL; 449269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 450269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 451b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz if (state_ == STATE_DISCONNECTED) { 452b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz return NULL; 453b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz } 454b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz 455269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Create an entry, if needed, so we can get our permissions set up correctly. 45632f39968ce79cfca5146069e410ded2f104bba23honghaiz CreateOrRefreshEntry(address.address()); 457269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 458269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // A TURN port will have two candiates, STUN and TURN. STUN may not 459269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // present in all cases. If present stun candidate will be added first 460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // and TURN candidate later. 461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org for (size_t index = 0; index < Candidates().size(); ++index) { 462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (Candidates()[index].type() == RELAY_PORT_TYPE) { 463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ProxyConnection* conn = new ProxyConnection(this, index, address); 464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed); 465269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org AddConnection(conn); 466269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return conn; 467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 468269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 469269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return NULL; 470269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 471269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 472f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhangbool TurnPort::DestroyConnection(const rtc::SocketAddress& address) { 473f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang Connection* conn = GetConnection(address); 474f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang if (conn != nullptr) { 475f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang conn->Destroy(); 476f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang return true; 477f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } 478f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang return false; 479f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang} 480f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang 481269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint TurnPort::SetOption(rtc::Socket::Option opt, int value) { 482269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!socket_) { 483269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If socket is not created yet, these options will be applied during socket 484269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // creation. 485269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org socket_options_[opt] = value; 486269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return 0; 487269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 488269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return socket_->SetOption(opt, value); 489269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 490269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 491269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint TurnPort::GetOption(rtc::Socket::Option opt, int* value) { 492269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!socket_) { 493269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SocketOptionsMap::const_iterator it = socket_options_.find(opt); 494269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (it == socket_options_.end()) { 495269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return -1; 496269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 497269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *value = it->second; 498269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return 0; 499269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 500269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 501269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return socket_->GetOption(opt, value); 502269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 503269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 504269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint TurnPort::GetError() { 505269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return error_; 506269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 507269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 508269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint TurnPort::SendTo(const void* data, size_t size, 509269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& addr, 510269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketOptions& options, 511269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org bool payload) { 512269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Try to find an entry for this specific address; we should have one. 513269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnEntry* entry = FindEntry(addr); 514269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!entry) { 515b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz LOG(LS_ERROR) << "Did not find the TurnEntry for address " << addr; 516269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return 0; 517269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 518269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 519b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz if (!ready()) { 520269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_ = EWOULDBLOCK; 521269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return SOCKET_ERROR; 522269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 523269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 524269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Send the actual contents to the server using the usual mechanism. 525269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int sent = entry->Send(data, size, payload, options); 526269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (sent <= 0) { 527269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return SOCKET_ERROR; 528269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 529269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 530269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // The caller of the function is expecting the number of user data bytes, 531269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // rather than the size of the packet. 532269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return static_cast<int>(size); 533269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 534269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 535269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnReadPacket( 536269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::AsyncPacketSocket* socket, const char* data, size_t size, 537269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& remote_addr, 538269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketTime& packet_time) { 539269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(socket == socket_); 540c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org 541c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org // This is to guard against a STUN response from previous server after 542c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org // alternative server redirection. TODO(guoweis): add a unit test for this 543c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org // race condition. 544c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org if (remote_addr != server_address_.address) { 545c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org LOG_J(LS_WARNING, this) << "Discarding TURN message from unknown address:" 546c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org << remote_addr.ToString() 547c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org << ", server_address_:" 548c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org << server_address_.address.ToString(); 549c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org return; 550c51fb9348df603f64dc37c88cb973cfed84394f7guoweis@webrtc.org } 551269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 552269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // The message must be at least the size of a channel header. 553269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (size < TURN_CHANNEL_HEADER_SIZE) { 554269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received TURN message that was too short"; 555269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 556269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 557269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 558269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check the message type, to see if is a Channel Data message. 559269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // The message will either be channel data, a TURN data indication, or 560269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // a response to a previous request. 5610c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint16_t msg_type = rtc::GetBE16(data); 562269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (IsTurnChannelData(msg_type)) { 563269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org HandleChannelData(msg_type, data, size, packet_time); 564269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else if (msg_type == TURN_DATA_INDICATION) { 565269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org HandleDataIndication(data, size, packet_time); 566269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 567511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org if (SharedSocket() && 568511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org (msg_type == STUN_BINDING_RESPONSE || 569511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org msg_type == STUN_BINDING_ERROR_RESPONSE)) { 570511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org LOG_J(LS_VERBOSE, this) << 571511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org "Ignoring STUN binding response message on shared socket."; 572511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org return; 573511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org } 574511f8a8ef2242781d1541daf4854910229690bf8jiayl@webrtc.org 575269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // This must be a response for one of our requests. 576269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check success responses, but not errors, for MESSAGE-INTEGRITY. 577269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (IsStunSuccessResponseType(msg_type) && 578269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org !StunMessage::ValidateMessageIntegrity(data, size, hash())) { 579269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received TURN message with invalid " 580269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "message integrity, msg_type=" << msg_type; 581269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 582269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 583269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request_manager_.CheckResponse(data, size); 584269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 585269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 586269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 58755674ffb32307c6f3efaab442340d3c5c075073bStefan Holmervoid TurnPort::OnSentPacket(rtc::AsyncPacketSocket* socket, 58855674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer const rtc::SentPacket& sent_packet) { 58955674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer PortInterface::SignalSentPacket(sent_packet); 59055674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer} 59155674ffb32307c6f3efaab442340d3c5c075073bStefan Holmer 592269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) { 593b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz if (ready()) { 594269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org Port::OnReadyToSend(); 595269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 596269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 597269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 598269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 599269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Update current server address port with the alternate server address port. 600269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) { 601269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check if we have seen this address before and reject if we did. 602269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address); 603269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (iter != attempted_server_addresses_.end()) { 604269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Redirection to [" 605269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << address.ToSensitiveString() 606269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "] ignored, allocation failed."; 607269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 608269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 609269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 610269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If protocol family of server address doesn't match with local, return. 611269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!IsCompatibleAddress(address)) { 612269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_WARNING) << "Server IP address family does not match with " 613269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "local host address family type"; 614269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 615269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 616269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 617269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, this) << "Redirecting from TURN server [" 618269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << server_address_.address.ToSensitiveString() 619269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "] to TURN server [" 620269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << address.ToSensitiveString() 621269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "]"; 622269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_ = ProtocolAddress(address, server_address_.proto, 623269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_.secure); 624269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 625269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Insert the current address to prevent redirection pingpong. 626269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org attempted_server_addresses_.insert(server_address_.address); 627269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return true; 628269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 629269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 630269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) { 631269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (resolver_) 632269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 633269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 6340f490a5b8609c1f10dba37d7a7b0b2fc055543ebHonghai Zhang LOG_J(LS_INFO, this) << "Starting TURN host lookup for " 6350f490a5b8609c1f10dba37d7a7b0b2fc055543ebHonghai Zhang << address.ToSensitiveString(); 636269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_ = socket_factory()->CreateAsyncResolver(); 637269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult); 638269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolver_->Start(address); 639269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 640269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 641269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnResolveResult(rtc::AsyncResolverInterface* resolver) { 642269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(resolver == resolver_); 643269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If DNS resolve is failed when trying to connect to the server using TCP, 644269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // one of the reason could be due to DNS queries blocked by firewall. 645269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // In such cases we will try to connect to the server with hostname, assuming 646269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // socket layer will resolve the hostname through a HTTP proxy (if any). 647269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (resolver_->GetError() != 0 && server_address_.proto == PROTO_TCP) { 648269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!CreateTurnClientSocket()) { 649269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 650269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 651269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 652269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 653269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 654269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Copy the original server address in |resolved_address|. For TLS based 655269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // sockets we need hostname along with resolved address. 656269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress resolved_address = server_address_.address; 657269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (resolver_->GetError() != 0 || 658269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org !resolver_->GetResolvedAddress(ip().family(), &resolved_address)) { 659269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "TURN host lookup received error " 660269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << resolver_->GetError(); 661269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org error_ = resolver_->GetError(); 662269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 663269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 664269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 665269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Signal needs both resolved and unresolved address. After signal is sent 666269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // we can copy resolved address back into |server_address_|. 667269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SignalResolvedServerAddress(this, server_address_.address, 668269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org resolved_address); 669269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org server_address_.address = resolved_address; 670269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org PrepareAddress(); 671269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 672269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 673269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnSendStunPacket(const void* data, size_t size, 674269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org StunRequest* request) { 675b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz ASSERT(connected()); 676269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::PacketOptions options(DefaultDscpValue()); 677269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (Send(data, size, options) < 0) { 678269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_ERROR, this) << "Failed to send TURN message, err=" 679269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << socket_->GetError(); 680269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 681269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 682269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 683269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnStunAddress(const rtc::SocketAddress& address) { 684269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // STUN Port will discover STUN candidate, as it's supplied with first TURN 685269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // server address. 686269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Why not using this address? - P2PTransportChannel will start creating 687269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // connections after first candidate, which means it could start creating the 688269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // connections before TURN candidate added. For that to handle, we need to 689269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // supply STUN candidate from this port to UDPPort, and TurnPort should have 690269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // handle to UDPPort to pass back the address. 691269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 692269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 693269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address, 694269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& stun_address) { 695b19eba3d4bbc70ece91d524e21e2e9d4253ff7a9honghaiz state_ = STATE_READY; 696269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 697269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress related_address = stun_address; 698269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!(candidate_filter() & CF_REFLEXIVE)) { 699269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If candidate filter only allows relay type of address, empty raddr to 700269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // avoid local address leakage. 701269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org related_address = rtc::EmptySocketAddressWithFamily(stun_address.family()); 702269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 703269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 704269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // For relayed candidate, Base is the candidate itself. 705269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org AddAddress(address, // Candidate address. 706269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org address, // Base address. 707269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org related_address, // Related address. 708269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org UDP_PROTOCOL_NAME, 7093d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh ProtoToString(server_address_.proto), // The first hop protocol. 710269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org "", // TCP canddiate type, empty for turn candidates. 711269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org RELAY_PORT_TYPE, 712269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org GetRelayPreference(server_address_.proto, server_address_.secure), 7133d564c10157d7de1d2d4236f4e2a13ff1363d52bGuo-wei Shieh server_priority_, true); 714269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 715269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 716269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnAllocateError() { 717269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // We will send SignalPortError asynchronously as this can be sent during 718269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // port initialization. This way it will not be blocking other port 719269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // creation. 720f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang thread()->Post(this, MSG_ALLOCATE_ERROR); 721f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang} 722f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang 7236b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaizvoid TurnPort::OnTurnRefreshError() { 7246b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz // Need to Close the port asynchronously because otherwise, the refresh 7256b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz // request may be deleted twice: once at the end of the message processing 7266b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz // and the other in Close(). 7276b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz thread()->Post(this, MSG_REFRESH_ERROR); 7286b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz} 7296b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz 730f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhangvoid TurnPort::Close() { 7316b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz if (!ready()) { 7326b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz OnAllocateError(); 7336b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz } 7346b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz request_manager_.Clear(); 735f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // Stop the port from creating new connections. 736f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang state_ = STATE_DISCONNECTED; 737f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // Delete all existing connections; stop sending data. 738f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang for (auto kv : connections()) { 739f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang kv.second->Destroy(); 740f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } 741269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 742269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 743269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnMessage(rtc::Message* message) { 744f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang switch (message->message_id) { 745f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang case MSG_ALLOCATE_ERROR: 746f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang SignalPortError(this); 747f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang break; 748f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang case MSG_ALLOCATE_MISMATCH: 749f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang OnAllocateMismatch(); 750f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang break; 7516b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz case MSG_REFRESH_ERROR: 7526b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz Close(); 7536b9ab9204b9e0891cb0be2595a0d7ada92945ceahonghaiz break; 754f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang case MSG_TRY_ALTERNATE_SERVER: 755f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang if (server_address().proto == PROTO_UDP) { 756f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // Send another allocate request to alternate server, with the received 757f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // realm and nonce values. 758f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang SendRequest(new TurnAllocateRequest(this), 0); 759f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } else { 760f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // Since it's TCP, we have to delete the connected socket and reconnect 761f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // with the alternate server. PrepareAddress will send stun binding once 762f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // the new socket is connected. 763f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang ASSERT(server_address().proto == PROTO_TCP); 764f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang ASSERT(!SharedSocket()); 765f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang delete socket_; 766f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang socket_ = NULL; 767f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang PrepareAddress(); 768f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } 769f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang break; 770f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang default: 771f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang Port::OnMessage(message); 772269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 773269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 774269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 775269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnAllocateRequestTimeout() { 776269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAllocateError(); 777269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 778269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 779269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::HandleDataIndication(const char* data, size_t size, 780269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketTime& packet_time) { 781269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Read in the message, and process according to RFC5766, Section 10.4. 782269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::ByteBuffer buf(data, size); 783269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnMessage msg; 784269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!msg.Read(&buf)) { 785269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received invalid TURN data indication"; 786269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 787269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 788269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 789269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check mandatory attributes. 790269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunAddressAttribute* addr_attr = 791269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS); 792269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!addr_attr) { 793269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_XOR_PEER_ADDRESS attribute " 794269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "in data indication."; 795269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 796269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 797269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 798269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* data_attr = 799269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org msg.GetByteString(STUN_ATTR_DATA); 800269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!data_attr) { 801269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_DATA attribute in " 802269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "data indication."; 803269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 804269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 805269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 806269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Verify that the data came from somewhere we think we have a permission for. 807269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::SocketAddress ext_addr(addr_attr->GetAddress()); 808269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!HasPermission(ext_addr.ipaddr())) { 809269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received TURN data indication with invalid " 810269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "peer address, addr=" 811269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << ext_addr.ToSensitiveString(); 812269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 813269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 814269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 815269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr, 816269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org PROTO_UDP, packet_time); 817269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 818269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 819269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::HandleChannelData(int channel_id, const char* data, 820269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org size_t size, 821269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketTime& packet_time) { 822269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Read the message, and process according to RFC5766, Section 11.6. 823269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // 0 1 2 3 824269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 825269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 826269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // | Channel Number | Length | 827269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 828269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // | | 829269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // / Application Data / 830269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // / / 831269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // | | 832269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // | +-------------------------------+ 833269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // | | 834269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // +-------------------------------+ 835269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 836269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Extract header fields from the message. 8370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint16_t len = rtc::GetBE16(data + 2); 838269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (len > size - TURN_CHANNEL_HEADER_SIZE) { 839269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received TURN channel data message with " 840269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "incorrect length, len=" << len; 841269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 842269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 843269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Allowing messages larger than |len|, as ChannelData can be padded. 844269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 845269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnEntry* entry = FindEntry(channel_id); 846269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!entry) { 847269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received TURN channel data message for invalid " 848269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "channel, channel_id=" << channel_id; 849269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 850269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 851269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 852269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(), 853269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org PROTO_UDP, packet_time); 854269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 855269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 856269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::DispatchPacket(const char* data, size_t size, 857269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& remote_addr, 858269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ProtocolType proto, const rtc::PacketTime& packet_time) { 859269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (Connection* conn = GetConnection(remote_addr)) { 860269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org conn->OnReadPacket(data, size, packet_time); 861269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 862269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org Port::OnReadPacket(data, size, remote_addr, proto); 863269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 864269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 865269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 866269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool TurnPort::ScheduleRefresh(int lifetime) { 867269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Lifetime is in seconds; we schedule a refresh for one minute less. 868269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (lifetime < 2 * 60) { 869269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, this) << "Received response with lifetime that was " 870269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "too short, lifetime=" << lifetime; 871269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 872269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 873269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 874b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher int delay = (lifetime - 60) * 1000; 875b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher SendRequest(new TurnRefreshRequest(this), delay); 876b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher LOG_J(LS_INFO, this) << "Scheduled refresh in " << delay << "ms."; 877269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return true; 878269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 879269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 880269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::SendRequest(StunRequest* req, int delay) { 881269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request_manager_.SendDelayed(req, delay); 882269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 883269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 884269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::AddRequestAuthInfo(StunMessage* msg) { 885269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If we've gotten the necessary data from the server, add it to our request. 886269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(!hash_.empty()); 887269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg->AddAttribute(new StunByteStringAttribute( 888269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_USERNAME, credentials_.username))); 889269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg->AddAttribute(new StunByteStringAttribute( 890269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_REALM, realm_))); 891269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg->AddAttribute(new StunByteStringAttribute( 892269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_NONCE, nonce_))); 893269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg->AddMessageIntegrity(hash())); 894269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 895269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 896269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint TurnPort::Send(const void* data, size_t len, 897269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketOptions& options) { 898269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return socket_->SendTo(data, len, server_address_.address, options); 899269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 900269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 901269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::UpdateHash() { 902269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(ComputeStunCredentialHash(credentials_.username, realm_, 903269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org credentials_.password, &hash_)); 904269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 905269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 906269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool TurnPort::UpdateNonce(StunMessage* response) { 907269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // When stale nonce error received, we should update 908269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // hash and store realm and nonce. 909269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check the mandatory attributes. 910269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* realm_attr = 911269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetByteString(STUN_ATTR_REALM); 912269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!realm_attr) { 913269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in " 914269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "stale nonce error response."; 915269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 916269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 917269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org set_realm(realm_attr->GetString()); 918269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 919269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* nonce_attr = 920269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetByteString(STUN_ATTR_NONCE); 921269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!nonce_attr) { 922269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in " 923269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "stale nonce error response."; 924269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return false; 925269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 926269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org set_nonce(nonce_attr->GetString()); 927269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return true; 928269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 929269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 930269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic bool MatchesIP(TurnEntry* e, rtc::IPAddress ipaddr) { 931269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return e->address().ipaddr() == ipaddr; 932269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 933269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgbool TurnPort::HasPermission(const rtc::IPAddress& ipaddr) const { 934269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return (std::find_if(entries_.begin(), entries_.end(), 935269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org std::bind2nd(std::ptr_fun(MatchesIP), ipaddr)) != entries_.end()); 936269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 937269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 938269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic bool MatchesAddress(TurnEntry* e, rtc::SocketAddress addr) { 939269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return e->address() == addr; 940269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 941269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnEntry* TurnPort::FindEntry(const rtc::SocketAddress& addr) const { 942269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(), 943269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org std::bind2nd(std::ptr_fun(MatchesAddress), addr)); 944269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return (it != entries_.end()) ? *it : NULL; 945269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 946269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 947269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstatic bool MatchesChannelId(TurnEntry* e, int id) { 948269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return e->channel_id() == id; 949269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 950269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnEntry* TurnPort::FindEntry(int channel_id) const { 951269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(), 952269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org std::bind2nd(std::ptr_fun(MatchesChannelId), channel_id)); 953269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return (it != entries_.end()) ? *it : NULL; 954269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 955269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 956c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaizbool TurnPort::EntryExists(TurnEntry* e) { 957c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz auto it = std::find(entries_.begin(), entries_.end(), e); 958c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz return it != entries_.end(); 959c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz} 960c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz 96132f39968ce79cfca5146069e410ded2f104bba23honghaizvoid TurnPort::CreateOrRefreshEntry(const rtc::SocketAddress& addr) { 96232f39968ce79cfca5146069e410ded2f104bba23honghaiz TurnEntry* entry = FindEntry(addr); 96332f39968ce79cfca5146069e410ded2f104bba23honghaiz if (entry == nullptr) { 96432f39968ce79cfca5146069e410ded2f104bba23honghaiz entry = new TurnEntry(this, next_channel_number_++, addr); 96532f39968ce79cfca5146069e410ded2f104bba23honghaiz entries_.push_back(entry); 96632f39968ce79cfca5146069e410ded2f104bba23honghaiz } else { 96732f39968ce79cfca5146069e410ded2f104bba23honghaiz // The channel binding request for the entry will be refreshed automatically 96832f39968ce79cfca5146069e410ded2f104bba23honghaiz // until the entry is destroyed. 96932f39968ce79cfca5146069e410ded2f104bba23honghaiz CancelEntryDestruction(entry); 97032f39968ce79cfca5146069e410ded2f104bba23honghaiz } 971269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 972269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 97332f39968ce79cfca5146069e410ded2f104bba23honghaizvoid TurnPort::DestroyEntry(TurnEntry* entry) { 974269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(entry != NULL); 975269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry->SignalDestroyed(entry); 976269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entries_.remove(entry); 977269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org delete entry; 978269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 979269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 98032f39968ce79cfca5146069e410ded2f104bba23honghaizvoid TurnPort::DestroyEntryIfNotCancelled(TurnEntry* entry, 98132f39968ce79cfca5146069e410ded2f104bba23honghaiz uint32_t timestamp) { 982c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz if (!EntryExists(entry)) { 983c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz return; 984c3e0fe7c21a6c6c367ce38b54634dc38f6222693honghaiz } 98532f39968ce79cfca5146069e410ded2f104bba23honghaiz bool cancelled = timestamp != entry->destruction_timestamp(); 98632f39968ce79cfca5146069e410ded2f104bba23honghaiz if (!cancelled) { 98732f39968ce79cfca5146069e410ded2f104bba23honghaiz DestroyEntry(entry); 98832f39968ce79cfca5146069e410ded2f104bba23honghaiz } 98932f39968ce79cfca5146069e410ded2f104bba23honghaiz} 99032f39968ce79cfca5146069e410ded2f104bba23honghaiz 991269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnPort::OnConnectionDestroyed(Connection* conn) { 99232f39968ce79cfca5146069e410ded2f104bba23honghaiz // Schedule an event to destroy TurnEntry for the connection, which is 99332f39968ce79cfca5146069e410ded2f104bba23honghaiz // already destroyed. 99432f39968ce79cfca5146069e410ded2f104bba23honghaiz const rtc::SocketAddress& remote_address = conn->remote_candidate().address(); 99532f39968ce79cfca5146069e410ded2f104bba23honghaiz TurnEntry* entry = FindEntry(remote_address); 99632f39968ce79cfca5146069e410ded2f104bba23honghaiz ASSERT(entry != NULL); 99732f39968ce79cfca5146069e410ded2f104bba23honghaiz ScheduleEntryDestruction(entry); 99832f39968ce79cfca5146069e410ded2f104bba23honghaiz} 99932f39968ce79cfca5146069e410ded2f104bba23honghaiz 100032f39968ce79cfca5146069e410ded2f104bba23honghaizvoid TurnPort::ScheduleEntryDestruction(TurnEntry* entry) { 100132f39968ce79cfca5146069e410ded2f104bba23honghaiz ASSERT(entry->destruction_timestamp() == 0); 100232f39968ce79cfca5146069e410ded2f104bba23honghaiz uint32_t timestamp = rtc::Time(); 100332f39968ce79cfca5146069e410ded2f104bba23honghaiz entry->set_destruction_timestamp(timestamp); 100432f39968ce79cfca5146069e410ded2f104bba23honghaiz invoker_.AsyncInvokeDelayed<void>( 100532f39968ce79cfca5146069e410ded2f104bba23honghaiz thread(), 100632f39968ce79cfca5146069e410ded2f104bba23honghaiz rtc::Bind(&TurnPort::DestroyEntryIfNotCancelled, this, entry, timestamp), 100732f39968ce79cfca5146069e410ded2f104bba23honghaiz TURN_PERMISSION_TIMEOUT); 100832f39968ce79cfca5146069e410ded2f104bba23honghaiz} 100932f39968ce79cfca5146069e410ded2f104bba23honghaiz 101032f39968ce79cfca5146069e410ded2f104bba23honghaizvoid TurnPort::CancelEntryDestruction(TurnEntry* entry) { 101132f39968ce79cfca5146069e410ded2f104bba23honghaiz ASSERT(entry->destruction_timestamp() != 0); 101232f39968ce79cfca5146069e410ded2f104bba23honghaiz entry->set_destruction_timestamp(0); 1013269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1014269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1015f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhangbool TurnPort::SetEntryChannelId(const rtc::SocketAddress& address, 1016f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang int channel_id) { 1017f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang TurnEntry* entry = FindEntry(address); 1018f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang if (!entry) { 1019f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang return false; 1020f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } 1021f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang entry->set_channel_id(channel_id); 1022f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang return true; 1023f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang} 1024f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang 1025269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnAllocateRequest::TurnAllocateRequest(TurnPort* port) 1026269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org : StunRequest(new TurnMessage()), 1027269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_(port) { 1028269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1029269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1030269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnAllocateRequest::Prepare(StunMessage* request) { 1031269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Create the request as indicated in RFC 5766, Section 6.1. 1032269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request->SetType(TURN_ALLOCATE_REQUEST); 1033269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32( 1034269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_REQUESTED_TRANSPORT); 1035269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org transport_attr->SetValue(IPPROTO_UDP << 24); 1036269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(request->AddAttribute(transport_attr)); 1037269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!port_->hash().empty()) { 1038269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->AddRequestAuthInfo(request); 1039269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1040269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1041269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 10421cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatchervoid TurnAllocateRequest::OnSent() { 10431cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN allocate request sent" 10441cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()); 10451cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher StunRequest::OnSent(); 10461cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher} 10471cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1048269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnAllocateRequest::OnResponse(StunMessage* response) { 10491cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN allocate requested successfully" 10501cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 10511cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=0" // Makes logging easier to parse. 10521cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 10531cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1054269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check mandatory attributes as indicated in RFC5766, Section 6.3. 1055269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunAddressAttribute* mapped_attr = 1056269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); 1057269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!mapped_attr) { 1058269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_MAPPED_ADDRESS " 1059269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "attribute in allocate success response"; 1060269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1061269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1062269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Using XOR-Mapped-Address for stun. 1063269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnStunAddress(mapped_attr->GetAddress()); 1064269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1065269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunAddressAttribute* relayed_attr = 1066269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS); 1067269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!relayed_attr) { 1068269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_RELAYED_ADDRESS " 1069269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "attribute in allocate success response"; 1070269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1071269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1072269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1073269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunUInt32Attribute* lifetime_attr = 1074269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetUInt32(STUN_ATTR_TURN_LIFETIME); 1075269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!lifetime_attr) { 1076269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in " 1077269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "allocate success response"; 1078269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1079269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1080269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Notify the port the allocate succeeded, and schedule a refresh request. 1081269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnAllocateSuccess(relayed_attr->GetAddress(), 1082269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org mapped_attr->GetAddress()); 1083269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->ScheduleRefresh(lifetime_attr->value()); 1084269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1085269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1086269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnAllocateRequest::OnErrorResponse(StunMessage* response) { 1087269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Process error response according to RFC5766, Section 6.4. 1088269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunErrorCodeAttribute* error_code = response->GetErrorCode(); 10891cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 10901cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "Received TURN allocate error response" 10911cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 10921cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=" << error_code->code() 10931cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 10941cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1095269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org switch (error_code->code()) { 1096269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org case STUN_ERROR_UNAUTHORIZED: // Unauthrorized. 1097269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnAuthChallenge(response, error_code->code()); 1098269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org break; 1099269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org case STUN_ERROR_TRY_ALTERNATE: 1100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org OnTryAlternate(response, error_code->code()); 1101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org break; 1102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org case STUN_ERROR_ALLOCATION_MISMATCH: 1103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // We must handle this error async because trying to delete the socket in 1104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // OnErrorResponse will cause a deadlock on the socket. 1105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->thread()->Post(port_, TurnPort::MSG_ALLOCATE_MISMATCH); 1106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org break; 1107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org default: 11081cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "Received TURN allocate error response" 11091cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 11101cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=" << error_code->code() 11111cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 1112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnAllocateError(); 1113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnAllocateRequest::OnTimeout() { 11171cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "TURN allocate request " 11181cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << rtc::hex_encode(id()) << " timout"; 1119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnAllocateRequestTimeout(); 1120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) { 1123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If we failed to authenticate even after we sent our credentials, fail hard. 1124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) { 1125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Failed to authenticate with the server " 1126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "after challenge."; 1127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnAllocateError(); 1128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check the mandatory attributes. 1132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* realm_attr = 1133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetByteString(STUN_ATTR_REALM); 1134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!realm_attr) { 1135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_REALM attribute in " 1136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "allocate unauthorized response."; 1137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->set_realm(realm_attr->GetString()); 1140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* nonce_attr = 1142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetByteString(STUN_ATTR_NONCE); 1143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!nonce_attr) { 1144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_NONCE attribute in " 1145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "allocate unauthorized response."; 1146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->set_nonce(nonce_attr->GetString()); 1149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Send another allocate request, with the received realm and nonce values. 1151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->SendRequest(new TurnAllocateRequest(port_), 0); 1152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) { 1155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // According to RFC 5389 section 11, there are use cases where 1157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // authentication of response is not possible, we're not validating 1158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // message integrity. 1159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Get the alternate server address attribute value. 1161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunAddressAttribute* alternate_server_attr = 1162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetAddress(STUN_ATTR_ALTERNATE_SERVER); 1163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!alternate_server_attr) { 1164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_ALTERNATE_SERVER " 1165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "attribute in try alternate error response"; 1166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnAllocateError(); 1167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) { 1170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->OnAllocateError(); 1171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check the attributes. 1175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* realm_attr = 1176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetByteString(STUN_ATTR_REALM); 1177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (realm_attr) { 1178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_REALM attribute in " 1179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "try alternate error response."; 1180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->set_realm(realm_attr->GetString()); 1181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunByteStringAttribute* nonce_attr = 1184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetByteString(STUN_ATTR_NONCE); 1185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (nonce_attr) { 1186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_NONCE attribute in " 1187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "try alternate error response."; 1188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->set_nonce(nonce_attr->GetString()); 1189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 119119e4e8d751478d34c05bc2d73e065429ed65a1c1guoweis@webrtc.org // For TCP, we can't close the original Tcp socket during handling a 300 as 119219e4e8d751478d34c05bc2d73e065429ed65a1c1guoweis@webrtc.org // we're still inside that socket's event handler. Doing so will cause 119319e4e8d751478d34c05bc2d73e065429ed65a1c1guoweis@webrtc.org // deadlock. 119419e4e8d751478d34c05bc2d73e065429ed65a1c1guoweis@webrtc.org port_->thread()->Post(port_, TurnPort::MSG_TRY_ALTERNATE_SERVER); 1195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnRefreshRequest::TurnRefreshRequest(TurnPort* port) 1198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org : StunRequest(new TurnMessage()), 1199fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org port_(port), 1200fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org lifetime_(-1) { 1201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnRefreshRequest::Prepare(StunMessage* request) { 1204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Create the request as indicated in RFC 5766, Section 7.1. 1205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // No attributes need to be included. 1206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request->SetType(TURN_REFRESH_REQUEST); 1207fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org if (lifetime_ > -1) { 1208fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org VERIFY(request->AddAttribute(new StunUInt32Attribute( 1209fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org STUN_ATTR_LIFETIME, lifetime_))); 1210fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org } 1211fe672e3839004350403423b74764d42396a0edabpthatcher@webrtc.org 1212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->AddRequestAuthInfo(request); 1213269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1214269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 12151cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatchervoid TurnRefreshRequest::OnSent() { 12161cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN refresh request sent" 12171cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()); 12181cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher StunRequest::OnSent(); 12191cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher} 12201cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1221269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnRefreshRequest::OnResponse(StunMessage* response) { 12221cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN refresh requested successfully" 12231cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 12241cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=0" // Makes logging easier to parse. 12251cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 1226b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher 1227269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Check mandatory attributes as indicated in RFC5766, Section 7.3. 1228269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunUInt32Attribute* lifetime_attr = 1229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org response->GetUInt32(STUN_ATTR_TURN_LIFETIME); 1230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (!lifetime_attr) { 1231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in " 1232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << "refresh success response."; 1233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return; 1234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Schedule a refresh based on the returned lifetime value. 1237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->ScheduleRefresh(lifetime_attr->value()); 1238f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->SignalTurnRefreshResult(port_, TURN_SUCCESS_RESULT_CODE); 1239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnRefreshRequest::OnErrorResponse(StunMessage* response) { 1242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const StunErrorCodeAttribute* error_code = response->GetErrorCode(); 12431cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (error_code->code() == STUN_ERROR_STALE_NONCE) { 1245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (port_->UpdateNonce(response)) { 1246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Send RefreshRequest immediately. 1247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->SendRequest(new TurnRefreshRequest(port_), 0); 1248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 12491cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher } else { 12501cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "Received TURN refresh error response" 12511cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 12521cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=" << error_code->code() 12531cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 1254f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->OnTurnRefreshError(); 1255f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->SignalTurnRefreshResult(port_, error_code->code()); 1256269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1259269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnRefreshRequest::OnTimeout() { 12601cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "TURN refresh timeout " << rtc::hex_encode(id()); 1261f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->OnTurnRefreshError(); 1262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnCreatePermissionRequest::TurnCreatePermissionRequest( 1265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port, TurnEntry* entry, 1266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& ext_addr) 1267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org : StunRequest(new TurnMessage()), 1268269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_(port), 1269269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_(entry), 1270269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ext_addr_(ext_addr) { 1271269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_->SignalDestroyed.connect( 1272269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org this, &TurnCreatePermissionRequest::OnEntryDestroyed); 1273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnCreatePermissionRequest::Prepare(StunMessage* request) { 1276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Create the request as indicated in RFC5766, Section 9.1. 1277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request->SetType(TURN_CREATE_PERMISSION_REQUEST); 1278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(request->AddAttribute(new StunXorAddressAttribute( 1279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_))); 1280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->AddRequestAuthInfo(request); 1281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 12831cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatchervoid TurnCreatePermissionRequest::OnSent() { 12841cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN create permission request sent" 12851cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()); 12861cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher StunRequest::OnSent(); 12871cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher} 12881cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnCreatePermissionRequest::OnResponse(StunMessage* response) { 12901cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN permission requested successfully" 12911cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 12921cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=0" // Makes logging easier to parse. 12931cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 12941cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (entry_) { 1296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_->OnCreatePermissionSuccess(); 1297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) { 1301b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher const StunErrorCodeAttribute* error_code = response->GetErrorCode(); 13021cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "Received TURN create permission error response" 13031cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 13041cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=" << error_code->code() 13051cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 1306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (entry_) { 1307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_->OnCreatePermissionError(response, error_code->code()); 1308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1311269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnCreatePermissionRequest::OnTimeout() { 13121cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "TURN create permission timeout " 13131cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << rtc::hex_encode(id()); 1314f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang if (entry_) { 1315f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang entry_->OnCreatePermissionTimeout(); 1316f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } 1317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) { 1320269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(entry_ == entry); 1321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_ = NULL; 1322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnChannelBindRequest::TurnChannelBindRequest( 1325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnPort* port, TurnEntry* entry, 1326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org int channel_id, const rtc::SocketAddress& ext_addr) 1327269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org : StunRequest(new TurnMessage()), 1328269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_(port), 1329269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_(entry), 1330269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org channel_id_(channel_id), 1331269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ext_addr_(ext_addr) { 1332269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_->SignalDestroyed.connect( 1333269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org this, &TurnChannelBindRequest::OnEntryDestroyed); 1334269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1335269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1336269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnChannelBindRequest::Prepare(StunMessage* request) { 1337269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Create the request as indicated in RFC5766, Section 11.1. 1338269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org request->SetType(TURN_CHANNEL_BIND_REQUEST); 1339269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(request->AddAttribute(new StunUInt32Attribute( 1340269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16))); 1341269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(request->AddAttribute(new StunXorAddressAttribute( 1342269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_))); 1343269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->AddRequestAuthInfo(request); 1344269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1345269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 13461cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatchervoid TurnChannelBindRequest::OnSent() { 13471cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN channel bind request sent" 13481cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()); 13491cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher StunRequest::OnSent(); 13501cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher} 13511cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1352269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnChannelBindRequest::OnResponse(StunMessage* response) { 13531cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_INFO, port_) << "TURN channel bind requested successfully" 13541cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 13551cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=0" // Makes logging easier to parse. 13561cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 13571cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher 1358269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (entry_) { 1359269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_->OnChannelBindSuccess(); 1360269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Refresh the channel binding just under the permission timeout 1361269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // threshold. The channel binding has a longer lifetime, but 1362269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // this is the easiest way to keep both the channel and the 1363269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // permission from expiring. 1364b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher int delay = TURN_PERMISSION_TIMEOUT - 60000; 1365b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher entry_->SendChannelBindRequest(delay); 1366b32a5c48d3d0b17f564fe680c7e1e45d5b76eefdPeter Thatcher LOG_J(LS_INFO, port_) << "Scheduled channel bind in " << delay << "ms."; 1367269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1368269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1369269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1370269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnChannelBindRequest::OnErrorResponse(StunMessage* response) { 13711cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher const StunErrorCodeAttribute* error_code = response->GetErrorCode(); 13721cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "Received TURN channel bind error response" 13731cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", id=" << rtc::hex_encode(id()) 13741cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", code=" << error_code->code() 13751cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << ", rtt=" << Elapsed(); 1376269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (entry_) { 1377269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_->OnChannelBindError(response, error_code->code()); 1378269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1379269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1380269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1381269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnChannelBindRequest::OnTimeout() { 13821cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher LOG_J(LS_WARNING, port_) << "TURN channel bind timeout " 13831cf6f8101ae9db517332783e99c98e14ff4c47e1Peter Thatcher << rtc::hex_encode(id()); 1384f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang if (entry_) { 1385f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang entry_->OnChannelBindTimeout(); 1386f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } 1387269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1388269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1389269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) { 1390269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(entry_ == entry); 1391269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org entry_ = NULL; 1392269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1393269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1394269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgTurnEntry::TurnEntry(TurnPort* port, int channel_id, 1395269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::SocketAddress& ext_addr) 1396269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org : port_(port), 1397269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org channel_id_(channel_id), 1398269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ext_addr_(ext_addr), 1399269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org state_(STATE_UNBOUND) { 1400269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Creating permission for |ext_addr_|. 14018597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang SendCreatePermissionRequest(0); 1402269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1403269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 14048597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhangvoid TurnEntry::SendCreatePermissionRequest(int delay) { 14058597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang port_->SendRequest(new TurnCreatePermissionRequest(port_, this, ext_addr_), 14068597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang delay); 1407269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1408269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1409269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnEntry::SendChannelBindRequest(int delay) { 1410269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->SendRequest(new TurnChannelBindRequest( 1411269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_, this, channel_id_, ext_addr_), delay); 1412269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1413269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1414269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgint TurnEntry::Send(const void* data, size_t size, bool payload, 1415269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org const rtc::PacketOptions& options) { 1416269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::ByteBuffer buf; 1417269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (state_ != STATE_BOUND) { 1418269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If we haven't bound the channel yet, we have to use a Send Indication. 1419269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org TurnMessage msg; 1420269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org msg.SetType(TURN_SEND_INDICATION); 1421269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org msg.SetTransactionID( 1422269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org rtc::CreateRandomString(kStunTransactionIdLength)); 1423269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg.AddAttribute(new StunXorAddressAttribute( 1424269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_))); 1425269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg.AddAttribute(new StunByteStringAttribute( 1426269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org STUN_ATTR_DATA, data, size))); 1427269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org VERIFY(msg.Write(&buf)); 1428269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1429269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If we're sending real data, request a channel bind that we can use later. 1430269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (state_ == STATE_UNBOUND && payload) { 1431269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendChannelBindRequest(0); 1432269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org state_ = STATE_BINDING; 1433269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1434269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 1435269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // If the channel is bound, we can send the data as a Channel Message. 1436269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org buf.WriteUInt16(channel_id_); 14370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström buf.WriteUInt16(static_cast<uint16_t>(size)); 1438269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org buf.WriteBytes(reinterpret_cast<const char*>(data), size); 1439269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1440269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org return port_->Send(buf.Data(), buf.Length(), options); 1441269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1442269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1443269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnEntry::OnCreatePermissionSuccess() { 1444269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, port_) << "Create permission for " 1445269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << ext_addr_.ToSensitiveString() 1446269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " succeeded"; 1447f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->SignalCreatePermissionResult(port_, ext_addr_, 1448f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang TURN_SUCCESS_RESULT_CODE); 14498597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang 14508597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang // If |state_| is STATE_BOUND, the permission will be refreshed 14518597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang // by ChannelBindRequest. 14528597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang if (state_ != STATE_BOUND) { 14538597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang // Refresh the permission request about 1 minute before the permission 14548597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang // times out. 14558597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang int delay = TURN_PERMISSION_TIMEOUT - 60000; 14568597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang SendCreatePermissionRequest(delay); 14578597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang LOG_J(LS_INFO, port_) << "Scheduled create-permission-request in " 14588597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang << delay << "ms."; 14598597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang } 1460269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1461269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1462269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnEntry::OnCreatePermissionError(StunMessage* response, int code) { 1463269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (code == STUN_ERROR_STALE_NONCE) { 1464269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (port_->UpdateNonce(response)) { 14658597543ae845073ca32876bfaaff207017b6c0ebHonghai Zhang SendCreatePermissionRequest(0); 1466269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1467269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } else { 1468f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->DestroyConnection(ext_addr_); 1469269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Send signal with error code. 1470269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org port_->SignalCreatePermissionResult(port_, ext_addr_, code); 1471376e1235c7b602e86afe9f36eb81289e42643718deadbeef Connection* c = port_->GetConnection(ext_addr_); 1472376e1235c7b602e86afe9f36eb81289e42643718deadbeef if (c) { 1473376e1235c7b602e86afe9f36eb81289e42643718deadbeef LOG_J(LS_ERROR, c) << "Received TURN CreatePermission error response, " 1474376e1235c7b602e86afe9f36eb81289e42643718deadbeef << "code=" << code << "; killing connection."; 1475376e1235c7b602e86afe9f36eb81289e42643718deadbeef c->FailAndDestroy(); 1476376e1235c7b602e86afe9f36eb81289e42643718deadbeef } 1477269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1478269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1479269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1480f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhangvoid TurnEntry::OnCreatePermissionTimeout() { 1481f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->DestroyConnection(ext_addr_); 1482f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang} 1483f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang 1484269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnEntry::OnChannelBindSuccess() { 1485269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString() 1486269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org << " succeeded"; 1487269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND); 1488269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org state_ = STATE_BOUND; 1489269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1490269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org 1491269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid TurnEntry::OnChannelBindError(StunMessage* response, int code) { 1492f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // If the channel bind fails due to errors other than STATE_NONCE, 1493f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // we just destroy the connection and rely on ICE restart to re-establish 1494f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang // the connection. 1495269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (code == STUN_ERROR_STALE_NONCE) { 1496269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org if (port_->UpdateNonce(response)) { 1497269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org // Send channel bind request with fresh nonce. 1498269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org SendChannelBindRequest(0); 1499269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1500f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang } else { 1501f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang state_ = STATE_UNBOUND; 1502f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->DestroyConnection(ext_addr_); 1503269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org } 1504269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} 1505f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhangvoid TurnEntry::OnChannelBindTimeout() { 1506f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang state_ = STATE_UNBOUND; 1507f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang port_->DestroyConnection(ext_addr_); 1508f67c548576ad957a1e9c3196e11d45f41e320424Honghai Zhang} 1509269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org} // namespace cricket 1510