OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 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 |
11 #include "webrtc/p2p/base/p2ptransportchannel.h" | 11 #include "webrtc/p2p/base/p2ptransportchannel.h" |
12 | 12 |
13 #include <set> | 13 #include <set> |
| 14 #include <algorithm> |
14 #include "webrtc/p2p/base/common.h" | 15 #include "webrtc/p2p/base/common.h" |
15 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. | 16 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. |
16 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. | 17 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. |
17 #include "webrtc/base/common.h" | 18 #include "webrtc/base/common.h" |
18 #include "webrtc/base/crc32.h" | 19 #include "webrtc/base/crc32.h" |
19 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
20 #include "webrtc/base/stringencode.h" | 21 #include "webrtc/base/stringencode.h" |
21 | 22 |
22 namespace { | 23 namespace { |
23 | 24 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; | 174 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; |
174 } | 175 } |
175 | 176 |
176 } // unnamed namespace | 177 } // unnamed namespace |
177 | 178 |
178 namespace cricket { | 179 namespace cricket { |
179 | 180 |
180 P2PTransportChannel::P2PTransportChannel(const std::string& content_name, | 181 P2PTransportChannel::P2PTransportChannel(const std::string& content_name, |
181 int component, | 182 int component, |
182 P2PTransport* transport, | 183 P2PTransport* transport, |
183 PortAllocator *allocator) : | 184 PortAllocator* allocator) |
184 TransportChannelImpl(content_name, component), | 185 : TransportChannelImpl(content_name, component), |
185 transport_(transport), | 186 transport_(transport), |
186 allocator_(allocator), | 187 allocator_(allocator), |
187 worker_thread_(rtc::Thread::Current()), | 188 worker_thread_(rtc::Thread::Current()), |
188 incoming_only_(false), | 189 incoming_only_(false), |
189 waiting_for_signaling_(false), | 190 error_(0), |
190 error_(0), | 191 best_connection_(NULL), |
191 best_connection_(NULL), | 192 pending_best_connection_(NULL), |
192 pending_best_connection_(NULL), | 193 sort_dirty_(false), |
193 sort_dirty_(false), | 194 was_writable_(false), |
194 was_writable_(false), | 195 protocol_type_(ICEPROTO_HYBRID), |
195 protocol_type_(ICEPROTO_HYBRID), | 196 remote_ice_mode_(ICEMODE_FULL), |
196 remote_ice_mode_(ICEMODE_FULL), | 197 ice_role_(ICEROLE_UNKNOWN), |
197 ice_role_(ICEROLE_UNKNOWN), | 198 tiebreaker_(0), |
198 tiebreaker_(0), | 199 remote_candidate_generation_(0), |
199 remote_candidate_generation_(0), | 200 gathering_state_(kGatheringNew), |
200 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), | 201 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |
201 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { | 202 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { |
202 } | 203 } |
203 | 204 |
204 P2PTransportChannel::~P2PTransportChannel() { | 205 P2PTransportChannel::~P2PTransportChannel() { |
205 ASSERT(worker_thread_ == rtc::Thread::Current()); | 206 ASSERT(worker_thread_ == rtc::Thread::Current()); |
206 | 207 |
207 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) | 208 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) |
208 delete allocator_sessions_[i]; | 209 delete allocator_sessions_[i]; |
209 } | 210 } |
210 | 211 |
211 // Add the allocator session to our list so that we know which sessions | 212 // Add the allocator session to our list so that we know which sessions |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 // ice ufrag or password. | 319 // ice ufrag or password. |
319 ice_restart = | 320 ice_restart = |
320 IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd); | 321 IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd); |
321 } | 322 } |
322 | 323 |
323 ice_ufrag_ = ice_ufrag; | 324 ice_ufrag_ = ice_ufrag; |
324 ice_pwd_ = ice_pwd; | 325 ice_pwd_ = ice_pwd; |
325 | 326 |
326 if (ice_restart) { | 327 if (ice_restart) { |
327 // Restart candidate gathering. | 328 // Restart candidate gathering. |
328 Allocate(); | 329 StartGatheringCandidates(); |
329 } | 330 } |
330 } | 331 } |
331 | 332 |
332 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag, | 333 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag, |
333 const std::string& ice_pwd) { | 334 const std::string& ice_pwd) { |
334 ASSERT(worker_thread_ == rtc::Thread::Current()); | 335 ASSERT(worker_thread_ == rtc::Thread::Current()); |
335 bool ice_restart = false; | 336 bool ice_restart = false; |
336 if (!remote_ice_ufrag_.empty() && !remote_ice_pwd_.empty()) { | 337 if (!remote_ice_ufrag_.empty() && !remote_ice_pwd_.empty()) { |
337 ice_restart = (remote_ice_ufrag_ != ice_ufrag) || | 338 ice_restart = (remote_ice_ufrag_ != ice_ufrag) || |
338 (remote_ice_pwd_!= ice_pwd); | 339 (remote_ice_pwd_!= ice_pwd); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 void P2PTransportChannel::Connect() { | 375 void P2PTransportChannel::Connect() { |
375 ASSERT(worker_thread_ == rtc::Thread::Current()); | 376 ASSERT(worker_thread_ == rtc::Thread::Current()); |
376 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 377 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
377 ASSERT(false); | 378 ASSERT(false); |
378 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 379 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
379 << "ice_pwd_ are not set."; | 380 << "ice_pwd_ are not set."; |
380 return; | 381 return; |
381 } | 382 } |
382 | 383 |
383 // Kick off an allocator session | 384 // Kick off an allocator session |
384 Allocate(); | 385 StartGatheringCandidates(); |
385 | 386 |
386 // Start pinging as the ports come in. | 387 // Start pinging as the ports come in. |
387 thread()->Post(this, MSG_PING); | 388 thread()->Post(this, MSG_PING); |
388 | 389 |
389 thread()->PostDelayed( | 390 thread()->PostDelayed( |
390 check_receiving_delay_, this, MSG_CHECK_RECEIVING); | 391 check_receiving_delay_, this, MSG_CHECK_RECEIVING); |
391 } | 392 } |
392 | 393 |
393 // A new port is available, attempt to make connections for it | 394 // A new port is available, attempt to make connections for it |
394 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 395 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); | 429 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); |
429 ++iter) { | 430 ++iter) { |
430 CreateConnection(port, *iter, iter->origin_port(), false); | 431 CreateConnection(port, *iter, iter->origin_port(), false); |
431 } | 432 } |
432 | 433 |
433 SortConnections(); | 434 SortConnections(); |
434 } | 435 } |
435 | 436 |
436 // A new candidate is available, let listeners know | 437 // A new candidate is available, let listeners know |
437 void P2PTransportChannel::OnCandidatesReady( | 438 void P2PTransportChannel::OnCandidatesReady( |
438 PortAllocatorSession *session, const std::vector<Candidate>& candidates) { | 439 PortAllocatorSession* session, |
| 440 const std::vector<Candidate>& candidates) { |
439 ASSERT(worker_thread_ == rtc::Thread::Current()); | 441 ASSERT(worker_thread_ == rtc::Thread::Current()); |
440 for (size_t i = 0; i < candidates.size(); ++i) { | 442 for (size_t i = 0; i < candidates.size(); ++i) { |
441 SignalCandidateReady(this, candidates[i]); | 443 SignalCandidateGathered(this, candidates[i]); |
442 } | 444 } |
443 } | 445 } |
444 | 446 |
445 void P2PTransportChannel::OnCandidatesAllocationDone( | 447 void P2PTransportChannel::OnCandidatesAllocationDone( |
446 PortAllocatorSession* session) { | 448 PortAllocatorSession* session) { |
447 ASSERT(worker_thread_ == rtc::Thread::Current()); | 449 ASSERT(worker_thread_ == rtc::Thread::Current()); |
448 SignalCandidatesAllocationDone(this); | 450 gathering_state_ = kGatheringComplete; |
| 451 LOG(LS_INFO) << "P2PTransportChannel: " << content_name() << ", component " |
| 452 << component() << " gathering complete"; |
| 453 SignalGatheringState(this); |
449 } | 454 } |
450 | 455 |
451 // Handle stun packets | 456 // Handle stun packets |
452 void P2PTransportChannel::OnUnknownAddress( | 457 void P2PTransportChannel::OnUnknownAddress( |
453 PortInterface* port, | 458 PortInterface* port, |
454 const rtc::SocketAddress& address, ProtocolType proto, | 459 const rtc::SocketAddress& address, ProtocolType proto, |
455 IceMessage* stun_msg, const std::string &remote_username, | 460 IceMessage* stun_msg, const std::string &remote_username, |
456 bool port_muxed) { | 461 bool port_muxed) { |
457 ASSERT(worker_thread_ == rtc::Thread::Current()); | 462 ASSERT(worker_thread_ == rtc::Thread::Current()); |
458 | 463 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 // connection in question. | 629 // connection in question. |
625 SortConnections(); | 630 SortConnections(); |
626 } | 631 } |
627 } | 632 } |
628 | 633 |
629 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { | 634 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { |
630 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called | 635 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called |
631 // from Transport. | 636 // from Transport. |
632 } | 637 } |
633 | 638 |
634 // When the signalling channel is ready, we can really kick off the allocator | |
635 void P2PTransportChannel::OnSignalingReady() { | |
636 ASSERT(worker_thread_ == rtc::Thread::Current()); | |
637 if (waiting_for_signaling_) { | |
638 waiting_for_signaling_ = false; | |
639 AddAllocatorSession(allocator_->CreateSession( | |
640 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); | |
641 } | |
642 } | |
643 | |
644 void P2PTransportChannel::OnUseCandidate(Connection* conn) { | 639 void P2PTransportChannel::OnUseCandidate(Connection* conn) { |
645 ASSERT(worker_thread_ == rtc::Thread::Current()); | 640 ASSERT(worker_thread_ == rtc::Thread::Current()); |
646 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 641 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
647 ASSERT(protocol_type_ == ICEPROTO_RFC5245); | 642 ASSERT(protocol_type_ == ICEPROTO_RFC5245); |
648 | 643 |
649 if (conn->write_state() == Connection::STATE_WRITABLE) { | 644 if (conn->write_state() == Connection::STATE_WRITABLE) { |
650 if (best_connection_ != conn) { | 645 if (best_connection_ != conn) { |
651 pending_best_connection_ = NULL; | 646 pending_best_connection_ = NULL; |
652 LOG(LS_INFO) << "Switching best connection on controlled side: " | 647 LOG(LS_INFO) << "Switching best connection on controlled side: " |
653 << conn->ToString(); | 648 << conn->ToString(); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 return sent; | 905 return sent; |
911 } | 906 } |
912 | 907 |
913 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 908 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
914 ASSERT(worker_thread_ == rtc::Thread::Current()); | 909 ASSERT(worker_thread_ == rtc::Thread::Current()); |
915 // Gather connection infos. | 910 // Gather connection infos. |
916 infos->clear(); | 911 infos->clear(); |
917 | 912 |
918 std::vector<Connection *>::const_iterator it; | 913 std::vector<Connection *>::const_iterator it; |
919 for (it = connections_.begin(); it != connections_.end(); ++it) { | 914 for (it = connections_.begin(); it != connections_.end(); ++it) { |
920 Connection *connection = *it; | 915 Connection* connection = *it; |
921 ConnectionInfo info; | 916 ConnectionInfo info; |
922 info.best_connection = (best_connection_ == connection); | 917 info.best_connection = (best_connection_ == connection); |
923 info.readable = | 918 info.readable = |
924 (connection->read_state() == Connection::STATE_READABLE); | 919 (connection->read_state() == Connection::STATE_READABLE); |
925 info.writable = | 920 info.writable = |
926 (connection->write_state() == Connection::STATE_WRITABLE); | 921 (connection->write_state() == Connection::STATE_WRITABLE); |
927 info.timeout = | 922 info.timeout = |
928 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 923 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
929 info.new_connection = !connection->reported(); | 924 info.new_connection = !connection->reported(); |
930 connection->set_reported(true); | 925 connection->set_reported(true); |
(...skipping 14 matching lines...) Expand all Loading... |
945 } | 940 } |
946 | 941 |
947 rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const { | 942 rtc::DiffServCodePoint P2PTransportChannel::DefaultDscpValue() const { |
948 OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP); | 943 OptionMap::const_iterator it = options_.find(rtc::Socket::OPT_DSCP); |
949 if (it == options_.end()) { | 944 if (it == options_.end()) { |
950 return rtc::DSCP_NO_CHANGE; | 945 return rtc::DSCP_NO_CHANGE; |
951 } | 946 } |
952 return static_cast<rtc::DiffServCodePoint> (it->second); | 947 return static_cast<rtc::DiffServCodePoint> (it->second); |
953 } | 948 } |
954 | 949 |
955 // Begin allocate (or immediately re-allocate, if MSG_ALLOCATE pending) | 950 void P2PTransportChannel::StartGatheringCandidates() { |
956 void P2PTransportChannel::Allocate() { | 951 // Time for a new allocator |
957 // Time for a new allocator, lets make sure we have a signalling channel | 952 if (gathering_state_ != kGatheringGathering) { |
958 // to communicate candidates through first. | 953 gathering_state_ = kGatheringGathering; |
959 waiting_for_signaling_ = true; | 954 SignalGatheringState(this); |
960 SignalRequestSignaling(this); | 955 } |
| 956 AddAllocatorSession(allocator_->CreateSession( |
| 957 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); |
961 } | 958 } |
962 | 959 |
963 // Monitor connection states. | 960 // Monitor connection states. |
964 void P2PTransportChannel::UpdateConnectionStates() { | 961 void P2PTransportChannel::UpdateConnectionStates() { |
965 uint32 now = rtc::Time(); | 962 uint32 now = rtc::Time(); |
966 | 963 |
967 // We need to copy the list of connections since some may delete themselves | 964 // We need to copy the list of connections since some may delete themselves |
968 // when we call UpdateState. | 965 // when we call UpdateState. |
969 for (uint32 i = 0; i < connections_.size(); ++i) | 966 for (uint32 i = 0; i < connections_.size(); ++i) |
970 connections_[i]->UpdateState(now); | 967 connections_[i]->UpdateState(now); |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1399 std::vector<PortInterface*>::iterator iter = | 1396 std::vector<PortInterface*>::iterator iter = |
1400 std::find(ports_.begin(), ports_.end(), port); | 1397 std::find(ports_.begin(), ports_.end(), port); |
1401 if (iter != ports_.end()) | 1398 if (iter != ports_.end()) |
1402 ports_.erase(iter); | 1399 ports_.erase(iter); |
1403 | 1400 |
1404 LOG(INFO) << "Removed port from p2p socket: " | 1401 LOG(INFO) << "Removed port from p2p socket: " |
1405 << static_cast<int>(ports_.size()) << " remaining"; | 1402 << static_cast<int>(ports_.size()) << " remaining"; |
1406 } | 1403 } |
1407 | 1404 |
1408 // We data is available, let listeners know | 1405 // We data is available, let listeners know |
1409 void P2PTransportChannel::OnReadPacket( | 1406 void P2PTransportChannel::OnReadPacket(Connection* connection, |
1410 Connection *connection, const char *data, size_t len, | 1407 const char* data, |
1411 const rtc::PacketTime& packet_time) { | 1408 size_t len, |
| 1409 const rtc::PacketTime& packet_time) { |
1412 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1410 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1413 | 1411 |
1414 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1412 // Do not deliver, if packet doesn't belong to the correct transport channel. |
1415 if (!FindConnection(connection)) | 1413 if (!FindConnection(connection)) |
1416 return; | 1414 return; |
1417 | 1415 |
1418 // Let the client know of an incoming packet | 1416 // Let the client know of an incoming packet |
1419 SignalReadPacket(this, data, len, packet_time, 0); | 1417 SignalReadPacket(this, data, len, packet_time, 0); |
1420 } | 1418 } |
1421 | 1419 |
1422 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1420 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1423 if (connection == best_connection_ && writable()) { | 1421 if (connection == best_connection_ && writable()) { |
1424 SignalReadyToSend(this); | 1422 SignalReadyToSend(this); |
1425 } | 1423 } |
1426 } | 1424 } |
1427 | 1425 |
1428 } // namespace cricket | 1426 } // namespace cricket |
OLD | NEW |