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