Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: webrtc/p2p/base/turnport.cc

Issue 1453823004: Handle Turn error response to RefreshRequest, CreatePermissionRequest, and ChanelBindRequest (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 // a channel for this remote destination to reduce the overhead of sending data. 130 // a channel for this remote destination to reduce the overhead of sending data.
131 class TurnEntry : public sigslot::has_slots<> { 131 class TurnEntry : public sigslot::has_slots<> {
132 public: 132 public:
133 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND }; 133 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
134 TurnEntry(TurnPort* port, int channel_id, 134 TurnEntry(TurnPort* port, int channel_id,
135 const rtc::SocketAddress& ext_addr); 135 const rtc::SocketAddress& ext_addr);
136 136
137 TurnPort* port() { return port_; } 137 TurnPort* port() { return port_; }
138 138
139 int channel_id() const { return channel_id_; } 139 int channel_id() const { return channel_id_; }
140 // For testing only.
141 void set_channel_id(int channel_id) { channel_id_ = channel_id; }
142
140 const rtc::SocketAddress& address() const { return ext_addr_; } 143 const rtc::SocketAddress& address() const { return ext_addr_; }
141 BindState state() const { return state_; } 144 BindState state() const { return state_; }
142 145
143 uint32_t destruction_timestamp() { return destruction_timestamp_; } 146 uint32_t destruction_timestamp() { return destruction_timestamp_; }
144 void set_destruction_timestamp(uint32_t destruction_timestamp) { 147 void set_destruction_timestamp(uint32_t destruction_timestamp) {
145 destruction_timestamp_ = destruction_timestamp; 148 destruction_timestamp_ = destruction_timestamp;
146 } 149 }
147 150
148 // Helper methods to send permission and channel bind requests. 151 // Helper methods to send permission and channel bind requests.
149 void SendCreatePermissionRequest(int delay); 152 void SendCreatePermissionRequest(int delay);
150 void SendChannelBindRequest(int delay); 153 void SendChannelBindRequest(int delay);
151 // Sends a packet to the given destination address. 154 // Sends a packet to the given destination address.
152 // This will wrap the packet in STUN if necessary. 155 // This will wrap the packet in STUN if necessary.
153 int Send(const void* data, size_t size, bool payload, 156 int Send(const void* data, size_t size, bool payload,
154 const rtc::PacketOptions& options); 157 const rtc::PacketOptions& options);
155 158
156 void OnCreatePermissionSuccess(); 159 void OnCreatePermissionSuccess();
157 void OnCreatePermissionError(StunMessage* response, int code); 160 void OnCreatePermissionError(StunMessage* response, int code);
161 void OnCreatePermissionTimeout();
158 void OnChannelBindSuccess(); 162 void OnChannelBindSuccess();
159 void OnChannelBindError(StunMessage* response, int code); 163 void OnChannelBindError(StunMessage* response, int code);
164 void OnChannelBindTimeout();
160 // Signal sent when TurnEntry is destroyed. 165 // Signal sent when TurnEntry is destroyed.
161 sigslot::signal1<TurnEntry*> SignalDestroyed; 166 sigslot::signal1<TurnEntry*> SignalDestroyed;
162 167
163 private: 168 private:
164 TurnPort* port_; 169 TurnPort* port_;
165 int channel_id_; 170 int channel_id_;
166 rtc::SocketAddress ext_addr_; 171 rtc::SocketAddress ext_addr_;
167 BindState state_; 172 BindState state_;
168 // A non-zero value indicates that this entry is scheduled to be destroyed. 173 // A non-zero value indicates that this entry is scheduled to be destroyed.
169 // It is also used as an ID of the event scheduling. When the destruction 174 // It is also used as an ID of the event scheduling. When the destruction
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 if (Candidates()[index].type() == RELAY_PORT_TYPE) { 462 if (Candidates()[index].type() == RELAY_PORT_TYPE) {
458 ProxyConnection* conn = new ProxyConnection(this, index, address); 463 ProxyConnection* conn = new ProxyConnection(this, index, address);
459 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed); 464 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
460 AddConnection(conn); 465 AddConnection(conn);
461 return conn; 466 return conn;
462 } 467 }
463 } 468 }
464 return NULL; 469 return NULL;
465 } 470 }
466 471
472 void TurnPort::DestroyConnection(const rtc::SocketAddress& address) {
pthatcher1 2015/12/08 20:04:20 Should it return a bool of whether or not it was d
honghaiz3 2015/12/10 17:58:30 Done
473 Connection* conn = GetConnection(address);
474 if (conn != nullptr) {
475 conn->Destroy();
476 }
477 }
478
467 int TurnPort::SetOption(rtc::Socket::Option opt, int value) { 479 int TurnPort::SetOption(rtc::Socket::Option opt, int value) {
468 if (!socket_) { 480 if (!socket_) {
469 // If socket is not created yet, these options will be applied during socket 481 // If socket is not created yet, these options will be applied during socket
470 // creation. 482 // creation.
471 socket_options_[opt] = value; 483 socket_options_[opt] = value;
472 return 0; 484 return 0;
473 } 485 }
474 return socket_->SetOption(opt, value); 486 return socket_->SetOption(opt, value);
475 } 487 }
476 488
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 "", // TCP canddiate type, empty for turn candidates. 701 "", // TCP canddiate type, empty for turn candidates.
690 RELAY_PORT_TYPE, 702 RELAY_PORT_TYPE,
691 GetRelayPreference(server_address_.proto, server_address_.secure), 703 GetRelayPreference(server_address_.proto, server_address_.secure),
692 server_priority_, true); 704 server_priority_, true);
693 } 705 }
694 706
695 void TurnPort::OnAllocateError() { 707 void TurnPort::OnAllocateError() {
696 // We will send SignalPortError asynchronously as this can be sent during 708 // We will send SignalPortError asynchronously as this can be sent during
697 // port initialization. This way it will not be blocking other port 709 // port initialization. This way it will not be blocking other port
698 // creation. 710 // creation.
699 thread()->Post(this, MSG_ERROR); 711 thread()->Post(this, MSG_ALLOCATE_ERROR);
712 }
713
714 void TurnPort::OnTurnRefreshError() {
715 // Stop the port from creating new connections.
716 state_ = STATE_DISCONNECTED;
717 // Delete all existing connections; stop sending data.
718 for (auto kv : connections()) {
719 kv.second->Destroy();
720 }
pthatcher1 2015/12/08 20:04:20 Should we have a TunrPort::Close method that does
honghaiz3 2015/12/10 17:58:30 Done.
700 } 721 }
701 722
702 void TurnPort::OnMessage(rtc::Message* message) { 723 void TurnPort::OnMessage(rtc::Message* message) {
703 if (message->message_id == MSG_ERROR) { 724 switch (message->message_id) {
704 SignalPortError(this); 725 case MSG_ALLOCATE_ERROR:
705 return; 726 SignalPortError(this);
706 } else if (message->message_id == MSG_ALLOCATE_MISMATCH) { 727 break;
707 OnAllocateMismatch(); 728 case MSG_ALLOCATE_MISMATCH:
708 return; 729 OnAllocateMismatch();
709 } else if (message->message_id == MSG_TRY_ALTERNATE_SERVER) { 730 break;
710 if (server_address().proto == PROTO_UDP) { 731 case MSG_TRY_ALTERNATE_SERVER:
711 // Send another allocate request to alternate server, with the received 732 if (server_address().proto == PROTO_UDP) {
712 // realm and nonce values. 733 // Send another allocate request to alternate server, with the received
713 SendRequest(new TurnAllocateRequest(this), 0); 734 // realm and nonce values.
714 } else { 735 SendRequest(new TurnAllocateRequest(this), 0);
715 // Since it's TCP, we have to delete the connected socket and reconnect 736 } else {
716 // with the alternate server. PrepareAddress will send stun binding once 737 // Since it's TCP, we have to delete the connected socket and reconnect
717 // the new socket is connected. 738 // with the alternate server. PrepareAddress will send stun binding once
718 ASSERT(server_address().proto == PROTO_TCP); 739 // the new socket is connected.
719 ASSERT(!SharedSocket()); 740 ASSERT(server_address().proto == PROTO_TCP);
720 delete socket_; 741 ASSERT(!SharedSocket());
721 socket_ = NULL; 742 delete socket_;
722 PrepareAddress(); 743 socket_ = NULL;
723 } 744 PrepareAddress();
724 return; 745 }
746 break;
747 default:
748 Port::OnMessage(message);
725 } 749 }
726 Port::OnMessage(message);
727 } 750 }
728 751
729 void TurnPort::OnAllocateRequestTimeout() { 752 void TurnPort::OnAllocateRequestTimeout() {
730 OnAllocateError(); 753 OnAllocateError();
731 } 754 }
732 755
733 void TurnPort::HandleDataIndication(const char* data, size_t size, 756 void TurnPort::HandleDataIndication(const char* data, size_t size,
734 const rtc::PacketTime& packet_time) { 757 const rtc::PacketTime& packet_time) {
735 // Read in the message, and process according to RFC5766, Section 10.4. 758 // Read in the message, and process according to RFC5766, Section 10.4.
736 rtc::ByteBuffer buf(data, size); 759 rtc::ByteBuffer buf(data, size);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 thread(), 974 thread(),
952 rtc::Bind(&TurnPort::DestroyEntryIfNotCancelled, this, entry, timestamp), 975 rtc::Bind(&TurnPort::DestroyEntryIfNotCancelled, this, entry, timestamp),
953 TURN_PERMISSION_TIMEOUT); 976 TURN_PERMISSION_TIMEOUT);
954 } 977 }
955 978
956 void TurnPort::CancelEntryDestruction(TurnEntry* entry) { 979 void TurnPort::CancelEntryDestruction(TurnEntry* entry) {
957 ASSERT(entry->destruction_timestamp() != 0); 980 ASSERT(entry->destruction_timestamp() != 0);
958 entry->set_destruction_timestamp(0); 981 entry->set_destruction_timestamp(0);
959 } 982 }
960 983
984 bool TurnPort::SetEntryChannelId(const rtc::SocketAddress& address,
985 int channel_id) {
986 TurnEntry* entry = FindEntry(address);
pthatcher1 2015/12/08 20:04:19 Can we just make FindEntry callable by the unit te
honghaiz3 2015/12/10 17:58:30 If we do that, we will need to make TurnEntry acce
987 if (!entry) {
988 return false;
989 }
990 entry->set_channel_id(channel_id);
991 return true;
992 }
993
961 TurnAllocateRequest::TurnAllocateRequest(TurnPort* port) 994 TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
962 : StunRequest(new TurnMessage()), 995 : StunRequest(new TurnMessage()),
963 port_(port) { 996 port_(port) {
964 } 997 }
965 998
966 void TurnAllocateRequest::Prepare(StunMessage* request) { 999 void TurnAllocateRequest::Prepare(StunMessage* request) {
967 // Create the request as indicated in RFC 5766, Section 6.1. 1000 // Create the request as indicated in RFC 5766, Section 6.1.
968 request->SetType(TURN_ALLOCATE_REQUEST); 1001 request->SetType(TURN_ALLOCATE_REQUEST);
969 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32( 1002 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
970 STUN_ATTR_REQUESTED_TRANSPORT); 1003 STUN_ATTR_REQUESTED_TRANSPORT);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 const StunUInt32Attribute* lifetime_attr = 1197 const StunUInt32Attribute* lifetime_attr =
1165 response->GetUInt32(STUN_ATTR_TURN_LIFETIME); 1198 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
1166 if (!lifetime_attr) { 1199 if (!lifetime_attr) {
1167 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in " 1200 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
1168 << "refresh success response."; 1201 << "refresh success response.";
1169 return; 1202 return;
1170 } 1203 }
1171 1204
1172 // Schedule a refresh based on the returned lifetime value. 1205 // Schedule a refresh based on the returned lifetime value.
1173 port_->ScheduleRefresh(lifetime_attr->value()); 1206 port_->ScheduleRefresh(lifetime_attr->value());
1207 // Result code 0 means the refresh request is successful.
1208 port_->SignalTurnRefreshResult(port_, 0);
pthatcher1 2015/12/08 20:04:19 Can we make a name constant for it? kTurnRefreshS
honghaiz3 2015/12/10 17:58:30 used name RESULT_SUCCESS_CODE. also used this for
1174 } 1209 }
1175 1210
1176 void TurnRefreshRequest::OnErrorResponse(StunMessage* response) { 1211 void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
1177 const StunErrorCodeAttribute* error_code = response->GetErrorCode(); 1212 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1178 1213
1179 LOG_J(LS_INFO, port_) << "Received TURN refresh error response"
1180 << ", id=" << rtc::hex_encode(id())
1181 << ", code=" << error_code->code()
1182 << ", rtt=" << Elapsed();
1183
1184 if (error_code->code() == STUN_ERROR_STALE_NONCE) { 1214 if (error_code->code() == STUN_ERROR_STALE_NONCE) {
1185 if (port_->UpdateNonce(response)) { 1215 if (port_->UpdateNonce(response)) {
1186 // Send RefreshRequest immediately. 1216 // Send RefreshRequest immediately.
1187 port_->SendRequest(new TurnRefreshRequest(port_), 0); 1217 port_->SendRequest(new TurnRefreshRequest(port_), 0);
1188 } 1218 }
1189 } else { 1219 } else {
1190 LOG_J(LS_WARNING, port_) << "Received TURN refresh error response" 1220 LOG_J(LS_WARNING, port_) << "Received TURN refresh error response"
1191 << ", id=" << rtc::hex_encode(id()) 1221 << ", id=" << rtc::hex_encode(id())
1192 << ", code=" << error_code->code() 1222 << ", code=" << error_code->code()
1193 << ", rtt=" << Elapsed(); 1223 << ", rtt=" << Elapsed();
1224 port_->OnTurnRefreshError();
1225 port_->SignalTurnRefreshResult(port_, error_code->code());
1194 } 1226 }
1195 } 1227 }
1196 1228
1197 void TurnRefreshRequest::OnTimeout() { 1229 void TurnRefreshRequest::OnTimeout() {
1198 LOG_J(LS_WARNING, port_) << "TURN refresh timeout " << rtc::hex_encode(id()); 1230 LOG_J(LS_WARNING, port_) << "TURN refresh timeout " << rtc::hex_encode(id());
1231 port_->OnTurnRefreshError();
1199 } 1232 }
1200 1233
1201 TurnCreatePermissionRequest::TurnCreatePermissionRequest( 1234 TurnCreatePermissionRequest::TurnCreatePermissionRequest(
1202 TurnPort* port, TurnEntry* entry, 1235 TurnPort* port, TurnEntry* entry,
1203 const rtc::SocketAddress& ext_addr) 1236 const rtc::SocketAddress& ext_addr)
1204 : StunRequest(new TurnMessage()), 1237 : StunRequest(new TurnMessage()),
1205 port_(port), 1238 port_(port),
1206 entry_(entry), 1239 entry_(entry),
1207 ext_addr_(ext_addr) { 1240 ext_addr_(ext_addr) {
1208 entry_->SignalDestroyed.connect( 1241 entry_->SignalDestroyed.connect(
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 << ", code=" << error_code->code() 1274 << ", code=" << error_code->code()
1242 << ", rtt=" << Elapsed(); 1275 << ", rtt=" << Elapsed();
1243 if (entry_) { 1276 if (entry_) {
1244 entry_->OnCreatePermissionError(response, error_code->code()); 1277 entry_->OnCreatePermissionError(response, error_code->code());
1245 } 1278 }
1246 } 1279 }
1247 1280
1248 void TurnCreatePermissionRequest::OnTimeout() { 1281 void TurnCreatePermissionRequest::OnTimeout() {
1249 LOG_J(LS_WARNING, port_) << "TURN create permission timeout " 1282 LOG_J(LS_WARNING, port_) << "TURN create permission timeout "
1250 << rtc::hex_encode(id()); 1283 << rtc::hex_encode(id());
1284 if (entry_) {
1285 entry_->OnCreatePermissionTimeout();
1286 }
1251 } 1287 }
1252 1288
1253 void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) { 1289 void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
1254 ASSERT(entry_ == entry); 1290 ASSERT(entry_ == entry);
1255 entry_ = NULL; 1291 entry_ = NULL;
1256 } 1292 }
1257 1293
1258 TurnChannelBindRequest::TurnChannelBindRequest( 1294 TurnChannelBindRequest::TurnChannelBindRequest(
1259 TurnPort* port, TurnEntry* entry, 1295 TurnPort* port, TurnEntry* entry,
1260 int channel_id, const rtc::SocketAddress& ext_addr) 1296 int channel_id, const rtc::SocketAddress& ext_addr)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 << ", code=" << error_code->code() 1344 << ", code=" << error_code->code()
1309 << ", rtt=" << Elapsed(); 1345 << ", rtt=" << Elapsed();
1310 if (entry_) { 1346 if (entry_) {
1311 entry_->OnChannelBindError(response, error_code->code()); 1347 entry_->OnChannelBindError(response, error_code->code());
1312 } 1348 }
1313 } 1349 }
1314 1350
1315 void TurnChannelBindRequest::OnTimeout() { 1351 void TurnChannelBindRequest::OnTimeout() {
1316 LOG_J(LS_WARNING, port_) << "TURN channel bind timeout " 1352 LOG_J(LS_WARNING, port_) << "TURN channel bind timeout "
1317 << rtc::hex_encode(id()); 1353 << rtc::hex_encode(id());
1354 if (entry_) {
1355 entry_->OnChannelBindTimeout();
1356 }
1318 } 1357 }
1319 1358
1320 void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) { 1359 void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
1321 ASSERT(entry_ == entry); 1360 ASSERT(entry_ == entry);
1322 entry_ = NULL; 1361 entry_ = NULL;
1323 } 1362 }
1324 1363
1325 TurnEntry::TurnEntry(TurnPort* port, int channel_id, 1364 TurnEntry::TurnEntry(TurnPort* port, int channel_id,
1326 const rtc::SocketAddress& ext_addr) 1365 const rtc::SocketAddress& ext_addr)
1327 : port_(port), 1366 : port_(port),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1389 << delay << "ms."; 1428 << delay << "ms.";
1390 } 1429 }
1391 } 1430 }
1392 1431
1393 void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) { 1432 void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
1394 if (code == STUN_ERROR_STALE_NONCE) { 1433 if (code == STUN_ERROR_STALE_NONCE) {
1395 if (port_->UpdateNonce(response)) { 1434 if (port_->UpdateNonce(response)) {
1396 SendCreatePermissionRequest(0); 1435 SendCreatePermissionRequest(0);
1397 } 1436 }
1398 } else { 1437 } else {
1438 port_->DestroyConnection(ext_addr_);
1399 // Send signal with error code. 1439 // Send signal with error code.
1400 port_->SignalCreatePermissionResult(port_, ext_addr_, code); 1440 port_->SignalCreatePermissionResult(port_, ext_addr_, code);
1401 } 1441 }
1402 } 1442 }
1403 1443
1444 void TurnEntry::OnCreatePermissionTimeout() {
1445 port_->DestroyConnection(ext_addr_);
1446 }
1447
1404 void TurnEntry::OnChannelBindSuccess() { 1448 void TurnEntry::OnChannelBindSuccess() {
1405 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString() 1449 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString()
1406 << " succeeded"; 1450 << " succeeded";
1407 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND); 1451 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND);
1408 state_ = STATE_BOUND; 1452 state_ = STATE_BOUND;
1409 } 1453 }
1410 1454
1411 void TurnEntry::OnChannelBindError(StunMessage* response, int code) { 1455 void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1412 // TODO(mallinath) - Implement handling of error response for channel 1456 // If the channel bind fails due to errors other than STATE_NONCE,
1413 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3 1457 // we just destroy the connection and rely on ICE restart to re-establish
1458 // the connection.
1414 if (code == STUN_ERROR_STALE_NONCE) { 1459 if (code == STUN_ERROR_STALE_NONCE) {
1415 if (port_->UpdateNonce(response)) { 1460 if (port_->UpdateNonce(response)) {
1416 // Send channel bind request with fresh nonce. 1461 // Send channel bind request with fresh nonce.
1417 SendChannelBindRequest(0); 1462 SendChannelBindRequest(0);
1418 } 1463 }
1464 } else {
1465 state_ = STATE_UNBOUND;
1466 port_->DestroyConnection(ext_addr_);
1419 } 1467 }
1420 } 1468 }
1421 1469 void TurnEntry::OnChannelBindTimeout() {
1470 state_ = STATE_UNBOUND;
1471 port_->DestroyConnection(ext_addr_);
1472 }
1422 } // namespace cricket 1473 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698