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

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: minor cleanup Created 5 years, 4 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 candidate_gathering_state_(kGatheringNew) {
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::Completed() 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->candidate_gathering_state() == kGatheringDone)) {
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 void Transport::SetIceRole(IceRole role) {
152 worker_thread_->Invoke<void>(Bind(&Transport::SetIdentity_w, this, identity)); 141 ice_role_ = role;
153 } 142 for (auto& iter : channels_) {
154 143 iter.second->SetIceRole(ice_role_);
155 bool Transport::GetIdentity(rtc::SSLIdentity** identity) { 144 }
156 // The identity is set on the worker thread, so for safety it must also be
157 // acquired on the worker thread.
158 return worker_thread_->Invoke<bool>(
159 Bind(&Transport::GetIdentity_w, this, identity));
160 } 145 }
161 146
162 bool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) { 147 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()) 148 if (channels_.empty())
172 return false; 149 return false;
173 150
174 ChannelMap::iterator iter = channels_.begin(); 151 ChannelMap::iterator iter = channels_.begin();
175 return iter->second->GetRemoteCertificate(cert); 152 return iter->second->GetRemoteCertificate(cert);
176 } 153 }
177 154
178 void Transport::SetChannelReceivingTimeout(int timeout_ms) { 155 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; 156 channel_receiving_timeout_ = timeout_ms;
186 for (const auto& kv : channels_) { 157 for (const auto& kv : channels_) {
187 kv.second->SetReceivingTimeout(timeout_ms); 158 kv.second->SetReceivingTimeout(timeout_ms);
188 } 159 }
189 } 160 }
190 161
191 bool Transport::SetLocalTransportDescription( 162 bool Transport::SetLocalTransportDescription(
192 const TransportDescription& description, 163 const TransportDescription& description,
193 ContentAction action, 164 ContentAction action,
194 std::string* error_desc) { 165 std::string* error_desc) {
195 return worker_thread_->Invoke<bool>(Bind( 166 bool ret = true;
196 &Transport::SetLocalTransportDescription_w, this, 167
197 description, action, error_desc)); 168 if (!VerifyIceParams(description)) {
169 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
170 error_desc);
171 }
172
173 if (local_description_ &&
174 IceCredentialsChanged(*local_description_, description)) {
175 IceRole new_ice_role = (action == CA_OFFER) ? ICEROLE_CONTROLLING
176 : ICEROLE_CONTROLLED;
177
178 // It must be called before ApplyLocalTransportDescription, which may
179 // trigger an ICE restart and depends on the new ICE role.
180 SetIceRole(new_ice_role);
181 }
182
183 local_description_.reset(new TransportDescription(description));
184
185 for (auto& iter : channels_) {
186 ret &= ApplyLocalTransportDescription(iter.second.get(), error_desc);
187 }
188 if (!ret)
189 return false;
190
191 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
192 if (action == CA_PRANSWER || action == CA_ANSWER) {
193 ret &= NegotiateTransportDescription(action, error_desc);
194 }
195 if (ret) {
196 local_description_set_ = true;
197 }
198
199 return ret;
198 } 200 }
199 201
200 bool Transport::SetRemoteTransportDescription( 202 bool Transport::SetRemoteTransportDescription(
201 const TransportDescription& description, 203 const TransportDescription& description,
202 ContentAction action, 204 ContentAction action,
203 std::string* error_desc) { 205 std::string* error_desc) {
204 return worker_thread_->Invoke<bool>(Bind( 206 bool ret = true;
205 &Transport::SetRemoteTransportDescription_w, this, 207
206 description, action, error_desc)); 208 if (!VerifyIceParams(description)) {
209 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
210 error_desc);
211 }
212
213 remote_description_.reset(new TransportDescription(description));
214 for (auto& iter : channels_) {
215 ret &= ApplyRemoteTransportDescription(iter.second.get(), error_desc);
216 }
217
218 // If PRANSWER/ANSWER is set, we should decide transport protocol type.
219 if (action == CA_PRANSWER || action == CA_ANSWER) {
220 ret = NegotiateTransportDescription(CA_OFFER, error_desc);
221 }
222 if (ret) {
223 remote_description_set_ = true;
224 }
225
226 return ret;
207 } 227 }
208 228
209 TransportChannelImpl* Transport::CreateChannel(int component) { 229 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; 230 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 231
225 // Create the entry if it does not exist. 232 // Create the entry if it does not exist.
226 bool impl_exists = false; 233 bool impl_exists = false;
227 auto iterator = channels_.find(component); 234 auto iterator = channels_.find(component);
228 if (iterator == channels_.end()) { 235 if (iterator == channels_.end()) {
229 impl = CreateTransportChannel(component); 236 impl = CreateTransportChannel(component);
230 iterator = channels_.insert(std::pair<int, ChannelMapEntry>( 237 iterator = channels_.insert(std::pair<int, ChannelMapEntry>(
231 component, ChannelMapEntry(impl))).first; 238 component, ChannelMapEntry(impl))).first;
232 } else { 239 } else {
233 impl = iterator->second.get(); 240 impl = iterator->second.get();
234 impl_exists = true; 241 impl_exists = true;
235 } 242 }
236 243
237 // Increase the ref count. 244 // Increase the ref count.
238 iterator->second.AddRef(); 245 iterator->second.AddRef();
239 destroyed_ = false; 246 destroyed_ = false;
240 247
241 if (impl_exists) { 248 if (impl_exists) {
242 // If this is an existing channel, we should just return it without 249 // If this is an existing channel, we should just return it without
243 // connecting to all the signal again. 250 // connecting to all the signal again.
244 return impl; 251 return impl;
245 } 252 }
246 253
247 // Push down our transport state to the new channel. 254 // Push down our transport state to the new channel.
248 impl->SetIceRole(ice_role_); 255 impl->SetIceRole(ice_role_);
249 impl->SetIceTiebreaker(tiebreaker_); 256 impl->SetIceTiebreaker(tiebreaker_);
250 impl->SetReceivingTimeout(channel_receiving_timeout_); 257 impl->SetReceivingTimeout(channel_receiving_timeout_);
251 // TODO(ronghuawu): Change CreateChannel_w to be able to return error since 258 // TODO(ronghuawu): Change CreateChannel to be able to return error since
252 // below Apply**Description_w calls can fail. 259 // below Apply**Description calls can fail.
253 if (local_description_) 260 if (local_description_)
254 ApplyLocalTransportDescription_w(impl, NULL); 261 ApplyLocalTransportDescription(impl, NULL);
255 if (remote_description_) 262 if (remote_description_)
256 ApplyRemoteTransportDescription_w(impl, NULL); 263 ApplyRemoteTransportDescription(impl, NULL);
257 if (local_description_ && remote_description_) 264 if (local_description_ && remote_description_)
258 ApplyNegotiatedTransportDescription_w(impl, NULL); 265 ApplyNegotiatedTransportDescription(impl, NULL);
259 266
260 impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState); 267 impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState);
261 impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState); 268 impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState);
262 impl->SignalReceivingState.connect(this, &Transport::OnChannelReceivingState); 269 impl->SignalReceivingState.connect(this, &Transport::OnChannelReceivingState);
263 impl->SignalRequestSignaling.connect( 270 impl->SignalCandidatesAllocationStarted.connect(
264 this, &Transport::OnChannelRequestSignaling); 271 this, &Transport::OnChannelCandidatesAllocationStarted);
265 impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady); 272 impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady);
266 impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange); 273 impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange);
267 impl->SignalCandidatesAllocationDone.connect( 274 impl->SignalCandidatesAllocationDone.connect(
268 this, &Transport::OnChannelCandidatesAllocationDone); 275 this, &Transport::OnChannelCandidatesAllocationDone);
269 impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict); 276 impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict);
270 impl->SignalConnectionRemoved.connect( 277 impl->SignalConnectionRemoved.connect(
271 this, &Transport::OnChannelConnectionRemoved); 278 this, &Transport::OnChannelConnectionRemoved);
272 279
273 if (connect_requested_) { 280 if (connect_requested_) {
274 impl->Connect(); 281 impl->Connect();
275 if (channels_.size() == 1) { 282 if (channels_.size() == 1) {
276 // If this is the first channel, then indicate that we have started 283 // If this is the first channel, then indicate that we have started
277 // connecting. 284 // connecting.
278 signaling_thread()->Post(this, MSG_CONNECTING, NULL); 285 SignalConnecting(this);
279 } 286 }
280 } 287 }
281 return impl; 288 return impl;
282 } 289 }
283 290
284 TransportChannelImpl* Transport::GetChannel(int component) { 291 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); 292 ChannelMap::iterator iter = channels_.find(component);
292 return (iter != channels_.end()) ? iter->second.get() : NULL; 293 return (iter != channels_.end()) ? iter->second.get() : NULL;
293 } 294 }
294 295
295 bool Transport::HasChannels() { 296 bool Transport::HasChannels() {
296 rtc::CritScope cs(&crit_);
297 return !channels_.empty(); 297 return !channels_.empty();
298 } 298 }
299 299
300 void Transport::DestroyChannel(int component) { 300 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); 301 ChannelMap::iterator iter = channels_.find(component);
309 if (iter == channels_.end()) 302 if (iter == channels_.end())
310 return; 303 return;
311 304
312 TransportChannelImpl* impl = NULL; 305 TransportChannelImpl* impl = NULL;
313 306
314 iter->second.DecRef(); 307 iter->second.DecRef();
315 if (!iter->second.ref()) { 308 if (!iter->second.ref()) {
316 impl = iter->second.get(); 309 impl = iter->second.get();
317 rtc::CritScope cs(&crit_);
318 channels_.erase(iter); 310 channels_.erase(iter);
319 } 311 }
320 312
321 if (connect_requested_ && channels_.empty()) { 313 if (connect_requested_ && channels_.empty()) {
322 // We're no longer attempting to connect. 314 // We're no longer attempting to connect.
323 signaling_thread()->Post(this, MSG_CONNECTING, NULL); 315 SignalConnecting(this);
324 } 316 }
325 317
326 if (impl) { 318 if (impl) {
327 // Check in case the deleted channel was the only non-writable channel.
328 OnChannelWritableState(impl);
329 DestroyTransportChannel(impl); 319 DestroyTransportChannel(impl);
320 // Need to update aggregate state after destroying a channel,
321 // for example if it was the only one that wasn't yet writable.
322 CheckIfCompleted();
323 UpdateReadableState();
324 UpdateWritableState();
325 UpdateReceivingState();
326 CheckIfCandidatesAllocationDone();
330 } 327 }
331 } 328 }
332 329
333 void Transport::ConnectChannels() { 330 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()) 331 if (connect_requested_ || channels_.empty())
341 return; 332 return;
342 333
343 connect_requested_ = true; 334 connect_requested_ = true;
344 signaling_thread()->Post(this, MSG_CANDIDATEREADY, NULL); 335
336 if (!ready_candidates_.empty()) {
337 SignalCandidatesReady(this, ready_candidates_);
338 ready_candidates_.clear();
339 }
345 340
346 if (!local_description_) { 341 if (!local_description_) {
347 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here. 342 // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here.
348 // As Transport must know TD is offer or answer and cricket::Transport 343 // 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 344 // doesn't have the capability to decide it. This should be set by the
350 // Session. 345 // Session.
351 // Session must generate local TD before remote candidates pushed when 346 // Session must generate local TD before remote candidates pushed when
352 // initiate request initiated by the remote. 347 // initiate request initiated by the remote.
353 LOG(LS_INFO) << "Transport::ConnectChannels_w: No local description has " 348 LOG(LS_INFO) << "Transport::ConnectChannels: No local description has "
354 << "been set. Will generate one."; 349 << "been set. Will generate one.";
355 TransportDescription desc(NS_GINGLE_P2P, std::vector<std::string>(), 350 TransportDescription desc(NS_GINGLE_P2P, std::vector<std::string>(),
356 rtc::CreateRandomString(ICE_UFRAG_LENGTH), 351 rtc::CreateRandomString(ICE_UFRAG_LENGTH),
357 rtc::CreateRandomString(ICE_PWD_LENGTH), 352 rtc::CreateRandomString(ICE_PWD_LENGTH),
358 ICEMODE_FULL, CONNECTIONROLE_NONE, NULL, 353 ICEMODE_FULL, CONNECTIONROLE_NONE, NULL,
359 Candidates()); 354 Candidates());
360 SetLocalTransportDescription_w(desc, CA_OFFER, NULL); 355 SetLocalTransportDescription(desc, CA_OFFER, NULL);
361 } 356 }
362 357
363 CallChannels_w(&TransportChannelImpl::Connect); 358 CallChannels(&TransportChannelImpl::Connect);
364 if (!channels_.empty()) { 359 if (HasChannels()) {
365 signaling_thread()->Post(this, MSG_CONNECTING, NULL); 360 SignalConnecting(this);
366 } 361 }
367 } 362 }
368 363
369 void Transport::OnConnecting_s() {
370 ASSERT(signaling_thread()->IsCurrent());
371 SignalConnecting(this);
372 }
373
374 void Transport::DestroyAllChannels() { 364 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; 365 std::vector<TransportChannelImpl*> impls;
386 for (auto& iter : channels_) { 366 for (auto& iter : channels_) {
387 iter.second.DecRef(); 367 iter.second.DecRef();
388 if (!iter.second.ref()) 368 if (!iter.second.ref())
389 impls.push_back(iter.second.get()); 369 impls.push_back(iter.second.get());
390 } 370 }
391 371
392 { 372 channels_.clear();
393 rtc::CritScope cs(&crit_); 373
394 channels_.clear(); 374 for (size_t i = 0; i < impls.size(); ++i) {
375 DestroyTransportChannel(impls[i]);
395 } 376 }
396 377 destroyed_ = true;
397 for (size_t i = 0; i < impls.size(); ++i)
398 DestroyTransportChannel(impls[i]);
399 } 378 }
400 379
401 void Transport::OnSignalingReady() { 380 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_) { 381 for (const auto& iter : channels_) {
414 ((iter.second.get())->*func)(); 382 ((iter.second.get())->*func)();
415 } 383 }
416 } 384 }
417 385
418 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) { 386 bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) {
419 // No address zero. 387 // No address zero.
420 if (cand.address().IsNil() || cand.address().IsAny()) { 388 if (cand.address().IsNil() || cand.address().IsAny()) {
421 *error = "candidate has address of zero"; 389 *error = "candidate has address of zero";
422 return false; 390 return false;
(...skipping 18 matching lines...) Expand all
441 *error = "candidate has port of 80 or 443 with private IP address"; 409 *error = "candidate has port of 80 or 443 with private IP address";
442 return false; 410 return false;
443 } 411 }
444 } 412 }
445 413
446 return true; 414 return true;
447 } 415 }
448 416
449 417
450 bool Transport::GetStats(TransportStats* stats) { 418 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(); 419 stats->content_name = content_name();
459 stats->channel_stats.clear(); 420 stats->channel_stats.clear();
460 for (auto iter : channels_) { 421 for (auto iter : channels_) {
461 ChannelMapEntry& entry = iter.second; 422 ChannelMapEntry& entry = iter.second;
462 TransportChannelStats substats; 423 TransportChannelStats substats;
463 substats.component = entry->component(); 424 substats.component = entry->component();
464 entry->GetSrtpCipher(&substats.srtp_cipher); 425 entry->GetSrtpCipher(&substats.srtp_cipher);
465 entry->GetSslCipher(&substats.ssl_cipher); 426 entry->GetSslCipher(&substats.ssl_cipher);
466 if (!entry->GetStats(&substats.connection_infos)) { 427 if (!entry->GetStats(&substats.connection_infos)) {
467 return false; 428 return false;
468 } 429 }
469 stats->channel_stats.push_back(substats); 430 stats->channel_stats.push_back(substats);
470 } 431 }
471 return true; 432 return true;
472 } 433 }
473 434
474 bool Transport::GetSslRole(rtc::SSLRole* ssl_role) const { 435 bool Transport::AddRemoteCandidates(
475 return worker_thread_->Invoke<bool>(Bind( 436 const std::vector<Candidate>& candidates, std::string* error) {
476 &Transport::GetSslRole_w, this, ssl_role)); 437 // Verify each candidate before passing down to transport layer.
477 } 438 for (const Candidate& cand : candidates) {
439 if (!VerifyCandidate(cand, error)) {
440 return false;
441 }
442 if (!HasChannel(cand.component())) {
443 *error = "Candidate has unknown component: " + cand.ToString() +
444 " for content: " + content_name_;
445 return false;
446 }
447 }
478 448
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(); 449 for (std::vector<Candidate>::const_iterator iter = candidates.begin();
486 iter != candidates.end(); 450 iter != candidates.end();
487 ++iter) { 451 ++iter) {
488 OnRemoteCandidate(*iter); 452 AddRemoteCandidate(*iter);
489 } 453 }
454 return true;
490 } 455 }
491 456
492 void Transport::OnRemoteCandidate(const Candidate& candidate) { 457 void Transport::AddRemoteCandidate(const Candidate& candidate) {
493 ASSERT(signaling_thread()->IsCurrent());
494 if (destroyed_) return; 458 if (destroyed_) return;
495 459
496 if (!HasChannel(candidate.component())) { 460 TransportChannelImpl* channel = GetChannel(candidate.component());
497 LOG(LS_WARNING) << "Ignoring candidate for unknown component " 461 if (channel != NULL) {
498 << candidate.component(); 462 channel->OnCandidate(candidate);
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 } 463 }
513 } 464 }
514 465
515 void Transport::OnChannelReadableState(TransportChannel* channel) { 466 void Transport::OnChannelReadableState(TransportChannel* channel) {
516 ASSERT(worker_thread()->IsCurrent()); 467 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 } 468 }
528 469
529 void Transport::OnChannelWritableState(TransportChannel* channel) { 470 void Transport::OnChannelWritableState(TransportChannel* channel) {
530 ASSERT(worker_thread()->IsCurrent()); 471 LOG(LS_INFO) << content_name() << " TransportChannel " << channel->component()
531 signaling_thread()->Post(this, MSG_WRITESTATE, NULL); 472 << " writability changed to " << channel->writable()
532 473 << ". Check if transport is complete.";
533 MaybeCompleted_w(); 474 UpdateWritableState();
534 } 475 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 } 476 }
545 477
546 void Transport::OnChannelReceivingState(TransportChannel* channel) { 478 void Transport::OnChannelReceivingState(TransportChannel* channel) {
547 ASSERT(worker_thread()->IsCurrent()); 479 UpdateReceivingState();
548 signaling_thread()->Post(this, MSG_RECEIVINGSTATE);
549 } 480 }
550 481
551 void Transport::OnChannelReceivingState_s() { 482 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; 483 bool any = false;
565 bool all = !channels_.empty(); 484 bool all = !channels_.empty();
566 for (const auto iter : channels_) { 485 for (const auto iter : channels_) {
567 bool b = false; 486 bool b = false;
568 switch (state_type) { 487 switch (state_type) {
569 case TRANSPORT_READABLE_STATE: 488 case TRANSPORT_READABLE_STATE:
570 b = iter.second->readable(); 489 b = iter.second->readable();
571 break; 490 break;
572 case TRANSPORT_WRITABLE_STATE: 491 case TRANSPORT_WRITABLE_STATE:
573 b = iter.second->writable(); 492 b = iter.second->writable();
(...skipping 10 matching lines...) Expand all
584 503
585 if (all) { 504 if (all) {
586 return TRANSPORT_STATE_ALL; 505 return TRANSPORT_STATE_ALL;
587 } else if (any) { 506 } else if (any) {
588 return TRANSPORT_STATE_SOME; 507 return TRANSPORT_STATE_SOME;
589 } 508 }
590 509
591 return TRANSPORT_STATE_NONE; 510 return TRANSPORT_STATE_NONE;
592 } 511 }
593 512
594 void Transport::OnChannelRequestSignaling(TransportChannelImpl* channel) { 513 void Transport::OnChannelCandidatesAllocationStarted(
595 ASSERT(worker_thread()->IsCurrent()); 514 TransportChannelImpl* channel) {
596 // Resetting ICE state for the channel. 515 if (candidate_gathering_state_ != kGatheringGathering) {
597 ChannelMap::iterator iter = channels_.find(channel->component()); 516 candidate_gathering_state_ = kGatheringGathering;
598 if (iter != channels_.end()) 517 LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates";
599 iter->second.set_candidates_allocated(false); 518 SignalCandidatesAllocationStarted(this);
600 signaling_thread()->Post(this, MSG_REQUESTSIGNALING, nullptr); 519 }
601 }
602
603 void Transport::OnChannelRequestSignaling_s() {
604 ASSERT(signaling_thread()->IsCurrent());
605 LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates";
606 SignalRequestSignaling(this);
607 } 520 }
608 521
609 void Transport::OnChannelCandidateReady(TransportChannelImpl* channel, 522 void Transport::OnChannelCandidateReady(TransportChannelImpl* channel,
610 const Candidate& candidate) { 523 const Candidate& candidate) {
611 // We should never signal peer-reflexive candidates. 524 // We should never signal peer-reflexive candidates.
612 if (candidate.type() == PRFLX_PORT_TYPE) { 525 if (candidate.type() == PRFLX_PORT_TYPE) {
613 ASSERT(false); 526 ASSERT(false);
614 return; 527 return;
615 } 528 }
616 529
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_) { 530 if (connect_requested_) {
623 signaling_thread()->Post( 531 std::vector<Candidate> candidates;
624 this, MSG_CANDIDATEREADY, NULL); 532 candidates.push_back(candidate);
625 }
626 }
627
628 void Transport::OnChannelCandidateReady_s() {
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); 533 SignalCandidatesReady(this, candidates);
534 } else {
535 // We hold any candidates until the client lets us connect.
536 ready_candidates_.push_back(candidate);
642 } 537 }
643 } 538 }
644 539
645 void Transport::OnChannelRouteChange(TransportChannel* channel, 540 void Transport::OnChannelRouteChange(TransportChannel* channel,
646 const Candidate& remote_candidate) { 541 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); 542 SignalRouteChange(this, remote_candidate.component(), remote_candidate);
657 } 543 }
658 544
659 void Transport::OnChannelCandidatesAllocationDone( 545 void Transport::OnChannelCandidatesAllocationDone(
660 TransportChannelImpl* channel) { 546 TransportChannelImpl* channel) {
661 ASSERT(worker_thread()->IsCurrent()); 547 ASSERT(channels_.find(channel->component()) != channels_.end());
662 ChannelMap::iterator iter = channels_.find(channel->component());
663 ASSERT(iter != channels_.end());
664 LOG(LS_INFO) << "Transport: " << content_name_ << ", component " 548 LOG(LS_INFO) << "Transport: " << content_name_ << ", component "
665 << channel->component() << " allocation complete"; 549 << channel->component() << " allocation complete";
666 550
667 iter->second.set_candidates_allocated(true); 551 CheckIfCandidatesAllocationDone();
668 552 CheckIfCompleted();
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 } 553 }
686 554
687 void Transport::OnRoleConflict(TransportChannelImpl* channel) { 555 void Transport::OnRoleConflict(TransportChannelImpl* channel) {
688 signaling_thread_->Post(this, MSG_ROLECONFLICT); 556 SignalRoleConflict();
689 } 557 }
690 558
691 void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) { 559 void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) {
692 ASSERT(worker_thread()->IsCurrent()); 560 LOG(LS_INFO) << content_name() << " TransportChannel " << channel->component()
693 MaybeCompleted_w(); 561 << " connection removed. Check if transport is complete.";
562 CheckIfCompleted();
694 563
695 // Check if the state is now Failed. 564 // Check if the state is now Failed.
696 // Failed is only available in the Controlling ICE role. 565 // Failed is only available in the Controlling ICE role.
697 if (channel->GetIceRole() != ICEROLE_CONTROLLING) { 566 if (channel->GetIceRole() != ICEROLE_CONTROLLING) {
698 return; 567 return;
699 } 568 }
700 569
701 ChannelMap::iterator iter = channels_.find(channel->component());
702 ASSERT(iter != channels_.end());
703 // Failed can only occur after candidate allocation has stopped. 570 // Failed can only occur after candidate allocation has stopped.
704 if (!iter->second.candidates_allocated()) { 571 if (channel->candidate_gathering_state() != kGatheringDone) {
705 return; 572 return;
706 } 573 }
707 574
708 if (channel->GetState() == TransportChannelState::STATE_FAILED) { 575 if (channel->GetState() == TransportChannelState::STATE_FAILED) {
709 // A Transport has failed if any of its channels have no remaining 576 // A Transport has failed if any of its channels have no remaining
710 // connections. 577 // connections.
711 signaling_thread_->Post(this, MSG_FAILED); 578 SignalFailed(this);
712 } 579 }
713 } 580 }
714 581
715 void Transport::MaybeCompleted_w() { 582 void Transport::CheckIfCompleted() {
716 ASSERT(worker_thread()->IsCurrent()); 583 if (Completed()) {
584 LOG(LS_INFO) << content_name() << " transport is complete"
585 << " because all the channels are complete.";
586 SignalCompleted(this);
587 }
588 // TODO(deadbeef): Should we do anything if we previously were completed,
589 // but now are not (if, for example, a new remote candidate is added)?
590 }
717 591
718 // When there is no channel created yet, calling this function could fire an 592 void Transport::CheckIfCandidatesAllocationDone() {
719 // IceConnectionCompleted event prematurely. 593 // If all channels belonging to this Transport got signaled, then
720 if (channels_.empty()) { 594 // forward this signal to upper layer.
721 return; 595 for (auto& iter : channels_) {
722 } 596 if (iter.second->candidate_gathering_state() != kGatheringDone) {
723
724 // A Transport's ICE process is completed if all of its channels are writable,
725 // have finished allocating candidates, and have pruned all but one of their
726 // connections.
727 for (const auto& iter : channels_) {
728 const TransportChannelImpl* channel = iter.second.get();
729 if (!(channel->writable() &&
730 channel->GetState() == TransportChannelState::STATE_COMPLETED &&
731 channel->GetIceRole() == ICEROLE_CONTROLLING &&
732 iter.second.candidates_allocated())) {
733 return; 597 return;
734 } 598 }
735 } 599 }
736 600
737 signaling_thread_->Post(this, MSG_COMPLETED); 601 LOG(LS_INFO) << "Transport " << content_name_ << " allocation complete.";
602
603 candidate_gathering_state_ = kGatheringDone;
604 SignalCandidatesAllocationDone(this);
738 } 605 }
739 606
740 void Transport::SetIceRole_w(IceRole role) { 607 void Transport::UpdateReceivingState() {
741 ASSERT(worker_thread()->IsCurrent()); 608 TransportState receiving = GetTransportState(TRANSPORT_RECEIVING_STATE);
742 rtc::CritScope cs(&crit_); 609 if (receiving_ != receiving) {
743 ice_role_ = role; 610 receiving_ = receiving;
744 for (auto& iter : channels_) { 611 SignalReceivingState(this);
745 iter.second->SetIceRole(ice_role_);
746 } 612 }
747 } 613 }
748 614
749 void Transport::SetRemoteIceMode_w(IceMode mode) { 615 void Transport::UpdateWritableState() {
750 ASSERT(worker_thread()->IsCurrent()); 616 TransportState writable = GetTransportState(TRANSPORT_WRITABLE_STATE);
751 remote_ice_mode_ = mode; 617 LOG(LS_INFO) << content_name() << " transport writable state changed? "
752 // Shouldn't channels be created after this method executed? 618 << writable_ << " => " << writable;
753 for (auto& iter : channels_) { 619 if (writable_ != writable) {
754 iter.second->SetRemoteIceMode(remote_ice_mode_); 620 was_writable_ = (writable_ == TRANSPORT_STATE_ALL);
621 writable_ = writable;
622 SignalWritableState(this);
755 } 623 }
756 } 624 }
757 625
758 bool Transport::SetLocalTransportDescription_w( 626 void Transport::UpdateReadableState() {
759 const TransportDescription& desc, 627 TransportState readable = GetTransportState(TRANSPORT_READABLE_STATE);
760 ContentAction action, 628 if (readable_ != readable) {
761 std::string* error_desc) { 629 readable_ = readable;
762 ASSERT(worker_thread()->IsCurrent()); 630 SignalReadableState(this);
763 bool ret = true;
764
765 if (!VerifyIceParams(desc)) {
766 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
767 error_desc);
768 } 631 }
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 } 632 }
802 633
803 bool Transport::SetRemoteTransportDescription_w( 634 bool Transport::ApplyLocalTransportDescription(TransportChannelImpl* ch,
804 const TransportDescription& desc,
805 ContentAction action,
806 std::string* error_desc) {
807 bool ret = true;
808
809 if (!VerifyIceParams(desc)) {
810 return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
811 error_desc);
812 }
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 }
827
828 bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch,
829 std::string* error_desc) { 635 std::string* error_desc) {
830 ASSERT(worker_thread()->IsCurrent());
831 // If existing protocol_type is HYBRID, we may have not chosen the final 636 // If existing protocol_type is HYBRID, we may have not chosen the final
832 // protocol type, so update the channel protocol type from the 637 // protocol type, so update the channel protocol type from the
833 // local description. Otherwise, skip updating the protocol type. 638 // local description. Otherwise, skip updating the protocol type.
834 // We check for HYBRID to avoid accidental changes; in the case of a 639 // 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, 640 // 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 641 // so we need to make sure we don't switch back from ICE mode to HYBRID
837 // when this happens. 642 // when this happens.
838 // There are some other ways we could have solved this, but this is the 643 // 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. 644 // simplest. The ultimate solution will be to get rid of GICE altogether.
840 IceProtocolType protocol_type; 645 IceProtocolType protocol_type;
841 if (ch->GetIceProtocolType(&protocol_type) && 646 if (ch->GetIceProtocolType(&protocol_type) &&
842 protocol_type == ICEPROTO_HYBRID) { 647 protocol_type == ICEPROTO_HYBRID) {
843 ch->SetIceProtocolType( 648 ch->SetIceProtocolType(
844 TransportProtocolFromDescription(local_description())); 649 TransportProtocolFromDescription(local_description()));
845 } 650 }
846 ch->SetIceCredentials(local_description_->ice_ufrag, 651 ch->SetIceCredentials(local_description_->ice_ufrag,
847 local_description_->ice_pwd); 652 local_description_->ice_pwd);
848 return true; 653 return true;
849 } 654 }
850 655
851 bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch, 656 bool Transport::ApplyRemoteTransportDescription(TransportChannelImpl* ch,
852 std::string* error_desc) { 657 std::string* error_desc) {
853 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag, 658 ch->SetRemoteIceCredentials(remote_description_->ice_ufrag,
854 remote_description_->ice_pwd); 659 remote_description_->ice_pwd);
855 return true; 660 return true;
856 } 661 }
857 662
858 bool Transport::ApplyNegotiatedTransportDescription_w( 663 bool Transport::ApplyNegotiatedTransportDescription(
859 TransportChannelImpl* channel, std::string* error_desc) { 664 TransportChannelImpl* channel, std::string* error_desc) {
860 ASSERT(worker_thread()->IsCurrent());
861 channel->SetIceProtocolType(protocol_); 665 channel->SetIceProtocolType(protocol_);
862 channel->SetRemoteIceMode(remote_ice_mode_); 666 channel->SetRemoteIceMode(remote_ice_mode_);
863 return true; 667 return true;
864 } 668 }
865 669
866 bool Transport::NegotiateTransportDescription_w(ContentAction local_role, 670 bool Transport::NegotiateTransportDescription(ContentAction local_role,
867 std::string* error_desc) { 671 std::string* error_desc) {
868 ASSERT(worker_thread()->IsCurrent());
869 // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into 672 // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
870 // P2PTransport. 673 // P2PTransport.
871 const TransportDescription* offer; 674 const TransportDescription* offer;
872 const TransportDescription* answer; 675 const TransportDescription* answer;
873 676
874 if (local_role == CA_OFFER) { 677 if (local_role == CA_OFFER) {
875 offer = local_description_.get(); 678 offer = local_description_.get();
876 answer = remote_description_.get(); 679 answer = remote_description_.get();
877 } else { 680 } else {
878 offer = remote_description_.get(); 681 offer = remote_description_.get();
(...skipping 20 matching lines...) Expand all
899 << " vs " 702 << " vs "
900 << IceProtoToString(answer_proto); 703 << IceProtoToString(answer_proto);
901 return BadTransportDescription(desc.str(), error_desc); 704 return BadTransportDescription(desc.str(), error_desc);
902 } 705 }
903 protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto; 706 protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto;
904 707
905 // If transport is in ICEROLE_CONTROLLED and remote end point supports only 708 // If transport is in ICEROLE_CONTROLLED and remote end point supports only
906 // ice_lite, this local end point should take CONTROLLING role. 709 // ice_lite, this local end point should take CONTROLLING role.
907 if (ice_role_ == ICEROLE_CONTROLLED && 710 if (ice_role_ == ICEROLE_CONTROLLED &&
908 remote_description_->ice_mode == ICEMODE_LITE) { 711 remote_description_->ice_mode == ICEMODE_LITE) {
909 SetIceRole_w(ICEROLE_CONTROLLING); 712 SetIceRole(ICEROLE_CONTROLLING);
910 } 713 }
911 714
912 // Update remote ice_mode to all existing channels. 715 // Update remote ice_mode to all existing channels.
913 remote_ice_mode_ = remote_description_->ice_mode; 716 remote_ice_mode_ = remote_description_->ice_mode;
914 717
915 // Now that we have negotiated everything, push it downward. 718 // Now that we have negotiated everything, push it downward.
916 // Note that we cache the result so that if we have race conditions 719 // Note that we cache the result so that if we have race conditions
917 // between future SetRemote/SetLocal invocations and new channel 720 // between future SetRemote/SetLocal invocations and new channel
918 // creation, we have the negotiation state saved until a new 721 // creation, we have the negotiation state saved until a new
919 // negotiation happens. 722 // negotiation happens.
920 for (auto& iter : channels_) { 723 for (auto& iter : channels_) {
921 if (!ApplyNegotiatedTransportDescription_w(iter.second.get(), error_desc)) 724 if (!ApplyNegotiatedTransportDescription(iter.second.get(), error_desc))
922 return false; 725 return false;
923 } 726 }
924 return true; 727 return true;
925 } 728 }
926 729
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 730 // 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. 731 // used and the GICE ice-option is set.
979 TransportProtocol TransportProtocolFromDescription( 732 TransportProtocol TransportProtocolFromDescription(
980 const TransportDescription* desc) { 733 const TransportDescription* desc) {
981 ASSERT(desc != NULL); 734 ASSERT(desc != NULL);
982 if (desc->transport_type == NS_JINGLE_ICE_UDP) { 735 if (desc->transport_type == NS_JINGLE_ICE_UDP) {
983 return (desc->HasOption(ICE_OPTION_GICE)) ? 736 return (desc->HasOption(ICE_OPTION_GICE)) ?
984 ICEPROTO_HYBRID : ICEPROTO_RFC5245; 737 ICEPROTO_HYBRID : ICEPROTO_RFC5245;
985 } 738 }
986 return ICEPROTO_GOOGLE; 739 return ICEPROTO_GOOGLE;
987 } 740 }
988 741
989 } // namespace cricket 742 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698