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 |
| 12 |
11 #include "webrtc/p2p/base/transport.h" | 13 #include "webrtc/p2p/base/transport.h" |
12 | 14 |
13 #include "webrtc/p2p/base/candidate.h" | 15 #include "webrtc/p2p/base/candidate.h" |
14 #include "webrtc/p2p/base/constants.h" | 16 #include "webrtc/p2p/base/constants.h" |
15 #include "webrtc/p2p/base/port.h" | 17 #include "webrtc/p2p/base/port.h" |
16 #include "webrtc/p2p/base/transportchannelimpl.h" | 18 #include "webrtc/p2p/base/transportchannelimpl.h" |
17 #include "webrtc/base/bind.h" | 19 #include "webrtc/base/bind.h" |
18 #include "webrtc/base/common.h" | 20 #include "webrtc/base/common.h" |
19 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
20 | 22 |
21 namespace cricket { | 23 namespace cricket { |
22 | 24 |
23 using rtc::Bind; | 25 using rtc::Bind; |
24 | 26 |
25 enum { | |
26 MSG_ONSIGNALINGREADY = 1, | |
27 MSG_ONREMOTECANDIDATE, | |
28 MSG_READSTATE, | |
29 MSG_WRITESTATE, | |
30 MSG_REQUESTSIGNALING, | |
31 MSG_CANDIDATEREADY, | |
32 MSG_ROUTECHANGE, | |
33 MSG_CONNECTING, | |
34 MSG_CANDIDATEALLOCATIONCOMPLETE, | |
35 MSG_ROLECONFLICT, | |
36 MSG_COMPLETED, | |
37 MSG_FAILED, | |
38 MSG_RECEIVINGSTATE, | |
39 }; | |
40 | |
41 struct ChannelParams : public rtc::MessageData { | |
42 ChannelParams() : channel(NULL), candidate(NULL) {} | |
43 explicit ChannelParams(int component) | |
44 : component(component), channel(NULL), candidate(NULL) {} | |
45 explicit ChannelParams(Candidate* candidate) | |
46 : channel(NULL), candidate(candidate) { | |
47 } | |
48 | |
49 ~ChannelParams() { | |
50 delete candidate; | |
51 } | |
52 | |
53 std::string name; | |
54 int component; | |
55 TransportChannelImpl* channel; | |
56 Candidate* candidate; | |
57 }; | |
58 | |
59 static bool VerifyIceParams(const TransportDescription& desc) { | 27 static bool VerifyIceParams(const TransportDescription& desc) { |
60 // For legacy protocols. | 28 // For legacy protocols. |
61 if (desc.ice_ufrag.empty() && desc.ice_pwd.empty()) | 29 if (desc.ice_ufrag.empty() && desc.ice_pwd.empty()) |
62 return true; | 30 return true; |
63 | 31 |
64 if (desc.ice_ufrag.length() < ICE_UFRAG_MIN_LENGTH || | 32 if (desc.ice_ufrag.length() < ICE_UFRAG_MIN_LENGTH || |
65 desc.ice_ufrag.length() > ICE_UFRAG_MAX_LENGTH) { | 33 desc.ice_ufrag.length() > ICE_UFRAG_MAX_LENGTH) { |
66 return false; | 34 return false; |
67 } | 35 } |
68 if (desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH || | 36 if (desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH || |
(...skipping 21 matching lines...) Expand all Loading... |
90 // should clean this up when GICE is no longer used. | 58 // should clean this up when GICE is no longer used. |
91 return (old_ufrag != new_ufrag) || (old_pwd != new_pwd); | 59 return (old_ufrag != new_ufrag) || (old_pwd != new_pwd); |
92 } | 60 } |
93 | 61 |
94 static bool IceCredentialsChanged(const TransportDescription& old_desc, | 62 static bool IceCredentialsChanged(const TransportDescription& old_desc, |
95 const TransportDescription& new_desc) { | 63 const TransportDescription& new_desc) { |
96 return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd, | 64 return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd, |
97 new_desc.ice_ufrag, new_desc.ice_pwd); | 65 new_desc.ice_ufrag, new_desc.ice_pwd); |
98 } | 66 } |
99 | 67 |
100 Transport::Transport(rtc::Thread* signaling_thread, | 68 Transport::Transport(const std::string& name, PortAllocator* allocator) |
101 rtc::Thread* worker_thread, | 69 : name_(name), allocator_(allocator) { |
102 const std::string& content_name, | |
103 PortAllocator* allocator) | |
104 : signaling_thread_(signaling_thread), | |
105 worker_thread_(worker_thread), | |
106 content_name_(content_name), | |
107 allocator_(allocator), | |
108 destroyed_(false), | |
109 readable_(TRANSPORT_STATE_NONE), | |
110 writable_(TRANSPORT_STATE_NONE), | |
111 receiving_(TRANSPORT_STATE_NONE), | |
112 was_writable_(false), | |
113 connect_requested_(false), | |
114 ice_role_(ICEROLE_UNKNOWN), | |
115 tiebreaker_(0), | |
116 remote_ice_mode_(ICEMODE_FULL), | |
117 channel_receiving_timeout_(-1) { | |
118 } | 70 } |
119 | 71 |
120 Transport::~Transport() { | 72 Transport::~Transport() { |
121 ASSERT(signaling_thread_->IsCurrent()); | 73 ASSERT(channels_destroyed_); |
122 ASSERT(destroyed_); | 74 } |
| 75 |
| 76 bool Transport::AllChannelsCompleted() const { |
| 77 // We aren't completed until at least one channel is compolete, so if there |
| 78 // are no channels, we aren't complete yet. |
| 79 if (channels_.empty()) { |
| 80 LOG(LS_INFO) << name() << " transport is not complete" |
| 81 << " because it has no TransportChannels"; |
| 82 return false; |
| 83 } |
| 84 |
| 85 // A Transport's ICE process is completed if all of its channels are writable, |
| 86 // have finished allocating candidates, and have pruned all but one of their |
| 87 // connections. |
| 88 for (const auto& iter : channels_) { |
| 89 const TransportChannelImpl* channel = iter.second.get(); |
| 90 bool complete = |
| 91 channel->writable() && |
| 92 channel->GetState() == TransportChannelState::STATE_COMPLETED && |
| 93 channel->GetIceRole() == ICEROLE_CONTROLLING && |
| 94 channel->gathering_state() == kIceGatheringComplete; |
| 95 if (!complete) { |
| 96 LOG(LS_INFO) << name() << " transport is not complete" |
| 97 << " because a channel is still incomplete."; |
| 98 return false; |
| 99 } |
| 100 } |
| 101 |
| 102 return true; |
| 103 } |
| 104 |
| 105 bool Transport::AnyChannelFailed() const { |
| 106 for (const auto& iter : channels_) { |
| 107 if (iter.second->GetState() == TransportChannelState::STATE_FAILED) { |
| 108 return true; |
| 109 } |
| 110 } |
| 111 return false; |
123 } | 112 } |
124 | 113 |
125 void Transport::SetIceRole(IceRole role) { | 114 void Transport::SetIceRole(IceRole role) { |
126 worker_thread_->Invoke<void>(Bind(&Transport::SetIceRole_w, this, role)); | 115 ice_role_ = role; |
127 } | 116 for (auto& iter : channels_) { |
128 | 117 iter.second->SetIceRole(ice_role_); |
129 void Transport::SetCertificate( | 118 } |
130 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | |
131 worker_thread_->Invoke<void>(Bind(&Transport::SetCertificate_w, this, | |
132 certificate)); | |
133 } | |
134 | |
135 bool Transport::GetCertificate( | |
136 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
137 // The identity is set on the worker thread, so for safety it must also be | |
138 // acquired on the worker thread. | |
139 return worker_thread_->Invoke<bool>( | |
140 Bind(&Transport::GetCertificate_w, this, certificate)); | |
141 } | 119 } |
142 | 120 |
143 bool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) { | 121 bool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) { |
144 // Channels can be deleted on the worker thread, so for safety the remote | |
145 // certificate is acquired on the worker thread. | |
146 return worker_thread_->Invoke<bool>( | |
147 Bind(&Transport::GetRemoteCertificate_w, this, cert)); | |
148 } | |
149 | |
150 bool Transport::GetRemoteCertificate_w(rtc::SSLCertificate** cert) { | |
151 ASSERT(worker_thread()->IsCurrent()); | |
152 if (channels_.empty()) | 122 if (channels_.empty()) |
153 return false; | 123 return false; |
154 | 124 |
155 ChannelMap::iterator iter = channels_.begin(); | 125 ChannelMap::iterator iter = channels_.begin(); |
156 return iter->second->GetRemoteCertificate(cert); | 126 return iter->second->GetRemoteCertificate(cert); |
157 } | 127 } |
158 | 128 |
159 void Transport::SetChannelReceivingTimeout(int timeout_ms) { | 129 void Transport::SetChannelReceivingTimeout(int timeout_ms) { |
160 worker_thread_->Invoke<void>( | |
161 Bind(&Transport::SetChannelReceivingTimeout_w, this, timeout_ms)); | |
162 } | |
163 | |
164 void Transport::SetChannelReceivingTimeout_w(int timeout_ms) { | |
165 ASSERT(worker_thread()->IsCurrent()); | |
166 channel_receiving_timeout_ = timeout_ms; | 130 channel_receiving_timeout_ = timeout_ms; |
167 for (const auto& kv : channels_) { | 131 for (const auto& kv : channels_) { |
168 kv.second->SetReceivingTimeout(timeout_ms); | 132 kv.second->SetReceivingTimeout(timeout_ms); |
169 } | 133 } |
170 } | 134 } |
171 | 135 |
172 bool Transport::SetLocalTransportDescription( | 136 bool Transport::SetLocalTransportDescription( |
173 const TransportDescription& description, | 137 const TransportDescription& description, |
174 ContentAction action, | 138 ContentAction action, |
175 std::string* error_desc) { | 139 std::string* error_desc) { |
176 return worker_thread_->Invoke<bool>(Bind( | 140 bool ret = true; |
177 &Transport::SetLocalTransportDescription_w, this, | 141 |
178 description, action, error_desc)); | 142 if (!VerifyIceParams(description)) { |
| 143 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", |
| 144 error_desc); |
| 145 } |
| 146 |
| 147 if (local_description_ && |
| 148 IceCredentialsChanged(*local_description_, description)) { |
| 149 IceRole new_ice_role = |
| 150 (action == CA_OFFER) ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED; |
| 151 |
| 152 // It must be called before ApplyLocalTransportDescription, which may |
| 153 // trigger an ICE restart and depends on the new ICE role. |
| 154 SetIceRole(new_ice_role); |
| 155 } |
| 156 |
| 157 local_description_.reset(new TransportDescription(description)); |
| 158 |
| 159 for (auto& iter : channels_) { |
| 160 ret &= ApplyLocalTransportDescription(iter.second.get(), error_desc); |
| 161 } |
| 162 if (!ret) { |
| 163 return false; |
| 164 } |
| 165 |
| 166 // If PRANSWER/ANSWER is set, we should decide transport protocol type. |
| 167 if (action == CA_PRANSWER || action == CA_ANSWER) { |
| 168 ret &= NegotiateTransportDescription(action, error_desc); |
| 169 } |
| 170 if (ret) { |
| 171 local_description_set_ = true; |
| 172 // This kicks off candidate gathering |
| 173 ConnectChannels(); |
| 174 } |
| 175 |
| 176 return ret; |
179 } | 177 } |
180 | 178 |
181 bool Transport::SetRemoteTransportDescription( | 179 bool Transport::SetRemoteTransportDescription( |
182 const TransportDescription& description, | 180 const TransportDescription& description, |
183 ContentAction action, | 181 ContentAction action, |
184 std::string* error_desc) { | 182 std::string* error_desc) { |
185 return worker_thread_->Invoke<bool>(Bind( | 183 bool ret = true; |
186 &Transport::SetRemoteTransportDescription_w, this, | 184 |
187 description, action, error_desc)); | 185 if (!VerifyIceParams(description)) { |
| 186 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", |
| 187 error_desc); |
| 188 } |
| 189 |
| 190 remote_description_.reset(new TransportDescription(description)); |
| 191 for (auto& iter : channels_) { |
| 192 ret &= ApplyRemoteTransportDescription(iter.second.get(), error_desc); |
| 193 } |
| 194 |
| 195 // If PRANSWER/ANSWER is set, we should decide transport protocol type. |
| 196 if (action == CA_PRANSWER || action == CA_ANSWER) { |
| 197 ret = NegotiateTransportDescription(CA_OFFER, error_desc); |
| 198 } |
| 199 if (ret) { |
| 200 remote_description_set_ = true; |
| 201 } |
| 202 |
| 203 return ret; |
188 } | 204 } |
189 | 205 |
190 TransportChannelImpl* Transport::CreateChannel(int component) { | 206 TransportChannelImpl* Transport::CreateChannel(int component) { |
191 return worker_thread_->Invoke<TransportChannelImpl*>(Bind( | |
192 &Transport::CreateChannel_w, this, component)); | |
193 } | |
194 | |
195 TransportChannelImpl* Transport::CreateChannel_w(int component) { | |
196 ASSERT(worker_thread()->IsCurrent()); | |
197 TransportChannelImpl* impl; | 207 TransportChannelImpl* impl; |
198 // TODO(tommi): We don't really need to grab the lock until the actual call | |
199 // to insert() below and presumably hold it throughout initialization of | |
200 // |impl| after the impl_exists check. Maybe we can factor that out to | |
201 // a separate function and not grab the lock in this function. | |
202 // Actually, we probably don't need to hold the lock while initializing | |
203 // |impl| since we can just do the insert when that's done. | |
204 rtc::CritScope cs(&crit_); | |
205 | 208 |
206 // Create the entry if it does not exist. | 209 // Create the entry if it does not exist. |
207 bool impl_exists = false; | 210 bool impl_exists = false; |
208 auto iterator = channels_.find(component); | 211 auto iterator = channels_.find(component); |
209 if (iterator == channels_.end()) { | 212 if (iterator == channels_.end()) { |
210 impl = CreateTransportChannel(component); | 213 impl = CreateTransportChannel(component); |
211 iterator = channels_.insert(std::pair<int, ChannelMapEntry>( | 214 iterator = channels_.insert(std::pair<int, ChannelMapEntry>( |
212 component, ChannelMapEntry(impl))).first; | 215 component, ChannelMapEntry(impl))).first; |
213 } else { | 216 } else { |
214 impl = iterator->second.get(); | 217 impl = iterator->second.get(); |
215 impl_exists = true; | 218 impl_exists = true; |
216 } | 219 } |
217 | 220 |
218 // Increase the ref count. | 221 // Increase the ref count. |
219 iterator->second.AddRef(); | 222 iterator->second.AddRef(); |
220 destroyed_ = false; | 223 channels_destroyed_ = false; |
221 | 224 |
222 if (impl_exists) { | 225 if (impl_exists) { |
223 // If this is an existing channel, we should just return it without | 226 // If this is an existing channel, we should just return it without |
224 // connecting to all the signal again. | 227 // connecting to all the signal again. |
225 return impl; | 228 return impl; |
226 } | 229 } |
227 | 230 |
228 // Push down our transport state to the new channel. | 231 // Push down our transport state to the new channel. |
229 impl->SetIceRole(ice_role_); | 232 impl->SetIceRole(ice_role_); |
230 impl->SetIceTiebreaker(tiebreaker_); | 233 impl->SetIceTiebreaker(tiebreaker_); |
231 impl->SetReceivingTimeout(channel_receiving_timeout_); | 234 impl->SetReceivingTimeout(channel_receiving_timeout_); |
232 // TODO(ronghuawu): Change CreateChannel_w to be able to return error since | 235 // TODO(ronghuawu): Change CreateChannel to be able to return error since |
233 // below Apply**Description_w calls can fail. | 236 // below Apply**Description calls can fail. |
234 if (local_description_) | 237 if (local_description_) |
235 ApplyLocalTransportDescription_w(impl, NULL); | 238 ApplyLocalTransportDescription(impl, NULL); |
236 if (remote_description_) | 239 if (remote_description_) |
237 ApplyRemoteTransportDescription_w(impl, NULL); | 240 ApplyRemoteTransportDescription(impl, NULL); |
238 if (local_description_ && remote_description_) | 241 if (local_description_ && remote_description_) |
239 ApplyNegotiatedTransportDescription_w(impl, NULL); | 242 ApplyNegotiatedTransportDescription(impl, NULL); |
240 | 243 |
241 impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState); | 244 impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState); |
242 impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState); | 245 impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState); |
243 impl->SignalReceivingState.connect(this, &Transport::OnChannelReceivingState); | 246 impl->SignalReceivingState.connect(this, &Transport::OnChannelReceivingState); |
244 impl->SignalRequestSignaling.connect( | 247 impl->SignalGatheringState.connect(this, &Transport::OnChannelGatheringState); |
245 this, &Transport::OnChannelRequestSignaling); | 248 impl->SignalCandidateGathered.connect(this, |
246 impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady); | 249 &Transport::OnChannelCandidateGathered); |
247 impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange); | 250 impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange); |
248 impl->SignalCandidatesAllocationDone.connect( | |
249 this, &Transport::OnChannelCandidatesAllocationDone); | |
250 impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict); | 251 impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict); |
251 impl->SignalConnectionRemoved.connect( | 252 impl->SignalConnectionRemoved.connect( |
252 this, &Transport::OnChannelConnectionRemoved); | 253 this, &Transport::OnChannelConnectionRemoved); |
253 | 254 |
254 if (connect_requested_) { | 255 if (connect_requested_) { |
255 impl->Connect(); | 256 impl->Connect(); |
256 if (channels_.size() == 1) { | 257 if (channels_.size() == 1) { |
257 // If this is the first channel, then indicate that we have started | 258 // If this is the first channel, then indicate that we have started |
258 // connecting. | 259 // connecting. |
259 signaling_thread()->Post(this, MSG_CONNECTING, NULL); | 260 SignalConnecting(this); |
260 } | 261 } |
261 } | 262 } |
262 return impl; | 263 return impl; |
263 } | 264 } |
264 | 265 |
265 TransportChannelImpl* Transport::GetChannel(int component) { | 266 TransportChannelImpl* Transport::GetChannel(int component) { |
266 // TODO(tommi,pthatcher): Since we're returning a pointer from the channels_ | |
267 // map, shouldn't we assume that we're on the worker thread? (The pointer | |
268 // will be used outside of the lock). | |
269 // And if we're on the worker thread, which is the only thread that modifies | |
270 // channels_, can we skip grabbing the lock? | |
271 rtc::CritScope cs(&crit_); | |
272 ChannelMap::iterator iter = channels_.find(component); | 267 ChannelMap::iterator iter = channels_.find(component); |
273 return (iter != channels_.end()) ? iter->second.get() : NULL; | 268 return (iter != channels_.end()) ? iter->second.get() : NULL; |
274 } | 269 } |
275 | 270 |
276 bool Transport::HasChannels() { | 271 bool Transport::HasChannels() { |
277 rtc::CritScope cs(&crit_); | |
278 return !channels_.empty(); | 272 return !channels_.empty(); |
279 } | 273 } |
280 | 274 |
281 void Transport::DestroyChannel(int component) { | 275 void Transport::DestroyChannel(int component) { |
282 worker_thread_->Invoke<void>(Bind( | |
283 &Transport::DestroyChannel_w, this, component)); | |
284 } | |
285 | |
286 void Transport::DestroyChannel_w(int component) { | |
287 ASSERT(worker_thread()->IsCurrent()); | |
288 | |
289 ChannelMap::iterator iter = channels_.find(component); | 276 ChannelMap::iterator iter = channels_.find(component); |
290 if (iter == channels_.end()) | 277 if (iter == channels_.end()) |
291 return; | 278 return; |
292 | 279 |
293 TransportChannelImpl* impl = NULL; | 280 TransportChannelImpl* impl = NULL; |
294 | 281 |
295 iter->second.DecRef(); | 282 iter->second.DecRef(); |
296 if (!iter->second.ref()) { | 283 if (!iter->second.ref()) { |
297 impl = iter->second.get(); | 284 impl = iter->second.get(); |
298 rtc::CritScope cs(&crit_); | |
299 channels_.erase(iter); | 285 channels_.erase(iter); |
300 } | 286 } |
301 | 287 |
302 if (connect_requested_ && channels_.empty()) { | 288 if (connect_requested_ && channels_.empty()) { |
303 // We're no longer attempting to connect. | 289 // We're no longer attempting to connect. |
304 signaling_thread()->Post(this, MSG_CONNECTING, NULL); | 290 SignalConnecting(this); |
305 } | 291 } |
306 | 292 |
307 if (impl) { | 293 if (impl) { |
308 // Check in case the deleted channel was the only non-writable channel. | |
309 OnChannelWritableState(impl); | |
310 DestroyTransportChannel(impl); | 294 DestroyTransportChannel(impl); |
| 295 // Need to update aggregate state after destroying a channel, |
| 296 // for example if it was the only one that wasn't yet writable. |
| 297 UpdateReadableState(); |
| 298 UpdateWritableState(); |
| 299 UpdateReceivingState(); |
| 300 UpdateGatheringState(); |
| 301 MaybeSignalCompleted(); |
311 } | 302 } |
312 } | 303 } |
313 | 304 |
314 void Transport::ConnectChannels() { | 305 void Transport::ConnectChannels() { |
315 ASSERT(signaling_thread()->IsCurrent()); | |
316 worker_thread_->Invoke<void>(Bind(&Transport::ConnectChannels_w, this)); | |
317 } | |
318 | |
319 void Transport::ConnectChannels_w() { | |
320 ASSERT(worker_thread()->IsCurrent()); | |
321 if (connect_requested_ || channels_.empty()) | 306 if (connect_requested_ || channels_.empty()) |
322 return; | 307 return; |
323 | 308 |
324 connect_requested_ = true; | 309 connect_requested_ = true; |
325 signaling_thread()->Post(this, MSG_CANDIDATEREADY, NULL); | 310 |
| 311 if (!ready_candidates_.empty()) { |
| 312 SignalCandidatesGathered(this, ready_candidates_); |
| 313 ready_candidates_.clear(); |
| 314 } |
326 | 315 |
327 if (!local_description_) { | 316 if (!local_description_) { |
328 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here. | 317 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here. |
329 // As Transport must know TD is offer or answer and cricket::Transport | 318 // As Transport must know TD is offer or answer and cricket::Transport |
330 // doesn't have the capability to decide it. This should be set by the | 319 // doesn't have the capability to decide it. This should be set by the |
331 // Session. | 320 // Session. |
332 // Session must generate local TD before remote candidates pushed when | 321 // Session must generate local TD before remote candidates pushed when |
333 // initiate request initiated by the remote. | 322 // initiate request initiated by the remote. |
334 LOG(LS_INFO) << "Transport::ConnectChannels_w: No local description has " | 323 LOG(LS_INFO) << "Transport::ConnectChannels: No local description has " |
335 << "been set. Will generate one."; | 324 << "been set. Will generate one."; |
336 TransportDescription desc(std::vector<std::string>(), | 325 TransportDescription desc( |
337 rtc::CreateRandomString(ICE_UFRAG_LENGTH), | 326 std::vector<std::string>(), rtc::CreateRandomString(ICE_UFRAG_LENGTH), |
338 rtc::CreateRandomString(ICE_PWD_LENGTH), | 327 rtc::CreateRandomString(ICE_PWD_LENGTH), ICEMODE_FULL, |
339 ICEMODE_FULL, CONNECTIONROLE_NONE, NULL, | 328 CONNECTIONROLE_NONE, NULL, Candidates()); |
340 Candidates()); | 329 SetLocalTransportDescription(desc, CA_OFFER, NULL); |
341 SetLocalTransportDescription_w(desc, CA_OFFER, NULL); | |
342 } | 330 } |
343 | 331 |
344 CallChannels_w(&TransportChannelImpl::Connect); | 332 CallChannels(&TransportChannelImpl::Connect); |
345 if (!channels_.empty()) { | 333 if (HasChannels()) { |
346 signaling_thread()->Post(this, MSG_CONNECTING, NULL); | 334 SignalConnecting(this); |
347 } | 335 } |
348 } | 336 } |
349 | 337 |
350 void Transport::OnConnecting_s() { | |
351 ASSERT(signaling_thread()->IsCurrent()); | |
352 SignalConnecting(this); | |
353 } | |
354 | |
355 void Transport::DestroyAllChannels() { | 338 void Transport::DestroyAllChannels() { |
356 ASSERT(signaling_thread()->IsCurrent()); | |
357 worker_thread_->Invoke<void>(Bind(&Transport::DestroyAllChannels_w, this)); | |
358 worker_thread()->Clear(this); | |
359 signaling_thread()->Clear(this); | |
360 destroyed_ = true; | |
361 } | |
362 | |
363 void Transport::DestroyAllChannels_w() { | |
364 ASSERT(worker_thread()->IsCurrent()); | |
365 | |
366 std::vector<TransportChannelImpl*> impls; | 339 std::vector<TransportChannelImpl*> impls; |
367 for (auto& iter : channels_) { | 340 for (auto& iter : channels_) { |
368 iter.second.DecRef(); | 341 iter.second.DecRef(); |
369 if (!iter.second.ref()) | 342 if (!iter.second.ref()) |
370 impls.push_back(iter.second.get()); | 343 impls.push_back(iter.second.get()); |
371 } | 344 } |
372 | 345 |
373 { | 346 channels_.clear(); |
374 rtc::CritScope cs(&crit_); | 347 |
375 channels_.clear(); | 348 for (TransportChannelImpl* impl : impls) { |
| 349 DestroyTransportChannel(impl); |
376 } | 350 } |
377 | 351 channels_destroyed_ = true; |
378 for (size_t i = 0; i < impls.size(); ++i) | |
379 DestroyTransportChannel(impls[i]); | |
380 } | 352 } |
381 | 353 |
382 void Transport::OnSignalingReady() { | 354 void Transport::CallChannels(TransportChannelFunc func) { |
383 ASSERT(signaling_thread()->IsCurrent()); | |
384 if (destroyed_) return; | |
385 | |
386 worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL); | |
387 | |
388 // Notify the subclass. | |
389 OnTransportSignalingReady(); | |
390 } | |
391 | |
392 void Transport::CallChannels_w(TransportChannelFunc func) { | |
393 ASSERT(worker_thread()->IsCurrent()); | |
394 for (const auto& iter : channels_) { | 355 for (const auto& iter : channels_) { |
395 ((iter.second.get())->*func)(); | 356 ((iter.second.get())->*func)(); |
396 } | 357 } |
397 } | 358 } |
398 | 359 |
399 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) { | 360 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) { |
400 // No address zero. | 361 // No address zero. |
401 if (cand.address().IsNil() || cand.address().IsAny()) { | 362 if (cand.address().IsNil() || cand.address().IsAny()) { |
402 *error = "candidate has address of zero"; | 363 *error = "candidate has address of zero"; |
403 return false; | 364 return false; |
(...skipping 18 matching lines...) Expand all Loading... |
422 *error = "candidate has port of 80 or 443 with private IP address"; | 383 *error = "candidate has port of 80 or 443 with private IP address"; |
423 return false; | 384 return false; |
424 } | 385 } |
425 } | 386 } |
426 | 387 |
427 return true; | 388 return true; |
428 } | 389 } |
429 | 390 |
430 | 391 |
431 bool Transport::GetStats(TransportStats* stats) { | 392 bool Transport::GetStats(TransportStats* stats) { |
432 ASSERT(signaling_thread()->IsCurrent()); | 393 stats->transport_name = name(); |
433 return worker_thread_->Invoke<bool>(Bind( | |
434 &Transport::GetStats_w, this, stats)); | |
435 } | |
436 | |
437 bool Transport::GetStats_w(TransportStats* stats) { | |
438 ASSERT(worker_thread()->IsCurrent()); | |
439 stats->content_name = content_name(); | |
440 stats->channel_stats.clear(); | 394 stats->channel_stats.clear(); |
441 for (auto iter : channels_) { | 395 for (auto iter : channels_) { |
442 ChannelMapEntry& entry = iter.second; | 396 ChannelMapEntry& entry = iter.second; |
443 TransportChannelStats substats; | 397 TransportChannelStats substats; |
444 substats.component = entry->component(); | 398 substats.component = entry->component(); |
445 entry->GetSrtpCipher(&substats.srtp_cipher); | 399 entry->GetSrtpCipher(&substats.srtp_cipher); |
446 entry->GetSslCipher(&substats.ssl_cipher); | 400 entry->GetSslCipher(&substats.ssl_cipher); |
447 if (!entry->GetStats(&substats.connection_infos)) { | 401 if (!entry->GetStats(&substats.connection_infos)) { |
448 return false; | 402 return false; |
449 } | 403 } |
450 stats->channel_stats.push_back(substats); | 404 stats->channel_stats.push_back(substats); |
451 } | 405 } |
452 return true; | 406 return true; |
453 } | 407 } |
454 | 408 |
455 bool Transport::GetSslRole(rtc::SSLRole* ssl_role) const { | 409 bool Transport::AddRemoteCandidates(const std::vector<Candidate>& candidates, |
456 return worker_thread_->Invoke<bool>(Bind( | 410 std::string* error) { |
457 &Transport::GetSslRole_w, this, ssl_role)); | 411 ASSERT(!channels_destroyed_); |
458 } | 412 // Verify each candidate before passing down to transport layer. |
| 413 for (const Candidate& cand : candidates) { |
| 414 if (!VerifyCandidate(cand, error)) { |
| 415 return false; |
| 416 } |
| 417 if (!HasChannel(cand.component())) { |
| 418 *error = "Candidate has unknown component: " + cand.ToString() + |
| 419 " for content: " + name(); |
| 420 return false; |
| 421 } |
| 422 } |
459 | 423 |
460 bool Transport::SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) { | |
461 return worker_thread_->Invoke<bool>(Bind( | |
462 &Transport::SetSslMaxProtocolVersion_w, this, version)); | |
463 } | |
464 | |
465 void Transport::OnRemoteCandidates(const std::vector<Candidate>& candidates) { | |
466 for (std::vector<Candidate>::const_iterator iter = candidates.begin(); | 424 for (std::vector<Candidate>::const_iterator iter = candidates.begin(); |
467 iter != candidates.end(); | 425 iter != candidates.end(); |
468 ++iter) { | 426 ++iter) { |
469 OnRemoteCandidate(*iter); | 427 TransportChannelImpl* channel = GetChannel(iter->component()); |
| 428 if (channel != NULL) { |
| 429 channel->AddRemoteCandidate(*iter); |
| 430 } |
470 } | 431 } |
471 } | 432 return true; |
472 | |
473 void Transport::OnRemoteCandidate(const Candidate& candidate) { | |
474 ASSERT(signaling_thread()->IsCurrent()); | |
475 if (destroyed_) return; | |
476 | |
477 if (!HasChannel(candidate.component())) { | |
478 LOG(LS_WARNING) << "Ignoring candidate for unknown component " | |
479 << candidate.component(); | |
480 return; | |
481 } | |
482 | |
483 ChannelParams* params = new ChannelParams(new Candidate(candidate)); | |
484 worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, params); | |
485 } | |
486 | |
487 void Transport::OnRemoteCandidate_w(const Candidate& candidate) { | |
488 ASSERT(worker_thread()->IsCurrent()); | |
489 ChannelMap::iterator iter = channels_.find(candidate.component()); | |
490 // It's ok for a channel to go away while this message is in transit. | |
491 if (iter != channels_.end()) { | |
492 iter->second->OnCandidate(candidate); | |
493 } | |
494 } | 433 } |
495 | 434 |
496 void Transport::OnChannelReadableState(TransportChannel* channel) { | 435 void Transport::OnChannelReadableState(TransportChannel* channel) { |
497 ASSERT(worker_thread()->IsCurrent()); | 436 UpdateReadableState(); |
498 signaling_thread()->Post(this, MSG_READSTATE, NULL); | |
499 } | |
500 | |
501 void Transport::OnChannelReadableState_s() { | |
502 ASSERT(signaling_thread()->IsCurrent()); | |
503 TransportState readable = GetTransportState_s(TRANSPORT_READABLE_STATE); | |
504 if (readable_ != readable) { | |
505 readable_ = readable; | |
506 SignalReadableState(this); | |
507 } | |
508 } | 437 } |
509 | 438 |
510 void Transport::OnChannelWritableState(TransportChannel* channel) { | 439 void Transport::OnChannelWritableState(TransportChannel* channel) { |
511 ASSERT(worker_thread()->IsCurrent()); | 440 LOG(LS_INFO) << name() << " TransportChannel " << channel->component() |
512 signaling_thread()->Post(this, MSG_WRITESTATE, NULL); | 441 << " writability changed to " << channel->writable() |
513 | 442 << ". Check if transport is complete."; |
514 MaybeCompleted_w(); | 443 UpdateWritableState(); |
515 } | 444 MaybeSignalCompleted(); |
516 | |
517 void Transport::OnChannelWritableState_s() { | |
518 ASSERT(signaling_thread()->IsCurrent()); | |
519 TransportState writable = GetTransportState_s(TRANSPORT_WRITABLE_STATE); | |
520 if (writable_ != writable) { | |
521 was_writable_ = (writable_ == TRANSPORT_STATE_ALL); | |
522 writable_ = writable; | |
523 SignalWritableState(this); | |
524 } | |
525 } | 445 } |
526 | 446 |
527 void Transport::OnChannelReceivingState(TransportChannel* channel) { | 447 void Transport::OnChannelReceivingState(TransportChannel* channel) { |
528 ASSERT(worker_thread()->IsCurrent()); | 448 UpdateReceivingState(); |
529 signaling_thread()->Post(this, MSG_RECEIVINGSTATE); | |
530 } | 449 } |
531 | 450 |
532 void Transport::OnChannelReceivingState_s() { | 451 TransportState Transport::GetTransportState(TransportStateType state_type) { |
533 ASSERT(signaling_thread()->IsCurrent()); | |
534 TransportState receiving = GetTransportState_s(TRANSPORT_RECEIVING_STATE); | |
535 if (receiving_ != receiving) { | |
536 receiving_ = receiving; | |
537 SignalReceivingState(this); | |
538 } | |
539 } | |
540 | |
541 TransportState Transport::GetTransportState_s(TransportStateType state_type) { | |
542 ASSERT(signaling_thread()->IsCurrent()); | |
543 | |
544 rtc::CritScope cs(&crit_); | |
545 bool any = false; | 452 bool any = false; |
546 bool all = !channels_.empty(); | 453 bool all = !channels_.empty(); |
547 for (const auto iter : channels_) { | 454 for (const auto iter : channels_) { |
548 bool b = false; | 455 bool b = false; |
549 switch (state_type) { | 456 switch (state_type) { |
550 case TRANSPORT_READABLE_STATE: | 457 case TRANSPORT_READABLE_STATE: |
551 b = iter.second->readable(); | 458 b = iter.second->readable(); |
552 break; | 459 break; |
553 case TRANSPORT_WRITABLE_STATE: | 460 case TRANSPORT_WRITABLE_STATE: |
554 b = iter.second->writable(); | 461 b = iter.second->writable(); |
(...skipping 10 matching lines...) Expand all Loading... |
565 | 472 |
566 if (all) { | 473 if (all) { |
567 return TRANSPORT_STATE_ALL; | 474 return TRANSPORT_STATE_ALL; |
568 } else if (any) { | 475 } else if (any) { |
569 return TRANSPORT_STATE_SOME; | 476 return TRANSPORT_STATE_SOME; |
570 } | 477 } |
571 | 478 |
572 return TRANSPORT_STATE_NONE; | 479 return TRANSPORT_STATE_NONE; |
573 } | 480 } |
574 | 481 |
575 void Transport::OnChannelRequestSignaling(TransportChannelImpl* channel) { | 482 void Transport::OnChannelGatheringState(TransportChannelImpl* channel) { |
576 ASSERT(worker_thread()->IsCurrent()); | 483 ASSERT(channels_.find(channel->component()) != channels_.end()); |
577 // Resetting ICE state for the channel. | 484 UpdateGatheringState(); |
578 ChannelMap::iterator iter = channels_.find(channel->component()); | 485 if (gathering_state_ == kIceGatheringComplete) { |
579 if (iter != channels_.end()) | 486 // If UpdateGatheringState brought us to kIceGatheringComplete, check if |
580 iter->second.set_candidates_allocated(false); | 487 // our connection state is also "Completed". Otherwise, there's no point in |
581 signaling_thread()->Post(this, MSG_REQUESTSIGNALING, nullptr); | 488 // checking (since it would only produce log messages). |
| 489 MaybeSignalCompleted(); |
| 490 } |
582 } | 491 } |
583 | 492 |
584 void Transport::OnChannelRequestSignaling_s() { | 493 void Transport::OnChannelCandidateGathered(TransportChannelImpl* channel, |
585 ASSERT(signaling_thread()->IsCurrent()); | 494 const Candidate& candidate) { |
586 LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates"; | |
587 SignalRequestSignaling(this); | |
588 } | |
589 | |
590 void Transport::OnChannelCandidateReady(TransportChannelImpl* channel, | |
591 const Candidate& candidate) { | |
592 // We should never signal peer-reflexive candidates. | 495 // We should never signal peer-reflexive candidates. |
593 if (candidate.type() == PRFLX_PORT_TYPE) { | 496 if (candidate.type() == PRFLX_PORT_TYPE) { |
594 ASSERT(false); | 497 ASSERT(false); |
595 return; | 498 return; |
596 } | 499 } |
597 | 500 |
598 ASSERT(worker_thread()->IsCurrent()); | |
599 rtc::CritScope cs(&crit_); | |
600 ready_candidates_.push_back(candidate); | |
601 | |
602 // We hold any messages until the client lets us connect. | |
603 if (connect_requested_) { | 501 if (connect_requested_) { |
604 signaling_thread()->Post( | 502 std::vector<Candidate> candidates; |
605 this, MSG_CANDIDATEREADY, NULL); | 503 candidates.push_back(candidate); |
606 } | 504 SignalCandidatesGathered(this, candidates); |
607 } | 505 } else { |
608 | 506 // We hold any candidates until the client lets us connect. |
609 void Transport::OnChannelCandidateReady_s() { | 507 ready_candidates_.push_back(candidate); |
610 ASSERT(signaling_thread()->IsCurrent()); | |
611 ASSERT(connect_requested_); | |
612 | |
613 std::vector<Candidate> candidates; | |
614 { | |
615 rtc::CritScope cs(&crit_); | |
616 candidates.swap(ready_candidates_); | |
617 } | |
618 | |
619 // we do the deleting of Candidate* here to keep the new above and | |
620 // delete below close to each other | |
621 if (!candidates.empty()) { | |
622 SignalCandidatesReady(this, candidates); | |
623 } | 508 } |
624 } | 509 } |
625 | 510 |
626 void Transport::OnChannelRouteChange(TransportChannel* channel, | 511 void Transport::OnChannelRouteChange(TransportChannel* channel, |
627 const Candidate& remote_candidate) { | 512 const Candidate& remote_candidate) { |
628 ASSERT(worker_thread()->IsCurrent()); | |
629 ChannelParams* params = new ChannelParams(new Candidate(remote_candidate)); | |
630 params->channel = static_cast<cricket::TransportChannelImpl*>(channel); | |
631 signaling_thread()->Post(this, MSG_ROUTECHANGE, params); | |
632 } | |
633 | |
634 void Transport::OnChannelRouteChange_s(const TransportChannel* channel, | |
635 const Candidate& remote_candidate) { | |
636 ASSERT(signaling_thread()->IsCurrent()); | |
637 SignalRouteChange(this, remote_candidate.component(), remote_candidate); | 513 SignalRouteChange(this, remote_candidate.component(), remote_candidate); |
638 } | 514 } |
639 | 515 |
640 void Transport::OnChannelCandidatesAllocationDone( | |
641 TransportChannelImpl* channel) { | |
642 ASSERT(worker_thread()->IsCurrent()); | |
643 ChannelMap::iterator iter = channels_.find(channel->component()); | |
644 ASSERT(iter != channels_.end()); | |
645 LOG(LS_INFO) << "Transport: " << content_name_ << ", component " | |
646 << channel->component() << " allocation complete"; | |
647 | |
648 iter->second.set_candidates_allocated(true); | |
649 | |
650 // If all channels belonging to this Transport got signal, then | |
651 // forward this signal to upper layer. | |
652 // Can this signal arrive before all transport channels are created? | |
653 for (auto& iter : channels_) { | |
654 if (!iter.second.candidates_allocated()) | |
655 return; | |
656 } | |
657 signaling_thread_->Post(this, MSG_CANDIDATEALLOCATIONCOMPLETE); | |
658 | |
659 MaybeCompleted_w(); | |
660 } | |
661 | |
662 void Transport::OnChannelCandidatesAllocationDone_s() { | |
663 ASSERT(signaling_thread()->IsCurrent()); | |
664 LOG(LS_INFO) << "Transport: " << content_name_ << " allocation complete"; | |
665 SignalCandidatesAllocationDone(this); | |
666 } | |
667 | |
668 void Transport::OnRoleConflict(TransportChannelImpl* channel) { | 516 void Transport::OnRoleConflict(TransportChannelImpl* channel) { |
669 signaling_thread_->Post(this, MSG_ROLECONFLICT); | 517 SignalRoleConflict(); |
670 } | 518 } |
671 | 519 |
672 void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) { | 520 void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) { |
673 ASSERT(worker_thread()->IsCurrent()); | 521 LOG(LS_INFO) << name() << " TransportChannel " << channel->component() |
674 MaybeCompleted_w(); | 522 << " connection removed. Check if transport is complete."; |
| 523 MaybeSignalCompleted(); |
675 | 524 |
676 // Check if the state is now Failed. | 525 // Check if the state is now Failed. |
677 // Failed is only available in the Controlling ICE role. | 526 // Failed is only available in the Controlling ICE role. |
678 if (channel->GetIceRole() != ICEROLE_CONTROLLING) { | 527 if (channel->GetIceRole() != ICEROLE_CONTROLLING) { |
679 return; | 528 return; |
680 } | 529 } |
681 | 530 |
682 ChannelMap::iterator iter = channels_.find(channel->component()); | 531 // Failed can only occur after candidate gathering has stopped. |
683 ASSERT(iter != channels_.end()); | 532 if (channel->gathering_state() != kIceGatheringComplete) { |
684 // Failed can only occur after candidate allocation has stopped. | |
685 if (!iter->second.candidates_allocated()) { | |
686 return; | 533 return; |
687 } | 534 } |
688 | 535 |
689 if (channel->GetState() == TransportChannelState::STATE_FAILED) { | 536 if (channel->GetState() == TransportChannelState::STATE_FAILED) { |
690 // A Transport has failed if any of its channels have no remaining | 537 // A Transport has failed if any of its channels have no remaining |
691 // connections. | 538 // connections. |
692 signaling_thread_->Post(this, MSG_FAILED); | 539 SignalFailed(this); |
693 } | 540 } |
694 } | 541 } |
695 | 542 |
696 void Transport::MaybeCompleted_w() { | 543 void Transport::MaybeSignalCompleted() { |
697 ASSERT(worker_thread()->IsCurrent()); | 544 if (AllChannelsCompleted()) { |
| 545 LOG(LS_INFO) << name() << " transport is complete" |
| 546 << " because all the channels are complete."; |
| 547 SignalCompleted(this); |
| 548 } |
| 549 // TODO(deadbeef): Should we do anything if we previously were completed, |
| 550 // but now are not (if, for example, a new remote candidate is added)? |
| 551 } |
698 | 552 |
699 // When there is no channel created yet, calling this function could fire an | 553 void Transport::UpdateGatheringState() { |
700 // IceConnectionCompleted event prematurely. | 554 IceGatheringState new_state = kIceGatheringNew; |
701 if (channels_.empty()) { | 555 bool any_gathering = false; |
702 return; | 556 bool all_complete = !channels_.empty(); |
| 557 for (const auto& kv : channels_) { |
| 558 any_gathering = |
| 559 any_gathering || kv.second->gathering_state() != kIceGatheringNew; |
| 560 all_complete = |
| 561 all_complete && kv.second->gathering_state() == kIceGatheringComplete; |
| 562 } |
| 563 if (all_complete) { |
| 564 new_state = kIceGatheringComplete; |
| 565 } else if (any_gathering) { |
| 566 new_state = kIceGatheringGathering; |
703 } | 567 } |
704 | 568 |
705 // A Transport's ICE process is completed if all of its channels are writable, | 569 if (gathering_state_ != new_state) { |
706 // have finished allocating candidates, and have pruned all but one of their | 570 gathering_state_ = new_state; |
707 // connections. | 571 if (gathering_state_ == kIceGatheringGathering) { |
708 for (const auto& iter : channels_) { | 572 LOG(LS_INFO) << "Transport: " << name_ << ", gathering candidates"; |
709 const TransportChannelImpl* channel = iter.second.get(); | 573 } else if (gathering_state_ == kIceGatheringComplete) { |
710 if (!(channel->writable() && | 574 LOG(LS_INFO) << "Transport " << name() << " gathering complete."; |
711 channel->GetState() == TransportChannelState::STATE_COMPLETED && | |
712 channel->GetIceRole() == ICEROLE_CONTROLLING && | |
713 iter.second.candidates_allocated())) { | |
714 return; | |
715 } | 575 } |
716 } | 576 SignalGatheringState(this); |
717 | |
718 signaling_thread_->Post(this, MSG_COMPLETED); | |
719 } | |
720 | |
721 void Transport::SetIceRole_w(IceRole role) { | |
722 ASSERT(worker_thread()->IsCurrent()); | |
723 rtc::CritScope cs(&crit_); | |
724 ice_role_ = role; | |
725 for (auto& iter : channels_) { | |
726 iter.second->SetIceRole(ice_role_); | |
727 } | 577 } |
728 } | 578 } |
729 | 579 |
730 void Transport::SetRemoteIceMode_w(IceMode mode) { | 580 void Transport::UpdateReceivingState() { |
731 ASSERT(worker_thread()->IsCurrent()); | 581 TransportState receiving = GetTransportState(TRANSPORT_RECEIVING_STATE); |
732 remote_ice_mode_ = mode; | 582 if (receiving_ != receiving) { |
733 // Shouldn't channels be created after this method executed? | 583 receiving_ = receiving; |
734 for (auto& iter : channels_) { | 584 SignalReceivingState(this); |
735 iter.second->SetRemoteIceMode(remote_ice_mode_); | |
736 } | 585 } |
737 } | 586 } |
738 | 587 |
739 bool Transport::SetLocalTransportDescription_w( | 588 void Transport::UpdateWritableState() { |
740 const TransportDescription& desc, | 589 TransportState writable = GetTransportState(TRANSPORT_WRITABLE_STATE); |
741 ContentAction action, | 590 LOG(LS_INFO) << name() << " transport writable state changed? " << writable_ |
742 std::string* error_desc) { | 591 << " => " << writable; |
743 ASSERT(worker_thread()->IsCurrent()); | 592 if (writable_ != writable) { |
744 bool ret = true; | 593 was_writable_ = (writable_ == TRANSPORT_STATE_ALL); |
745 | 594 writable_ = writable; |
746 if (!VerifyIceParams(desc)) { | 595 SignalWritableState(this); |
747 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", | |
748 error_desc); | |
749 } | 596 } |
750 | |
751 // TODO(tommi,pthatcher): I'm not sure why we need to grab this lock at this | |
752 // point. |local_description_| seems to always be modified on the worker | |
753 // thread, so we should be able to use it here without grabbing the lock. | |
754 // However, we _might_ need it before the call to reset() below? | |
755 // Raw access to |local_description_| is granted to derived transports outside | |
756 // of locking (see local_description() in the header file). | |
757 // The contract is that the derived implementations must be aware of when the | |
758 // description might change and do appropriate synchronization. | |
759 rtc::CritScope cs(&crit_); | |
760 if (local_description_ && IceCredentialsChanged(*local_description_, desc)) { | |
761 IceRole new_ice_role = (action == CA_OFFER) ? ICEROLE_CONTROLLING | |
762 : ICEROLE_CONTROLLED; | |
763 | |
764 // It must be called before ApplyLocalTransportDescription_w, which may | |
765 // trigger an ICE restart and depends on the new ICE role. | |
766 SetIceRole_w(new_ice_role); | |
767 } | |
768 | |
769 local_description_.reset(new TransportDescription(desc)); | |
770 | |
771 for (auto& iter : channels_) { | |
772 ret &= ApplyLocalTransportDescription_w(iter.second.get(), error_desc); | |
773 } | |
774 if (!ret) | |
775 return false; | |
776 | |
777 // If PRANSWER/ANSWER is set, we should decide transport protocol type. | |
778 if (action == CA_PRANSWER || action == CA_ANSWER) { | |
779 ret &= NegotiateTransportDescription_w(action, error_desc); | |
780 } | |
781 return ret; | |
782 } | 597 } |
783 | 598 |
784 bool Transport::SetRemoteTransportDescription_w( | 599 void Transport::UpdateReadableState() { |
785 const TransportDescription& desc, | 600 TransportState readable = GetTransportState(TRANSPORT_READABLE_STATE); |
786 ContentAction action, | 601 if (readable_ != readable) { |
787 std::string* error_desc) { | 602 readable_ = readable; |
788 bool ret = true; | 603 SignalReadableState(this); |
789 | |
790 if (!VerifyIceParams(desc)) { | |
791 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length", | |
792 error_desc); | |
793 } | 604 } |
794 | |
795 // TODO(tommi,pthatcher): See todo for local_description_ above. | |
796 rtc::CritScope cs(&crit_); | |
797 remote_description_.reset(new TransportDescription(desc)); | |
798 for (auto& iter : channels_) { | |
799 ret &= ApplyRemoteTransportDescription_w(iter.second.get(), error_desc); | |
800 } | |
801 | |
802 // If PRANSWER/ANSWER is set, we should decide transport protocol type. | |
803 if (action == CA_PRANSWER || action == CA_ANSWER) { | |
804 ret = NegotiateTransportDescription_w(CA_OFFER, error_desc); | |
805 } | |
806 return ret; | |
807 } | 605 } |
808 | 606 |
809 bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch, | 607 bool Transport::ApplyLocalTransportDescription(TransportChannelImpl* ch, |
810 std::string* error_desc) { | 608 std::string* error_desc) { |
811 ASSERT(worker_thread()->IsCurrent()); | |
812 ch->SetIceCredentials(local_description_->ice_ufrag, | 609 ch->SetIceCredentials(local_description_->ice_ufrag, |
813 local_description_->ice_pwd); | 610 local_description_->ice_pwd); |
814 return true; | 611 return true; |
815 } | 612 } |
816 | 613 |
817 bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch, | 614 bool Transport::ApplyRemoteTransportDescription(TransportChannelImpl* ch, |
818 std::string* error_desc) { | 615 std::string* error_desc) { |
819 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, | 616 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, |
820 remote_description_->ice_pwd); | 617 remote_description_->ice_pwd); |
821 return true; | 618 return true; |
822 } | 619 } |
823 | 620 |
824 bool Transport::ApplyNegotiatedTransportDescription_w( | 621 bool Transport::ApplyNegotiatedTransportDescription( |
825 TransportChannelImpl* channel, std::string* error_desc) { | 622 TransportChannelImpl* channel, |
826 ASSERT(worker_thread()->IsCurrent()); | 623 std::string* error_desc) { |
827 channel->SetRemoteIceMode(remote_ice_mode_); | 624 channel->SetRemoteIceMode(remote_ice_mode_); |
828 return true; | 625 return true; |
829 } | 626 } |
830 | 627 |
831 bool Transport::NegotiateTransportDescription_w(ContentAction local_role, | 628 bool Transport::NegotiateTransportDescription(ContentAction local_role, |
832 std::string* error_desc) { | 629 std::string* error_desc) { |
833 ASSERT(worker_thread()->IsCurrent()); | |
834 // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into | 630 // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into |
835 // P2PTransport. | 631 // P2PTransport. |
836 | 632 |
837 // If transport is in ICEROLE_CONTROLLED and remote end point supports only | 633 // If transport is in ICEROLE_CONTROLLED and remote end point supports only |
838 // ice_lite, this local end point should take CONTROLLING role. | 634 // ice_lite, this local end point should take CONTROLLING role. |
839 if (ice_role_ == ICEROLE_CONTROLLED && | 635 if (ice_role_ == ICEROLE_CONTROLLED && |
840 remote_description_->ice_mode == ICEMODE_LITE) { | 636 remote_description_->ice_mode == ICEMODE_LITE) { |
841 SetIceRole_w(ICEROLE_CONTROLLING); | 637 SetIceRole(ICEROLE_CONTROLLING); |
842 } | 638 } |
843 | 639 |
844 // Update remote ice_mode to all existing channels. | 640 // Update remote ice_mode to all existing channels. |
845 remote_ice_mode_ = remote_description_->ice_mode; | 641 remote_ice_mode_ = remote_description_->ice_mode; |
846 | 642 |
847 // Now that we have negotiated everything, push it downward. | 643 // Now that we have negotiated everything, push it downward. |
848 // Note that we cache the result so that if we have race conditions | 644 // Note that we cache the result so that if we have race conditions |
849 // between future SetRemote/SetLocal invocations and new channel | 645 // between future SetRemote/SetLocal invocations and new channel |
850 // creation, we have the negotiation state saved until a new | 646 // creation, we have the negotiation state saved until a new |
851 // negotiation happens. | 647 // negotiation happens. |
852 for (auto& iter : channels_) { | 648 for (auto& iter : channels_) { |
853 if (!ApplyNegotiatedTransportDescription_w(iter.second.get(), error_desc)) | 649 if (!ApplyNegotiatedTransportDescription(iter.second.get(), error_desc)) |
854 return false; | 650 return false; |
855 } | 651 } |
856 return true; | 652 return true; |
857 } | 653 } |
858 | 654 |
859 void Transport::OnMessage(rtc::Message* msg) { | |
860 switch (msg->message_id) { | |
861 case MSG_ONSIGNALINGREADY: | |
862 CallChannels_w(&TransportChannelImpl::OnSignalingReady); | |
863 break; | |
864 case MSG_ONREMOTECANDIDATE: { | |
865 ChannelParams* params = static_cast<ChannelParams*>(msg->pdata); | |
866 OnRemoteCandidate_w(*params->candidate); | |
867 delete params; | |
868 } | |
869 break; | |
870 case MSG_CONNECTING: | |
871 OnConnecting_s(); | |
872 break; | |
873 case MSG_READSTATE: | |
874 OnChannelReadableState_s(); | |
875 break; | |
876 case MSG_WRITESTATE: | |
877 OnChannelWritableState_s(); | |
878 break; | |
879 case MSG_RECEIVINGSTATE: | |
880 OnChannelReceivingState_s(); | |
881 break; | |
882 case MSG_REQUESTSIGNALING: | |
883 OnChannelRequestSignaling_s(); | |
884 break; | |
885 case MSG_CANDIDATEREADY: | |
886 OnChannelCandidateReady_s(); | |
887 break; | |
888 case MSG_ROUTECHANGE: { | |
889 ChannelParams* params = static_cast<ChannelParams*>(msg->pdata); | |
890 OnChannelRouteChange_s(params->channel, *params->candidate); | |
891 delete params; | |
892 } | |
893 break; | |
894 case MSG_CANDIDATEALLOCATIONCOMPLETE: | |
895 OnChannelCandidatesAllocationDone_s(); | |
896 break; | |
897 case MSG_ROLECONFLICT: | |
898 SignalRoleConflict(); | |
899 break; | |
900 case MSG_COMPLETED: | |
901 SignalCompleted(this); | |
902 break; | |
903 case MSG_FAILED: | |
904 SignalFailed(this); | |
905 break; | |
906 } | |
907 } | |
908 | |
909 } // namespace cricket | 655 } // namespace cricket |
OLD | NEW |