Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: webrtc/p2p/base/transport.cc

Issue 1246913005: TransportController refactoring (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fixing problems with "failed" state; a channel isn't failed if it's never added a connection Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698