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

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

Powered by Google App Engine
This is Rietveld 408576698