| 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 <utility> // for std::pair | 11 #include <utility> // for std::pair |
| 12 | 12 |
| 13 #include "webrtc/p2p/base/transport.h" | 13 #include "webrtc/p2p/base/transport.h" |
| 14 | 14 |
| 15 #include "webrtc/p2p/base/candidate.h" | 15 #include "webrtc/p2p/base/candidate.h" |
| 16 #include "webrtc/p2p/base/constants.h" | 16 #include "webrtc/p2p/base/constants.h" |
| 17 #include "webrtc/p2p/base/port.h" | 17 #include "webrtc/p2p/base/port.h" |
| 18 #include "webrtc/p2p/base/transportchannelimpl.h" | 18 #include "webrtc/p2p/base/transportchannelimpl.h" |
| 19 #include "webrtc/base/bind.h" | 19 #include "webrtc/base/bind.h" |
| 20 #include "webrtc/base/common.h" | 20 #include "webrtc/base/checks.h" |
| 21 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
| 22 | 22 |
| 23 namespace cricket { | 23 namespace cricket { |
| 24 | 24 |
| 25 using rtc::Bind; | 25 using rtc::Bind; |
| 26 | 26 |
| 27 static bool VerifyIceParams(const TransportDescription& desc) { | 27 static bool VerifyIceParams(const TransportDescription& desc) { |
| 28 // For legacy protocols. | 28 // For legacy protocols. |
| 29 if (desc.ice_ufrag.empty() && desc.ice_pwd.empty()) | 29 if (desc.ice_ufrag.empty() && desc.ice_pwd.empty()) |
| 30 return true; | 30 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 static bool IceCredentialsChanged(const TransportDescription& old_desc, | 62 static bool IceCredentialsChanged(const TransportDescription& old_desc, |
| 63 const TransportDescription& new_desc) { | 63 const TransportDescription& new_desc) { |
| 64 return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd, | 64 return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd, |
| 65 new_desc.ice_ufrag, new_desc.ice_pwd); | 65 new_desc.ice_ufrag, new_desc.ice_pwd); |
| 66 } | 66 } |
| 67 | 67 |
| 68 Transport::Transport(const std::string& name, PortAllocator* allocator) | 68 Transport::Transport(const std::string& name, PortAllocator* allocator) |
| 69 : name_(name), allocator_(allocator) {} | 69 : name_(name), allocator_(allocator) {} |
| 70 | 70 |
| 71 Transport::~Transport() { | 71 Transport::~Transport() { |
| 72 ASSERT(channels_destroyed_); | 72 RTC_DCHECK(channels_destroyed_); |
| 73 } | |
| 74 | |
| 75 bool Transport::AllChannelsCompleted() const { | |
| 76 // We aren't completed until at least one channel is complete, so if there | |
| 77 // are no channels, we aren't complete yet. | |
| 78 if (channels_.empty()) { | |
| 79 LOG(LS_INFO) << name() << " transport is not complete" | |
| 80 << " because it has no TransportChannels"; | |
| 81 return false; | |
| 82 } | |
| 83 | |
| 84 // A Transport's ICE process is completed if all of its channels are writable, | |
| 85 // have finished allocating candidates, and have pruned all but one of their | |
| 86 // connections. | |
| 87 for (const auto& iter : channels_) { | |
| 88 const TransportChannelImpl* channel = iter.second.get(); | |
| 89 bool complete = | |
| 90 channel->writable() && | |
| 91 channel->GetState() == TransportChannelState::STATE_COMPLETED && | |
| 92 channel->GetIceRole() == ICEROLE_CONTROLLING && | |
| 93 channel->gathering_state() == kIceGatheringComplete; | |
| 94 if (!complete) { | |
| 95 LOG(LS_INFO) << name() << " transport is not complete" | |
| 96 << " because a channel is still incomplete."; | |
| 97 return false; | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 return true; | |
| 102 } | |
| 103 | |
| 104 bool Transport::AnyChannelFailed() const { | |
| 105 for (const auto& iter : channels_) { | |
| 106 if (iter.second->GetState() == TransportChannelState::STATE_FAILED) { | |
| 107 return true; | |
| 108 } | |
| 109 } | |
| 110 return false; | |
| 111 } | 73 } |
| 112 | 74 |
| 113 void Transport::SetIceRole(IceRole role) { | 75 void Transport::SetIceRole(IceRole role) { |
| 114 ice_role_ = role; | 76 ice_role_ = role; |
| 115 for (auto& iter : channels_) { | 77 for (const auto& kv : channels_) { |
| 116 iter.second->SetIceRole(ice_role_); | 78 kv.second->SetIceRole(ice_role_); |
| 117 } | 79 } |
| 118 } | 80 } |
| 119 | 81 |
| 120 bool Transport::GetRemoteSSLCertificate(rtc::SSLCertificate** cert) { | 82 bool Transport::GetRemoteSSLCertificate(rtc::SSLCertificate** cert) { |
| 121 if (channels_.empty()) | 83 if (channels_.empty()) { |
| 122 return false; | 84 return false; |
| 85 } |
| 123 | 86 |
| 124 ChannelMap::iterator iter = channels_.begin(); | 87 auto iter = channels_.begin(); |
| 125 return iter->second->GetRemoteSSLCertificate(cert); | 88 return iter->second->GetRemoteSSLCertificate(cert); |
| 126 } | 89 } |
| 127 | 90 |
| 128 void Transport::SetIceConfig(const IceConfig& config) { | 91 void Transport::SetIceConfig(const IceConfig& config) { |
| 129 ice_config_ = config; | 92 ice_config_ = config; |
| 130 for (const auto& kv : channels_) { | 93 for (const auto& kv : channels_) { |
| 131 kv.second->SetIceConfig(ice_config_); | 94 kv.second->SetIceConfig(ice_config_); |
| 132 } | 95 } |
| 133 } | 96 } |
| 134 | 97 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 148 IceRole new_ice_role = | 111 IceRole new_ice_role = |
| 149 (action == CA_OFFER) ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED; | 112 (action == CA_OFFER) ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED; |
| 150 | 113 |
| 151 // It must be called before ApplyLocalTransportDescription, which may | 114 // It must be called before ApplyLocalTransportDescription, which may |
| 152 // trigger an ICE restart and depends on the new ICE role. | 115 // trigger an ICE restart and depends on the new ICE role. |
| 153 SetIceRole(new_ice_role); | 116 SetIceRole(new_ice_role); |
| 154 } | 117 } |
| 155 | 118 |
| 156 local_description_.reset(new TransportDescription(description)); | 119 local_description_.reset(new TransportDescription(description)); |
| 157 | 120 |
| 158 for (auto& iter : channels_) { | 121 for (const auto& kv : channels_) { |
| 159 ret &= ApplyLocalTransportDescription(iter.second.get(), error_desc); | 122 ret &= ApplyLocalTransportDescription(kv.second, error_desc); |
| 160 } | 123 } |
| 161 if (!ret) { | 124 if (!ret) { |
| 162 return false; | 125 return false; |
| 163 } | 126 } |
| 164 | 127 |
| 165 // If PRANSWER/ANSWER is set, we should decide transport protocol type. | 128 // If PRANSWER/ANSWER is set, we should decide transport protocol type. |
| 166 if (action == CA_PRANSWER || action == CA_ANSWER) { | 129 if (action == CA_PRANSWER || action == CA_ANSWER) { |
| 167 ret &= NegotiateTransportDescription(action, error_desc); | 130 ret &= NegotiateTransportDescription(action, error_desc); |
| 168 } | 131 } |
| 169 if (ret) { | 132 if (ret) { |
| 170 local_description_set_ = true; | 133 local_description_set_ = true; |
| 171 ConnectChannels(); | 134 ConnectChannels(); |
| 172 } | 135 } |
| 173 | 136 |
| 174 return ret; | 137 return ret; |
| 175 } | 138 } |
| 176 | 139 |
| 177 bool Transport::SetRemoteTransportDescription( | 140 bool Transport::SetRemoteTransportDescription( |
| 178 const TransportDescription& description, | 141 const TransportDescription& description, |
| 179 ContentAction action, | 142 ContentAction action, |
| 180 std::string* error_desc) { | 143 std::string* error_desc) { |
| 181 bool ret = true; | 144 bool ret = true; |
| 182 | 145 |
| 183 if (!VerifyIceParams(description)) { | 146 if (!VerifyIceParams(description)) { |
| 184 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", | 147 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", |
| 185 error_desc); | 148 error_desc); |
| 186 } | 149 } |
| 187 | 150 |
| 188 remote_description_.reset(new TransportDescription(description)); | 151 remote_description_.reset(new TransportDescription(description)); |
| 189 for (auto& iter : channels_) { | 152 for (const auto& kv : channels_) { |
| 190 ret &= ApplyRemoteTransportDescription(iter.second.get(), error_desc); | 153 ret &= ApplyRemoteTransportDescription(kv.second, error_desc); |
| 191 } | 154 } |
| 192 | 155 |
| 193 // If PRANSWER/ANSWER is set, we should decide transport protocol type. | 156 // If PRANSWER/ANSWER is set, we should decide transport protocol type. |
| 194 if (action == CA_PRANSWER || action == CA_ANSWER) { | 157 if (action == CA_PRANSWER || action == CA_ANSWER) { |
| 195 ret = NegotiateTransportDescription(CA_OFFER, error_desc); | 158 ret = NegotiateTransportDescription(CA_OFFER, error_desc); |
| 196 } | 159 } |
| 197 if (ret) { | 160 if (ret) { |
| 198 remote_description_set_ = true; | 161 remote_description_set_ = true; |
| 199 } | 162 } |
| 200 | 163 |
| 201 return ret; | 164 return ret; |
| 202 } | 165 } |
| 203 | 166 |
| 204 TransportChannelImpl* Transport::CreateChannel(int component) { | 167 TransportChannelImpl* Transport::CreateChannel(int component) { |
| 205 TransportChannelImpl* impl; | 168 TransportChannelImpl* channel; |
| 206 | 169 |
| 207 // Create the entry if it does not exist. | 170 // Create the entry if it does not exist. |
| 208 bool impl_exists = false; | 171 bool channel_exists = false; |
| 209 auto iterator = channels_.find(component); | 172 auto iter = channels_.find(component); |
| 210 if (iterator == channels_.end()) { | 173 if (iter == channels_.end()) { |
| 211 impl = CreateTransportChannel(component); | 174 channel = CreateTransportChannel(component); |
| 212 iterator = channels_.insert(std::pair<int, ChannelMapEntry>( | 175 channels_.insert(std::pair<int, TransportChannelImpl*>(component, channel)); |
| 213 component, ChannelMapEntry(impl))).first; | |
| 214 } else { | 176 } else { |
| 215 impl = iterator->second.get(); | 177 channel = iter->second; |
| 216 impl_exists = true; | 178 channel_exists = true; |
| 217 } | 179 } |
| 218 | 180 |
| 219 // Increase the ref count. | |
| 220 iterator->second.AddRef(); | |
| 221 channels_destroyed_ = false; | 181 channels_destroyed_ = false; |
| 222 | 182 |
| 223 if (impl_exists) { | 183 if (channel_exists) { |
| 224 // If this is an existing channel, we should just return it without | 184 // If this is an existing channel, we should just return it. |
| 225 // connecting to all the signal again. | 185 return channel; |
| 226 return impl; | |
| 227 } | 186 } |
| 228 | 187 |
| 229 // Push down our transport state to the new channel. | 188 // Push down our transport state to the new channel. |
| 230 impl->SetIceRole(ice_role_); | 189 channel->SetIceRole(ice_role_); |
| 231 impl->SetIceTiebreaker(tiebreaker_); | 190 channel->SetIceTiebreaker(tiebreaker_); |
| 232 impl->SetIceConfig(ice_config_); | 191 channel->SetIceConfig(ice_config_); |
| 233 // TODO(ronghuawu): Change CreateChannel to be able to return error since | 192 // TODO(ronghuawu): Change CreateChannel to be able to return error since |
| 234 // below Apply**Description calls can fail. | 193 // below Apply**Description calls can fail. |
| 235 if (local_description_) | 194 if (local_description_) |
| 236 ApplyLocalTransportDescription(impl, NULL); | 195 ApplyLocalTransportDescription(channel, nullptr); |
| 237 if (remote_description_) | 196 if (remote_description_) |
| 238 ApplyRemoteTransportDescription(impl, NULL); | 197 ApplyRemoteTransportDescription(channel, nullptr); |
| 239 if (local_description_ && remote_description_) | 198 if (local_description_ && remote_description_) |
| 240 ApplyNegotiatedTransportDescription(impl, NULL); | 199 ApplyNegotiatedTransportDescription(channel, nullptr); |
| 241 | |
| 242 impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState); | |
| 243 impl->SignalReceivingState.connect(this, &Transport::OnChannelReceivingState); | |
| 244 impl->SignalGatheringState.connect(this, &Transport::OnChannelGatheringState); | |
| 245 impl->SignalCandidateGathered.connect(this, | |
| 246 &Transport::OnChannelCandidateGathered); | |
| 247 impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange); | |
| 248 impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict); | |
| 249 impl->SignalConnectionRemoved.connect( | |
| 250 this, &Transport::OnChannelConnectionRemoved); | |
| 251 | 200 |
| 252 if (connect_requested_) { | 201 if (connect_requested_) { |
| 253 impl->Connect(); | 202 channel->Connect(); |
| 254 if (channels_.size() == 1) { | |
| 255 // If this is the first channel, then indicate that we have started | |
| 256 // connecting. | |
| 257 SignalConnecting(this); | |
| 258 } | |
| 259 } | 203 } |
| 260 return impl; | 204 return channel; |
| 261 } | 205 } |
| 262 | 206 |
| 263 TransportChannelImpl* Transport::GetChannel(int component) { | 207 TransportChannelImpl* Transport::GetChannel(int component) { |
| 264 ChannelMap::iterator iter = channels_.find(component); | 208 auto iter = channels_.find(component); |
| 265 return (iter != channels_.end()) ? iter->second.get() : NULL; | 209 return (iter != channels_.end()) ? iter->second : nullptr; |
| 266 } | 210 } |
| 267 | 211 |
| 268 bool Transport::HasChannels() { | 212 bool Transport::HasChannels() { |
| 269 return !channels_.empty(); | 213 return !channels_.empty(); |
| 270 } | 214 } |
| 271 | 215 |
| 272 void Transport::DestroyChannel(int component) { | 216 void Transport::DestroyChannel(int component) { |
| 273 ChannelMap::iterator iter = channels_.find(component); | 217 auto iter = channels_.find(component); |
| 274 if (iter == channels_.end()) | 218 if (iter == channels_.end()) |
| 275 return; | 219 return; |
| 276 | 220 |
| 277 TransportChannelImpl* impl = NULL; | 221 TransportChannelImpl* channel = iter->second; |
| 278 | 222 channels_.erase(iter); |
| 279 iter->second.DecRef(); | 223 DestroyTransportChannel(channel); |
| 280 if (!iter->second.ref()) { | |
| 281 impl = iter->second.get(); | |
| 282 channels_.erase(iter); | |
| 283 } | |
| 284 | |
| 285 if (connect_requested_ && channels_.empty()) { | |
| 286 // We're no longer attempting to connect. | |
| 287 SignalConnecting(this); | |
| 288 } | |
| 289 | |
| 290 if (impl) { | |
| 291 DestroyTransportChannel(impl); | |
| 292 // Need to update aggregate state after destroying a channel, | |
| 293 // for example if it was the only one that wasn't yet writable. | |
| 294 UpdateWritableState(); | |
| 295 UpdateReceivingState(); | |
| 296 UpdateGatheringState(); | |
| 297 MaybeSignalCompleted(); | |
| 298 } | |
| 299 } | 224 } |
| 300 | 225 |
| 301 void Transport::ConnectChannels() { | 226 void Transport::ConnectChannels() { |
| 302 if (connect_requested_ || channels_.empty()) | 227 if (connect_requested_ || channels_.empty()) |
| 303 return; | 228 return; |
| 304 | 229 |
| 305 connect_requested_ = true; | 230 connect_requested_ = true; |
| 306 | 231 |
| 307 if (!local_description_) { | 232 if (!local_description_) { |
| 308 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here. | 233 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here. |
| 309 // As Transport must know TD is offer or answer and cricket::Transport | 234 // As Transport must know TD is offer or answer and cricket::Transport |
| 310 // doesn't have the capability to decide it. This should be set by the | 235 // doesn't have the capability to decide it. This should be set by the |
| 311 // Session. | 236 // Session. |
| 312 // Session must generate local TD before remote candidates pushed when | 237 // Session must generate local TD before remote candidates pushed when |
| 313 // initiate request initiated by the remote. | 238 // initiate request initiated by the remote. |
| 314 LOG(LS_INFO) << "Transport::ConnectChannels: No local description has " | 239 LOG(LS_INFO) << "Transport::ConnectChannels: No local description has " |
| 315 << "been set. Will generate one."; | 240 << "been set. Will generate one."; |
| 316 TransportDescription desc( | 241 TransportDescription desc( |
| 317 std::vector<std::string>(), rtc::CreateRandomString(ICE_UFRAG_LENGTH), | 242 std::vector<std::string>(), rtc::CreateRandomString(ICE_UFRAG_LENGTH), |
| 318 rtc::CreateRandomString(ICE_PWD_LENGTH), ICEMODE_FULL, | 243 rtc::CreateRandomString(ICE_PWD_LENGTH), ICEMODE_FULL, |
| 319 CONNECTIONROLE_NONE, NULL, Candidates()); | 244 CONNECTIONROLE_NONE, nullptr, Candidates()); |
| 320 SetLocalTransportDescription(desc, CA_OFFER, NULL); | 245 SetLocalTransportDescription(desc, CA_OFFER, nullptr); |
| 321 } | 246 } |
| 322 | 247 |
| 323 CallChannels(&TransportChannelImpl::Connect); | 248 CallChannels(&TransportChannelImpl::Connect); |
| 324 if (HasChannels()) { | |
| 325 SignalConnecting(this); | |
| 326 } | |
| 327 } | 249 } |
| 328 | 250 |
| 329 void Transport::MaybeStartGathering() { | 251 void Transport::MaybeStartGathering() { |
| 330 if (connect_requested_) { | 252 if (connect_requested_) { |
| 331 CallChannels(&TransportChannelImpl::MaybeStartGathering); | 253 CallChannels(&TransportChannelImpl::MaybeStartGathering); |
| 332 } | 254 } |
| 333 } | 255 } |
| 334 | 256 |
| 335 void Transport::DestroyAllChannels() { | 257 void Transport::DestroyAllChannels() { |
| 336 std::vector<TransportChannelImpl*> impls; | 258 for (const auto& kv : channels_) { |
| 337 for (auto& iter : channels_) { | 259 DestroyTransportChannel(kv.second); |
| 338 iter.second.DecRef(); | |
| 339 if (!iter.second.ref()) | |
| 340 impls.push_back(iter.second.get()); | |
| 341 } | 260 } |
| 342 | |
| 343 channels_.clear(); | 261 channels_.clear(); |
| 344 | |
| 345 for (TransportChannelImpl* impl : impls) { | |
| 346 DestroyTransportChannel(impl); | |
| 347 } | |
| 348 channels_destroyed_ = true; | 262 channels_destroyed_ = true; |
| 349 } | 263 } |
| 350 | 264 |
| 351 void Transport::CallChannels(TransportChannelFunc func) { | 265 void Transport::CallChannels(TransportChannelFunc func) { |
| 352 for (const auto& iter : channels_) { | 266 for (const auto& kv : channels_) { |
| 353 ((iter.second.get())->*func)(); | 267 (kv.second->*func)(); |
| 354 } | 268 } |
| 355 } | 269 } |
| 356 | 270 |
| 357 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) { | 271 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) { |
| 358 // No address zero. | 272 // No address zero. |
| 359 if (cand.address().IsNil() || cand.address().IsAny()) { | 273 if (cand.address().IsNil() || cand.address().IsAny()) { |
| 360 *error = "candidate has address of zero"; | 274 *error = "candidate has address of zero"; |
| 361 return false; | 275 return false; |
| 362 } | 276 } |
| 363 | 277 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 382 } | 296 } |
| 383 } | 297 } |
| 384 | 298 |
| 385 return true; | 299 return true; |
| 386 } | 300 } |
| 387 | 301 |
| 388 | 302 |
| 389 bool Transport::GetStats(TransportStats* stats) { | 303 bool Transport::GetStats(TransportStats* stats) { |
| 390 stats->transport_name = name(); | 304 stats->transport_name = name(); |
| 391 stats->channel_stats.clear(); | 305 stats->channel_stats.clear(); |
| 392 for (auto iter : channels_) { | 306 for (auto kv : channels_) { |
| 393 ChannelMapEntry& entry = iter.second; | 307 TransportChannelImpl* channel = kv.second; |
| 394 TransportChannelStats substats; | 308 TransportChannelStats substats; |
| 395 substats.component = entry->component(); | 309 substats.component = channel->component(); |
| 396 entry->GetSrtpCipher(&substats.srtp_cipher); | 310 channel->GetSrtpCipher(&substats.srtp_cipher); |
| 397 entry->GetSslCipher(&substats.ssl_cipher); | 311 channel->GetSslCipher(&substats.ssl_cipher); |
| 398 if (!entry->GetStats(&substats.connection_infos)) { | 312 if (!channel->GetStats(&substats.connection_infos)) { |
| 399 return false; | 313 return false; |
| 400 } | 314 } |
| 401 stats->channel_stats.push_back(substats); | 315 stats->channel_stats.push_back(substats); |
| 402 } | 316 } |
| 403 return true; | 317 return true; |
| 404 } | 318 } |
| 405 | 319 |
| 406 bool Transport::AddRemoteCandidates(const std::vector<Candidate>& candidates, | 320 bool Transport::AddRemoteCandidates(const std::vector<Candidate>& candidates, |
| 407 std::string* error) { | 321 std::string* error) { |
| 408 ASSERT(!channels_destroyed_); | 322 ASSERT(!channels_destroyed_); |
| 409 // Verify each candidate before passing down to transport layer. | 323 // Verify each candidate before passing down to transport layer. |
| 410 for (const Candidate& cand : candidates) { | 324 for (const Candidate& cand : candidates) { |
| 411 if (!VerifyCandidate(cand, error)) { | 325 if (!VerifyCandidate(cand, error)) { |
| 412 return false; | 326 return false; |
| 413 } | 327 } |
| 414 if (!HasChannel(cand.component())) { | 328 if (!HasChannel(cand.component())) { |
| 415 *error = "Candidate has unknown component: " + cand.ToString() + | 329 *error = "Candidate has unknown component: " + cand.ToString() + |
| 416 " for content: " + name(); | 330 " for content: " + name(); |
| 417 return false; | 331 return false; |
| 418 } | 332 } |
| 419 } | 333 } |
| 420 | 334 |
| 421 for (std::vector<Candidate>::const_iterator iter = candidates.begin(); | 335 for (const Candidate& candidate : candidates) { |
| 422 iter != candidates.end(); | 336 TransportChannelImpl* channel = GetChannel(candidate.component()); |
| 423 ++iter) { | 337 if (channel != nullptr) { |
| 424 TransportChannelImpl* channel = GetChannel(iter->component()); | 338 channel->AddRemoteCandidate(candidate); |
| 425 if (channel != NULL) { | |
| 426 channel->AddRemoteCandidate(*iter); | |
| 427 } | 339 } |
| 428 } | 340 } |
| 429 return true; | 341 return true; |
| 430 } | 342 } |
| 431 | 343 |
| 432 void Transport::OnChannelWritableState(TransportChannel* channel) { | |
| 433 LOG(LS_INFO) << name() << " TransportChannel " << channel->component() | |
| 434 << " writability changed to " << channel->writable() | |
| 435 << ". Check if transport is complete."; | |
| 436 UpdateWritableState(); | |
| 437 MaybeSignalCompleted(); | |
| 438 } | |
| 439 | |
| 440 void Transport::OnChannelReceivingState(TransportChannel* channel) { | |
| 441 UpdateReceivingState(); | |
| 442 } | |
| 443 | |
| 444 TransportState Transport::GetTransportState(TransportStateType state_type) { | |
| 445 bool any = false; | |
| 446 bool all = !channels_.empty(); | |
| 447 for (const auto iter : channels_) { | |
| 448 bool b = false; | |
| 449 switch (state_type) { | |
| 450 case TRANSPORT_WRITABLE_STATE: | |
| 451 b = iter.second->writable(); | |
| 452 break; | |
| 453 case TRANSPORT_RECEIVING_STATE: | |
| 454 b = iter.second->receiving(); | |
| 455 break; | |
| 456 default: | |
| 457 ASSERT(false); | |
| 458 } | |
| 459 any |= b; | |
| 460 all &= b; | |
| 461 } | |
| 462 | |
| 463 if (all) { | |
| 464 return TRANSPORT_STATE_ALL; | |
| 465 } else if (any) { | |
| 466 return TRANSPORT_STATE_SOME; | |
| 467 } | |
| 468 | |
| 469 return TRANSPORT_STATE_NONE; | |
| 470 } | |
| 471 | |
| 472 void Transport::OnChannelGatheringState(TransportChannelImpl* channel) { | |
| 473 ASSERT(channels_.find(channel->component()) != channels_.end()); | |
| 474 UpdateGatheringState(); | |
| 475 if (gathering_state_ == kIceGatheringComplete) { | |
| 476 // If UpdateGatheringState brought us to kIceGatheringComplete, check if | |
| 477 // our connection state is also "Completed". Otherwise, there's no point in | |
| 478 // checking (since it would only produce log messages). | |
| 479 MaybeSignalCompleted(); | |
| 480 } | |
| 481 } | |
| 482 | |
| 483 void Transport::OnChannelCandidateGathered(TransportChannelImpl* channel, | |
| 484 const Candidate& candidate) { | |
| 485 // We should never signal peer-reflexive candidates. | |
| 486 if (candidate.type() == PRFLX_PORT_TYPE) { | |
| 487 ASSERT(false); | |
| 488 return; | |
| 489 } | |
| 490 | |
| 491 ASSERT(connect_requested_); | |
| 492 std::vector<Candidate> candidates; | |
| 493 candidates.push_back(candidate); | |
| 494 SignalCandidatesGathered(this, candidates); | |
| 495 } | |
| 496 | |
| 497 void Transport::OnChannelRouteChange(TransportChannel* channel, | |
| 498 const Candidate& remote_candidate) { | |
| 499 SignalRouteChange(this, remote_candidate.component(), remote_candidate); | |
| 500 } | |
| 501 | |
| 502 void Transport::OnRoleConflict(TransportChannelImpl* channel) { | |
| 503 SignalRoleConflict(); | |
| 504 } | |
| 505 | |
| 506 void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) { | |
| 507 LOG(LS_INFO) << name() << " TransportChannel " << channel->component() | |
| 508 << " connection removed. Check if transport is complete."; | |
| 509 MaybeSignalCompleted(); | |
| 510 | |
| 511 // Check if the state is now Failed. | |
| 512 // Failed is only available in the Controlling ICE role. | |
| 513 if (channel->GetIceRole() != ICEROLE_CONTROLLING) { | |
| 514 return; | |
| 515 } | |
| 516 | |
| 517 // Failed can only occur after candidate gathering has stopped. | |
| 518 if (channel->gathering_state() != kIceGatheringComplete) { | |
| 519 return; | |
| 520 } | |
| 521 | |
| 522 if (channel->GetState() == TransportChannelState::STATE_FAILED) { | |
| 523 // A Transport has failed if any of its channels have no remaining | |
| 524 // connections. | |
| 525 SignalFailed(this); | |
| 526 } | |
| 527 } | |
| 528 | |
| 529 void Transport::MaybeSignalCompleted() { | |
| 530 if (AllChannelsCompleted()) { | |
| 531 LOG(LS_INFO) << name() << " transport is complete" | |
| 532 << " because all the channels are complete."; | |
| 533 SignalCompleted(this); | |
| 534 } | |
| 535 // TODO(deadbeef): Should we do anything if we previously were completed, | |
| 536 // but now are not (if, for example, a new remote candidate is added)? | |
| 537 } | |
| 538 | |
| 539 void Transport::UpdateGatheringState() { | |
| 540 IceGatheringState new_state = kIceGatheringNew; | |
| 541 bool any_gathering = false; | |
| 542 bool all_complete = !channels_.empty(); | |
| 543 for (const auto& kv : channels_) { | |
| 544 any_gathering = | |
| 545 any_gathering || kv.second->gathering_state() != kIceGatheringNew; | |
| 546 all_complete = | |
| 547 all_complete && kv.second->gathering_state() == kIceGatheringComplete; | |
| 548 } | |
| 549 if (all_complete) { | |
| 550 new_state = kIceGatheringComplete; | |
| 551 } else if (any_gathering) { | |
| 552 new_state = kIceGatheringGathering; | |
| 553 } | |
| 554 | |
| 555 if (gathering_state_ != new_state) { | |
| 556 gathering_state_ = new_state; | |
| 557 if (gathering_state_ == kIceGatheringGathering) { | |
| 558 LOG(LS_INFO) << "Transport: " << name_ << ", gathering candidates"; | |
| 559 } else if (gathering_state_ == kIceGatheringComplete) { | |
| 560 LOG(LS_INFO) << "Transport " << name() << " gathering complete."; | |
| 561 } | |
| 562 SignalGatheringState(this); | |
| 563 } | |
| 564 } | |
| 565 | |
| 566 void Transport::UpdateReceivingState() { | |
| 567 TransportState receiving = GetTransportState(TRANSPORT_RECEIVING_STATE); | |
| 568 if (receiving_ != receiving) { | |
| 569 receiving_ = receiving; | |
| 570 SignalReceivingState(this); | |
| 571 } | |
| 572 } | |
| 573 | |
| 574 void Transport::UpdateWritableState() { | |
| 575 TransportState writable = GetTransportState(TRANSPORT_WRITABLE_STATE); | |
| 576 LOG(LS_INFO) << name() << " transport writable state changed? " << writable_ | |
| 577 << " => " << writable; | |
| 578 if (writable_ != writable) { | |
| 579 was_writable_ = (writable_ == TRANSPORT_STATE_ALL); | |
| 580 writable_ = writable; | |
| 581 SignalWritableState(this); | |
| 582 } | |
| 583 } | |
| 584 | |
| 585 bool Transport::ApplyLocalTransportDescription(TransportChannelImpl* ch, | 344 bool Transport::ApplyLocalTransportDescription(TransportChannelImpl* ch, |
| 586 std::string* error_desc) { | 345 std::string* error_desc) { |
| 587 ch->SetIceCredentials(local_description_->ice_ufrag, | 346 ch->SetIceCredentials(local_description_->ice_ufrag, |
| 588 local_description_->ice_pwd); | 347 local_description_->ice_pwd); |
| 589 return true; | 348 return true; |
| 590 } | 349 } |
| 591 | 350 |
| 592 bool Transport::ApplyRemoteTransportDescription(TransportChannelImpl* ch, | 351 bool Transport::ApplyRemoteTransportDescription(TransportChannelImpl* ch, |
| 593 std::string* error_desc) { | 352 std::string* error_desc) { |
| 594 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, | 353 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 616 } | 375 } |
| 617 | 376 |
| 618 // Update remote ice_mode to all existing channels. | 377 // Update remote ice_mode to all existing channels. |
| 619 remote_ice_mode_ = remote_description_->ice_mode; | 378 remote_ice_mode_ = remote_description_->ice_mode; |
| 620 | 379 |
| 621 // Now that we have negotiated everything, push it downward. | 380 // Now that we have negotiated everything, push it downward. |
| 622 // Note that we cache the result so that if we have race conditions | 381 // Note that we cache the result so that if we have race conditions |
| 623 // between future SetRemote/SetLocal invocations and new channel | 382 // between future SetRemote/SetLocal invocations and new channel |
| 624 // creation, we have the negotiation state saved until a new | 383 // creation, we have the negotiation state saved until a new |
| 625 // negotiation happens. | 384 // negotiation happens. |
| 626 for (auto& iter : channels_) { | 385 for (const auto& kv : channels_) { |
| 627 if (!ApplyNegotiatedTransportDescription(iter.second.get(), error_desc)) | 386 if (!ApplyNegotiatedTransportDescription(kv.second, error_desc)) { |
| 628 return false; | 387 return false; |
| 388 } |
| 629 } | 389 } |
| 630 return true; | 390 return true; |
| 631 } | 391 } |
| 632 | 392 |
| 633 } // namespace cricket | 393 } // namespace cricket |
| OLD | NEW |