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