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

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: Slight change in asynctcpsocket.cc 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
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 port_state_(DISCONNECTED),
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 port_state_(DISCONNECTED),
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 (connected()) {
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: "
juberti1 2015/07/29 05:28:13 Address -> address
honghaiz3 2015/07/29 21:44:13 Done.
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
301 void TurnPort::SendAllocateRequest(int delay) {
302 SendRequest(new TurnAllocateRequest(this), delay);
303 }
304
286 bool TurnPort::CreateTurnClientSocket() { 305 bool TurnPort::CreateTurnClientSocket() {
287 ASSERT(!socket_ || SharedSocket()); 306 ASSERT(!socket_ || SharedSocket());
288 307
289 if (server_address_.proto == PROTO_UDP && !SharedSocket()) { 308 if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
290 socket_ = socket_factory()->CreateUdpSocket( 309 socket_ = socket_factory()->CreateUdpSocket(
291 rtc::SocketAddress(ip(), 0), min_port(), max_port()); 310 rtc::SocketAddress(ip(), 0), min_port(), max_port());
292 } else if (server_address_.proto == PROTO_TCP) { 311 } else if (server_address_.proto == PROTO_TCP) {
293 ASSERT(!SharedSocket()); 312 ASSERT(!SharedSocket());
294 int opts = rtc::PacketSocketFactory::OPT_STUN; 313 int opts = rtc::PacketSocketFactory::OPT_STUN;
295 // If secure bit is enabled in server address, use TLS over TCP. 314 // If secure bit is enabled in server address, use TLS over TCP.
(...skipping 16 matching lines...) Expand all
312 socket_->SetOption(iter->first, iter->second); 331 socket_->SetOption(iter->first, iter->second);
313 } 332 }
314 333
315 if (!SharedSocket()) { 334 if (!SharedSocket()) {
316 // If socket is shared, AllocationSequence will receive the packet. 335 // If socket is shared, AllocationSequence will receive the packet.
317 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket); 336 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
318 } 337 }
319 338
320 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend); 339 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
321 340
341 // TCP port becomes CONNECTING after the socket is connected,
juberti1 2015/07/29 05:28:13 The port becomes connecting after the socket is co
pthatcher1 2015/07/29 20:51:50 It's already like that in the existing code, where
honghaiz3 2015/07/29 21:44:13 If we change the name, we'd better change all thre
juberti1 2015/07/30 20:47:40 how about STATE_CONNECTING (init), STATE_CONNECTED
pthatcher1 2015/07/30 21:29:16 That sounds fine. The only strange part is that c
honghaiz3 2015/07/30 21:35:05 Well, I can change the method to ready() :) STAT
342 // while UDP port becomes CONNECTING once the socket is created.
322 if (server_address_.proto == PROTO_TCP) { 343 if (server_address_.proto == PROTO_TCP) {
323 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect); 344 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
324 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose); 345 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
346 } else {
347 port_state_ = CONNECTING;
325 } 348 }
326 return true; 349 return true;
327 } 350 }
328 351
329 void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) { 352 void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
330 ASSERT(server_address_.proto == PROTO_TCP); 353 ASSERT(server_address_.proto == PROTO_TCP);
331 // Do not use this port if the socket bound to a different address than 354 // 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 355 // 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 356 // given a binding address, and the platform is expected to pick the
334 // correct local address. 357 // correct local address.
(...skipping 18 matching lines...) Expand all
353 } else { 376 } else {
354 LOG(LS_WARNING) << "Socket is bound to a different address:" 377 LOG(LS_WARNING) << "Socket is bound to a different address:"
355 << socket->GetLocalAddress().ipaddr().ToString() 378 << socket->GetLocalAddress().ipaddr().ToString()
356 << ", rather then the local port:" << ip().ToString() 379 << ", rather then the local port:" << ip().ToString()
357 << ". Discarding TURN port."; 380 << ". Discarding TURN port.";
358 OnAllocateError(); 381 OnAllocateError();
359 return; 382 return;
360 } 383 }
361 } 384 }
362 385
386 port_state_ = CONNECTING; // It is ready to send stun requests.
363 if (server_address_.address.IsUnresolved()) { 387 if (server_address_.address.IsUnresolved()) {
364 server_address_.address = socket_->GetRemoteAddress(); 388 server_address_.address = socket_->GetRemoteAddress();
365 } 389 }
366 390
367 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress() 391 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
368 << " using tcp."; 392 << " using tcp.";
369 SendRequest(new TurnAllocateRequest(this), 0); 393 SendRequest(new TurnAllocateRequest(this), 0);
370 } 394 }
371 395
372 void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) { 396 void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
373 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error; 397 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
374 ASSERT(socket == socket_); 398 ASSERT(socket == socket_);
375 if (!connected_) { 399 if (port_state_ == DISCONNECTED) {
376 OnAllocateError(); 400 OnAllocateError();
377 } 401 }
378 connected_ = false; 402 port_state_ = DISCONNECTED;
379 } 403 }
380 404
381 void TurnPort::OnAllocateMismatch() { 405 void TurnPort::OnAllocateMismatch() {
382 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) { 406 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
383 LOG_J(LS_WARNING, this) << "Giving up on the port after " 407 LOG_J(LS_WARNING, this) << "Giving up on the port after "
384 << allocate_mismatch_retries_ 408 << allocate_mismatch_retries_
385 << " retries for STUN_ERROR_ALLOCATION_MISMATCH"; 409 << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
386 OnAllocateError(); 410 OnAllocateError();
387 return; 411 return;
388 } 412 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 int TurnPort::GetError() { 479 int TurnPort::GetError() {
456 return error_; 480 return error_;
457 } 481 }
458 482
459 int TurnPort::SendTo(const void* data, size_t size, 483 int TurnPort::SendTo(const void* data, size_t size,
460 const rtc::SocketAddress& addr, 484 const rtc::SocketAddress& addr,
461 const rtc::PacketOptions& options, 485 const rtc::PacketOptions& options,
462 bool payload) { 486 bool payload) {
463 // Try to find an entry for this specific address; we should have one. 487 // Try to find an entry for this specific address; we should have one.
464 TurnEntry* entry = FindEntry(addr); 488 TurnEntry* entry = FindEntry(addr);
465 ASSERT(entry != NULL);
466 if (!entry) { 489 if (!entry) {
490 LOG(LS_ERROR) << "Did not find the TurnEntry for address " << addr;
467 return 0; 491 return 0;
468 } 492 }
469 493
470 if (!connected()) { 494 if (!connected()) {
471 error_ = EWOULDBLOCK; 495 error_ = EWOULDBLOCK;
472 return SOCKET_ERROR; 496 return SOCKET_ERROR;
473 } 497 }
474 498
475 // Send the actual contents to the server using the usual mechanism. 499 // Send the actual contents to the server using the usual mechanism.
476 int sent = entry->Send(data, size, payload, options); 500 int sent = entry->Send(data, size, payload, options);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 !StunMessage::ValidateMessageIntegrity(data, size, hash())) { 553 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
530 LOG_J(LS_WARNING, this) << "Received TURN message with invalid " 554 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
531 << "message integrity, msg_type=" << msg_type; 555 << "message integrity, msg_type=" << msg_type;
532 return; 556 return;
533 } 557 }
534 request_manager_.CheckResponse(data, size); 558 request_manager_.CheckResponse(data, size);
535 } 559 }
536 } 560 }
537 561
538 void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) { 562 void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
539 if (connected_) { 563 if (connected()) {
540 Port::OnReadyToSend(); 564 Port::OnReadyToSend();
541 } 565 }
542 } 566 }
543 567
544 568
545 // Update current server address port with the alternate server address port. 569 // Update current server address port with the alternate server address port.
546 bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) { 570 bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
547 // Check if we have seen this address before and reject if we did. 571 // Check if we have seen this address before and reject if we did.
548 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address); 572 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
549 if (iter != attempted_server_addresses_.end()) { 573 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 633 // Signal needs both resolved and unresolved address. After signal is sent
610 // we can copy resolved address back into |server_address_|. 634 // we can copy resolved address back into |server_address_|.
611 SignalResolvedServerAddress(this, server_address_.address, 635 SignalResolvedServerAddress(this, server_address_.address,
612 resolved_address); 636 resolved_address);
613 server_address_.address = resolved_address; 637 server_address_.address = resolved_address;
614 PrepareAddress(); 638 PrepareAddress();
615 } 639 }
616 640
617 void TurnPort::OnSendStunPacket(const void* data, size_t size, 641 void TurnPort::OnSendStunPacket(const void* data, size_t size,
618 StunRequest* request) { 642 StunRequest* request) {
643 if (port_state_ == DISCONNECTED) {
juberti1 2015/07/29 05:28:13 Could we just flush pending packets when the conne
pthatcher1 2015/07/29 20:51:50 We could add a StunRequestManager::RemoveAll that
honghaiz3 2015/07/29 21:44:13 Actually there is a request_manager_->Clear method
pthatcher1 2015/07/29 22:00:10 But if RequestManager called thread_->Clear(), I t
juberti1 2015/07/30 18:22:33 I think Clear() + a check during permission creati
honghaiz3 2015/07/30 18:38:27 That means we will keep all the changes on the Por
juberti1 2015/07/30 20:47:40 right. We would ASSERT if we get a packet when STA
honghaiz3 2015/07/31 00:17:06 Done.
644 LOG(LS_WARNING) << "Dropping STUN request because port is disconnected";
645 return;
646 }
619 rtc::PacketOptions options(DefaultDscpValue()); 647 rtc::PacketOptions options(DefaultDscpValue());
620 if (Send(data, size, options) < 0) { 648 if (Send(data, size, options) < 0) {
621 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err=" 649 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
622 << socket_->GetError(); 650 << socket_->GetError();
623 } 651 }
624 } 652 }
625 653
626 void TurnPort::OnStunAddress(const rtc::SocketAddress& address) { 654 void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
627 // STUN Port will discover STUN candidate, as it's supplied with first TURN 655 // STUN Port will discover STUN candidate, as it's supplied with first TURN
628 // server address. 656 // server address.
629 // Why not using this address? - P2PTransportChannel will start creating 657 // Why not using this address? - P2PTransportChannel will start creating
630 // connections after first candidate, which means it could start creating the 658 // connections after first candidate, which means it could start creating the
631 // connections before TURN candidate added. For that to handle, we need to 659 // 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 660 // supply STUN candidate from this port to UDPPort, and TurnPort should have
633 // handle to UDPPort to pass back the address. 661 // handle to UDPPort to pass back the address.
634 } 662 }
635 663
636 void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address, 664 void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
637 const rtc::SocketAddress& stun_address) { 665 const rtc::SocketAddress& stun_address) {
638 connected_ = true; 666 port_state_ = CONNECTED;
639 667
640 rtc::SocketAddress related_address = stun_address; 668 rtc::SocketAddress related_address = stun_address;
641 if (!(candidate_filter() & CF_REFLEXIVE)) { 669 if (!(candidate_filter() & CF_REFLEXIVE)) {
642 // If candidate filter only allows relay type of address, empty raddr to 670 // If candidate filter only allows relay type of address, empty raddr to
643 // avoid local address leakage. 671 // avoid local address leakage.
644 related_address = rtc::EmptySocketAddressWithFamily(stun_address.family()); 672 related_address = rtc::EmptySocketAddressWithFamily(stun_address.family());
645 } 673 }
646 674
647 // For relayed candidate, Base is the candidate itself. 675 // For relayed candidate, Base is the candidate itself.
648 AddAddress(address, // Candidate address. 676 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 1364 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
1337 if (code == STUN_ERROR_STALE_NONCE) { 1365 if (code == STUN_ERROR_STALE_NONCE) {
1338 if (port_->UpdateNonce(response)) { 1366 if (port_->UpdateNonce(response)) {
1339 // Send channel bind request with fresh nonce. 1367 // Send channel bind request with fresh nonce.
1340 SendChannelBindRequest(0); 1368 SendChannelBindRequest(0);
1341 } 1369 }
1342 } 1370 }
1343 } 1371 }
1344 1372
1345 } // namespace cricket 1373 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698