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

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

Issue 1247573002: Fix a Turn TCP port issue. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 4 months 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
« no previous file with comments | « webrtc/p2p/base/turnport.h ('k') | webrtc/p2p/base/turnport_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 TurnPort::TurnPort(rtc::Thread* thread, 165 TurnPort::TurnPort(rtc::Thread* thread,
166 rtc::PacketSocketFactory* factory, 166 rtc::PacketSocketFactory* factory,
167 rtc::Network* network, 167 rtc::Network* network,
168 rtc::AsyncPacketSocket* socket, 168 rtc::AsyncPacketSocket* socket,
169 const std::string& username, 169 const std::string& username,
170 const std::string& password, 170 const std::string& password,
171 const ProtocolAddress& server_address, 171 const ProtocolAddress& server_address,
172 const RelayCredentials& credentials, 172 const RelayCredentials& credentials,
173 int server_priority, 173 int server_priority,
174 const std::string& origin) 174 const std::string& origin)
175 : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(), 175 : Port(thread,
176 username, password), 176 factory,
177 network,
178 socket->GetLocalAddress().ipaddr(),
179 username,
180 password),
177 server_address_(server_address), 181 server_address_(server_address),
178 credentials_(credentials), 182 credentials_(credentials),
179 socket_(socket), 183 socket_(socket),
180 resolver_(NULL), 184 resolver_(NULL),
181 error_(0), 185 error_(0),
182 request_manager_(thread), 186 request_manager_(thread),
183 next_channel_number_(TURN_CHANNEL_NUMBER_START), 187 next_channel_number_(TURN_CHANNEL_NUMBER_START),
184 connected_(false), 188 state_(STATE_CONNECTING),
185 server_priority_(server_priority), 189 server_priority_(server_priority),
186 allocate_mismatch_retries_(0) { 190 allocate_mismatch_retries_(0) {
187 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket); 191 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
188 request_manager_.set_origin(origin); 192 request_manager_.set_origin(origin);
189 } 193 }
190 194
191 TurnPort::TurnPort(rtc::Thread* thread, 195 TurnPort::TurnPort(rtc::Thread* thread,
192 rtc::PacketSocketFactory* factory, 196 rtc::PacketSocketFactory* factory,
193 rtc::Network* network, 197 rtc::Network* network,
194 const rtc::IPAddress& ip, 198 const rtc::IPAddress& ip,
195 uint16 min_port, 199 uint16 min_port,
196 uint16 max_port, 200 uint16 max_port,
197 const std::string& username, 201 const std::string& username,
198 const std::string& password, 202 const std::string& password,
199 const ProtocolAddress& server_address, 203 const ProtocolAddress& server_address,
200 const RelayCredentials& credentials, 204 const RelayCredentials& credentials,
201 int server_priority, 205 int server_priority,
202 const std::string& origin) 206 const std::string& origin)
203 : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port, 207 : Port(thread,
204 username, password), 208 RELAY_PORT_TYPE,
209 factory,
210 network,
211 ip,
212 min_port,
213 max_port,
214 username,
215 password),
205 server_address_(server_address), 216 server_address_(server_address),
206 credentials_(credentials), 217 credentials_(credentials),
207 socket_(NULL), 218 socket_(NULL),
208 resolver_(NULL), 219 resolver_(NULL),
209 error_(0), 220 error_(0),
210 request_manager_(thread), 221 request_manager_(thread),
211 next_channel_number_(TURN_CHANNEL_NUMBER_START), 222 next_channel_number_(TURN_CHANNEL_NUMBER_START),
212 connected_(false), 223 state_(STATE_CONNECTING),
213 server_priority_(server_priority), 224 server_priority_(server_priority),
214 allocate_mismatch_retries_(0) { 225 allocate_mismatch_retries_(0) {
215 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket); 226 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
216 request_manager_.set_origin(origin); 227 request_manager_.set_origin(origin);
217 } 228 }
218 229
219 TurnPort::~TurnPort() { 230 TurnPort::~TurnPort() {
220 // TODO(juberti): Should this even be necessary? 231 // TODO(juberti): Should this even be necessary?
221 232
222 // release the allocation by sending a refresh with 233 // release the allocation by sending a refresh with
223 // lifetime 0. 234 // lifetime 0.
224 if (connected_) { 235 if (ready()) {
225 TurnRefreshRequest bye(this); 236 TurnRefreshRequest bye(this);
226 bye.set_lifetime(0); 237 bye.set_lifetime(0);
227 SendRequest(&bye, 0); 238 SendRequest(&bye, 0);
228 } 239 }
229 240
230 while (!entries_.empty()) { 241 while (!entries_.empty()) {
231 DestroyEntry(entries_.front()->address()); 242 DestroyEntry(entries_.front()->address());
232 } 243 }
233 if (resolver_) { 244 if (resolver_) {
234 resolver_->Destroy(false); 245 resolver_->Destroy(false);
(...skipping 19 matching lines...) Expand all
254 if (!server_address_.address.port()) { 265 if (!server_address_.address.port()) {
255 // We will set default TURN port, if no port is set in the address. 266 // We will set default TURN port, if no port is set in the address.
256 server_address_.address.SetPort(TURN_DEFAULT_PORT); 267 server_address_.address.SetPort(TURN_DEFAULT_PORT);
257 } 268 }
258 269
259 if (server_address_.address.IsUnresolved()) { 270 if (server_address_.address.IsUnresolved()) {
260 ResolveTurnAddress(server_address_.address); 271 ResolveTurnAddress(server_address_.address);
261 } else { 272 } else {
262 // If protocol family of server address doesn't match with local, return. 273 // If protocol family of server address doesn't match with local, return.
263 if (!IsCompatibleAddress(server_address_.address)) { 274 if (!IsCompatibleAddress(server_address_.address)) {
264 LOG(LS_ERROR) << "Server IP address family does not match with " 275 LOG(LS_ERROR) << "IP address family does not match: "
265 << "local host address family type"; 276 << "server: " << server_address_.address.family()
277 << "local: " << ip().family();
266 OnAllocateError(); 278 OnAllocateError();
267 return; 279 return;
268 } 280 }
269 281
270 // Insert the current address to prevent redirection pingpong. 282 // Insert the current address to prevent redirection pingpong.
271 attempted_server_addresses_.insert(server_address_.address); 283 attempted_server_addresses_.insert(server_address_.address);
272 284
273 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via " 285 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
274 << ProtoToString(server_address_.proto) << " @ " 286 << ProtoToString(server_address_.proto) << " @ "
275 << server_address_.address.ToSensitiveString(); 287 << server_address_.address.ToSensitiveString();
276 if (!CreateTurnClientSocket()) { 288 if (!CreateTurnClientSocket()) {
289 LOG(LS_ERROR) << "Failed to create TURN client socket";
277 OnAllocateError(); 290 OnAllocateError();
278 } else if (server_address_.proto == PROTO_UDP) { 291 return;
292 }
293 if (server_address_.proto == PROTO_UDP) {
279 // If its UDP, send AllocateRequest now. 294 // If its UDP, send AllocateRequest now.
280 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect. 295 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
281 SendRequest(new TurnAllocateRequest(this), 0); 296 SendRequest(new TurnAllocateRequest(this), 0);
282 } 297 }
283 } 298 }
284 } 299 }
285 300
286 bool TurnPort::CreateTurnClientSocket() { 301 bool TurnPort::CreateTurnClientSocket() {
287 ASSERT(!socket_ || SharedSocket()); 302 ASSERT(!socket_ || SharedSocket());
288 303
(...skipping 23 matching lines...) Expand all
312 socket_->SetOption(iter->first, iter->second); 327 socket_->SetOption(iter->first, iter->second);
313 } 328 }
314 329
315 if (!SharedSocket()) { 330 if (!SharedSocket()) {
316 // If socket is shared, AllocationSequence will receive the packet. 331 // If socket is shared, AllocationSequence will receive the packet.
317 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket); 332 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
318 } 333 }
319 334
320 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend); 335 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
321 336
337 // TCP port is ready to send stun requests after the socket is connected,
338 // while UDP port is ready to do so once the socket is created.
322 if (server_address_.proto == PROTO_TCP) { 339 if (server_address_.proto == PROTO_TCP) {
323 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect); 340 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
324 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose); 341 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
342 } else {
343 state_ = STATE_CONNECTED;
325 } 344 }
326 return true; 345 return true;
327 } 346 }
328 347
329 void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) { 348 void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
330 ASSERT(server_address_.proto == PROTO_TCP); 349 ASSERT(server_address_.proto == PROTO_TCP);
331 // Do not use this port if the socket bound to a different address than 350 // Do not use this port if the socket bound to a different address than
332 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be 351 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be
333 // given a binding address, and the platform is expected to pick the 352 // given a binding address, and the platform is expected to pick the
334 // correct local address. 353 // correct local address.
(...skipping 18 matching lines...) Expand all
353 } else { 372 } else {
354 LOG(LS_WARNING) << "Socket is bound to a different address:" 373 LOG(LS_WARNING) << "Socket is bound to a different address:"
355 << socket->GetLocalAddress().ipaddr().ToString() 374 << socket->GetLocalAddress().ipaddr().ToString()
356 << ", rather then the local port:" << ip().ToString() 375 << ", rather then the local port:" << ip().ToString()
357 << ". Discarding TURN port."; 376 << ". Discarding TURN port.";
358 OnAllocateError(); 377 OnAllocateError();
359 return; 378 return;
360 } 379 }
361 } 380 }
362 381
382 state_ = STATE_CONNECTED; // It is ready to send stun requests.
363 if (server_address_.address.IsUnresolved()) { 383 if (server_address_.address.IsUnresolved()) {
364 server_address_.address = socket_->GetRemoteAddress(); 384 server_address_.address = socket_->GetRemoteAddress();
365 } 385 }
366 386
367 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress() 387 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
368 << " using tcp."; 388 << " using tcp.";
369 SendRequest(new TurnAllocateRequest(this), 0); 389 SendRequest(new TurnAllocateRequest(this), 0);
370 } 390 }
371 391
372 void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) { 392 void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
373 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error; 393 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
374 ASSERT(socket == socket_); 394 ASSERT(socket == socket_);
375 if (!connected_) { 395 if (!ready()) {
376 OnAllocateError(); 396 OnAllocateError();
377 } 397 }
378 connected_ = false; 398 request_manager_.Clear();
399 state_ = STATE_DISCONNECTED;
379 } 400 }
380 401
381 void TurnPort::OnAllocateMismatch() { 402 void TurnPort::OnAllocateMismatch() {
382 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) { 403 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
383 LOG_J(LS_WARNING, this) << "Giving up on the port after " 404 LOG_J(LS_WARNING, this) << "Giving up on the port after "
384 << allocate_mismatch_retries_ 405 << allocate_mismatch_retries_
385 << " retries for STUN_ERROR_ALLOCATION_MISMATCH"; 406 << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
386 OnAllocateError(); 407 OnAllocateError();
387 return; 408 return;
388 } 409 }
(...skipping 16 matching lines...) Expand all
405 CandidateOrigin origin) { 426 CandidateOrigin origin) {
406 // TURN-UDP can only connect to UDP candidates. 427 // TURN-UDP can only connect to UDP candidates.
407 if (address.protocol() != UDP_PROTOCOL_NAME) { 428 if (address.protocol() != UDP_PROTOCOL_NAME) {
408 return NULL; 429 return NULL;
409 } 430 }
410 431
411 if (!IsCompatibleAddress(address.address())) { 432 if (!IsCompatibleAddress(address.address())) {
412 return NULL; 433 return NULL;
413 } 434 }
414 435
436 if (state_ == STATE_DISCONNECTED) {
437 return NULL;
438 }
439
415 // Create an entry, if needed, so we can get our permissions set up correctly. 440 // Create an entry, if needed, so we can get our permissions set up correctly.
416 CreateEntry(address.address()); 441 CreateEntry(address.address());
417 442
418 // A TURN port will have two candiates, STUN and TURN. STUN may not 443 // A TURN port will have two candiates, STUN and TURN. STUN may not
419 // present in all cases. If present stun candidate will be added first 444 // present in all cases. If present stun candidate will be added first
420 // and TURN candidate later. 445 // and TURN candidate later.
421 for (size_t index = 0; index < Candidates().size(); ++index) { 446 for (size_t index = 0; index < Candidates().size(); ++index) {
422 if (Candidates()[index].type() == RELAY_PORT_TYPE) { 447 if (Candidates()[index].type() == RELAY_PORT_TYPE) {
423 ProxyConnection* conn = new ProxyConnection(this, index, address); 448 ProxyConnection* conn = new ProxyConnection(this, index, address);
424 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed); 449 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
(...skipping 30 matching lines...) Expand all
455 int TurnPort::GetError() { 480 int TurnPort::GetError() {
456 return error_; 481 return error_;
457 } 482 }
458 483
459 int TurnPort::SendTo(const void* data, size_t size, 484 int TurnPort::SendTo(const void* data, size_t size,
460 const rtc::SocketAddress& addr, 485 const rtc::SocketAddress& addr,
461 const rtc::PacketOptions& options, 486 const rtc::PacketOptions& options,
462 bool payload) { 487 bool payload) {
463 // Try to find an entry for this specific address; we should have one. 488 // Try to find an entry for this specific address; we should have one.
464 TurnEntry* entry = FindEntry(addr); 489 TurnEntry* entry = FindEntry(addr);
465 ASSERT(entry != NULL);
466 if (!entry) { 490 if (!entry) {
491 LOG(LS_ERROR) << "Did not find the TurnEntry for address " << addr;
467 return 0; 492 return 0;
468 } 493 }
469 494
470 if (!connected()) { 495 if (!ready()) {
471 error_ = EWOULDBLOCK; 496 error_ = EWOULDBLOCK;
472 return SOCKET_ERROR; 497 return SOCKET_ERROR;
473 } 498 }
474 499
475 // Send the actual contents to the server using the usual mechanism. 500 // Send the actual contents to the server using the usual mechanism.
476 int sent = entry->Send(data, size, payload, options); 501 int sent = entry->Send(data, size, payload, options);
477 if (sent <= 0) { 502 if (sent <= 0) {
478 return SOCKET_ERROR; 503 return SOCKET_ERROR;
479 } 504 }
480 505
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 !StunMessage::ValidateMessageIntegrity(data, size, hash())) { 554 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
530 LOG_J(LS_WARNING, this) << "Received TURN message with invalid " 555 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
531 << "message integrity, msg_type=" << msg_type; 556 << "message integrity, msg_type=" << msg_type;
532 return; 557 return;
533 } 558 }
534 request_manager_.CheckResponse(data, size); 559 request_manager_.CheckResponse(data, size);
535 } 560 }
536 } 561 }
537 562
538 void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) { 563 void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
539 if (connected_) { 564 if (ready()) {
540 Port::OnReadyToSend(); 565 Port::OnReadyToSend();
541 } 566 }
542 } 567 }
543 568
544 569
545 // Update current server address port with the alternate server address port. 570 // Update current server address port with the alternate server address port.
546 bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) { 571 bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
547 // Check if we have seen this address before and reject if we did. 572 // Check if we have seen this address before and reject if we did.
548 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address); 573 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
549 if (iter != attempted_server_addresses_.end()) { 574 if (iter != attempted_server_addresses_.end()) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 // Signal needs both resolved and unresolved address. After signal is sent 634 // Signal needs both resolved and unresolved address. After signal is sent
610 // we can copy resolved address back into |server_address_|. 635 // we can copy resolved address back into |server_address_|.
611 SignalResolvedServerAddress(this, server_address_.address, 636 SignalResolvedServerAddress(this, server_address_.address,
612 resolved_address); 637 resolved_address);
613 server_address_.address = resolved_address; 638 server_address_.address = resolved_address;
614 PrepareAddress(); 639 PrepareAddress();
615 } 640 }
616 641
617 void TurnPort::OnSendStunPacket(const void* data, size_t size, 642 void TurnPort::OnSendStunPacket(const void* data, size_t size,
618 StunRequest* request) { 643 StunRequest* request) {
644 ASSERT(connected());
619 rtc::PacketOptions options(DefaultDscpValue()); 645 rtc::PacketOptions options(DefaultDscpValue());
620 if (Send(data, size, options) < 0) { 646 if (Send(data, size, options) < 0) {
621 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err=" 647 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
622 << socket_->GetError(); 648 << socket_->GetError();
623 } 649 }
624 } 650 }
625 651
626 void TurnPort::OnStunAddress(const rtc::SocketAddress& address) { 652 void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
627 // STUN Port will discover STUN candidate, as it's supplied with first TURN 653 // STUN Port will discover STUN candidate, as it's supplied with first TURN
628 // server address. 654 // server address.
629 // Why not using this address? - P2PTransportChannel will start creating 655 // Why not using this address? - P2PTransportChannel will start creating
630 // connections after first candidate, which means it could start creating the 656 // connections after first candidate, which means it could start creating the
631 // connections before TURN candidate added. For that to handle, we need to 657 // connections before TURN candidate added. For that to handle, we need to
632 // supply STUN candidate from this port to UDPPort, and TurnPort should have 658 // supply STUN candidate from this port to UDPPort, and TurnPort should have
633 // handle to UDPPort to pass back the address. 659 // handle to UDPPort to pass back the address.
634 } 660 }
635 661
636 void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address, 662 void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
637 const rtc::SocketAddress& stun_address) { 663 const rtc::SocketAddress& stun_address) {
638 connected_ = true; 664 state_ = STATE_READY;
639 665
640 rtc::SocketAddress related_address = stun_address; 666 rtc::SocketAddress related_address = stun_address;
641 if (!(candidate_filter() & CF_REFLEXIVE)) { 667 if (!(candidate_filter() & CF_REFLEXIVE)) {
642 // If candidate filter only allows relay type of address, empty raddr to 668 // If candidate filter only allows relay type of address, empty raddr to
643 // avoid local address leakage. 669 // avoid local address leakage.
644 related_address = rtc::EmptySocketAddressWithFamily(stun_address.family()); 670 related_address = rtc::EmptySocketAddressWithFamily(stun_address.family());
645 } 671 }
646 672
647 // For relayed candidate, Base is the candidate itself. 673 // For relayed candidate, Base is the candidate itself.
648 AddAddress(address, // Candidate address. 674 AddAddress(address, // Candidate address.
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3 1362 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
1337 if (code == STUN_ERROR_STALE_NONCE) { 1363 if (code == STUN_ERROR_STALE_NONCE) {
1338 if (port_->UpdateNonce(response)) { 1364 if (port_->UpdateNonce(response)) {
1339 // Send channel bind request with fresh nonce. 1365 // Send channel bind request with fresh nonce.
1340 SendChannelBindRequest(0); 1366 SendChannelBindRequest(0);
1341 } 1367 }
1342 } 1368 }
1343 } 1369 }
1344 1370
1345 } // namespace cricket 1371 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/turnport.h ('k') | webrtc/p2p/base/turnport_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698