OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/libjingle_transport_factory.h" | 5 #include "remoting/protocol/libjingle_transport_factory.h" |
6 | 6 |
7 #include "base/callback.h" | |
7 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
8 #include "base/thread_task_runner_handle.h" | 9 #include "base/thread_task_runner_handle.h" |
9 #include "base/timer/timer.h" | 10 #include "base/timer/timer.h" |
10 #include "jingle/glue/channel_socket_adapter.h" | 11 #include "jingle/glue/channel_socket_adapter.h" |
11 #include "jingle/glue/pseudotcp_adapter.h" | 12 #include "jingle/glue/pseudotcp_adapter.h" |
12 #include "jingle/glue/thread_wrapper.h" | 13 #include "jingle/glue/thread_wrapper.h" |
13 #include "jingle/glue/utils.h" | 14 #include "jingle/glue/utils.h" |
14 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
15 #include "remoting/base/constants.h" | 16 #include "remoting/base/constants.h" |
17 #include "remoting/jingle_glue/jingle_info_request.h" | |
16 #include "remoting/jingle_glue/network_settings.h" | 18 #include "remoting/jingle_glue/network_settings.h" |
17 #include "remoting/protocol/channel_authenticator.h" | 19 #include "remoting/protocol/channel_authenticator.h" |
18 #include "remoting/protocol/transport_config.h" | |
19 #include "third_party/libjingle/source/talk/base/network.h" | 20 #include "third_party/libjingle/source/talk/base/network.h" |
20 #include "third_party/libjingle/source/talk/p2p/base/constants.h" | 21 #include "third_party/libjingle/source/talk/p2p/base/constants.h" |
21 #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h" | 22 #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h" |
22 #include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h" | 23 #include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h" |
23 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h" | 24 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h" |
24 | 25 |
25 namespace remoting { | 26 namespace remoting { |
26 namespace protocol { | 27 namespace protocol { |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 // Value is chosen to balance the extra latency against the reduced | 31 // Value is chosen to balance the extra latency against the reduced |
31 // load due to ACK traffic. | 32 // load due to ACK traffic. |
32 const int kTcpAckDelayMilliseconds = 10; | 33 const int kTcpAckDelayMilliseconds = 10; |
33 | 34 |
34 // Values for the TCP send and receive buffer size. This should be tuned to | 35 // Values for the TCP send and receive buffer size. This should be tuned to |
35 // accommodate high latency network but not backlog the decoding pipeline. | 36 // accommodate high latency network but not backlog the decoding pipeline. |
36 const int kTcpReceiveBufferSize = 256 * 1024; | 37 const int kTcpReceiveBufferSize = 256 * 1024; |
37 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; | 38 const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024; |
38 | 39 |
39 // Try connecting ICE twice with timeout of 15 seconds for each attempt. | 40 // Try connecting ICE twice with timeout of 15 seconds for each attempt. |
40 const int kMaxReconnectAttempts = 2; | 41 const int kMaxReconnectAttempts = 2; |
41 const int kReconnectDelaySeconds = 15; | 42 const int kReconnectDelaySeconds = 15; |
42 | 43 |
43 class LibjingleStreamTransport : public StreamTransport, | 44 // Get fresh STUN/Relay configuration every hour. |
44 public sigslot::has_slots<> { | 45 const int kJingleInfoUpdatePeriodSeconds = 3600; |
46 | |
47 class LibjingleStreamTransport | |
48 : public StreamTransport, | |
49 public base::SupportsWeakPtr<LibjingleStreamTransport>, | |
50 public sigslot::has_slots<> { | |
45 public: | 51 public: |
46 LibjingleStreamTransport(cricket::PortAllocator* port_allocator, | 52 LibjingleStreamTransport(cricket::PortAllocator* port_allocator, |
47 bool incoming_only); | 53 const NetworkSettings& network_settings); |
48 virtual ~LibjingleStreamTransport(); | 54 virtual ~LibjingleStreamTransport(); |
49 | 55 |
56 // Called by JingleTransportFactory when it has fresh Jingle info. | |
57 void OnCanStart(); | |
58 | |
50 // StreamTransport interface. | 59 // StreamTransport interface. |
51 virtual void Initialize( | 60 virtual void Initialize( |
52 const std::string& name, | 61 const std::string& name, |
53 Transport::EventHandler* event_handler, | 62 Transport::EventHandler* event_handler, |
54 scoped_ptr<ChannelAuthenticator> authenticator) OVERRIDE; | 63 scoped_ptr<ChannelAuthenticator> authenticator) OVERRIDE; |
55 virtual void Connect( | 64 virtual void Connect( |
56 const StreamTransport::ConnectedCallback& callback) OVERRIDE; | 65 const StreamTransport::ConnectedCallback& callback) OVERRIDE; |
57 virtual void AddRemoteCandidate(const cricket::Candidate& candidate) OVERRIDE; | 66 virtual void AddRemoteCandidate(const cricket::Candidate& candidate) OVERRIDE; |
58 virtual const std::string& name() const OVERRIDE; | 67 virtual const std::string& name() const OVERRIDE; |
59 virtual bool is_connected() const OVERRIDE; | 68 virtual bool is_connected() const OVERRIDE; |
60 | 69 |
61 private: | 70 private: |
71 void DoStart(); | |
72 | |
62 // Signal handlers for cricket::TransportChannel. | 73 // Signal handlers for cricket::TransportChannel. |
63 void OnRequestSignaling(cricket::TransportChannelImpl* channel); | 74 void OnRequestSignaling(cricket::TransportChannelImpl* channel); |
64 void OnCandidateReady(cricket::TransportChannelImpl* channel, | 75 void OnCandidateReady(cricket::TransportChannelImpl* channel, |
65 const cricket::Candidate& candidate); | 76 const cricket::Candidate& candidate); |
66 void OnRouteChange(cricket::TransportChannel* channel, | 77 void OnRouteChange(cricket::TransportChannel* channel, |
67 const cricket::Candidate& candidate); | 78 const cricket::Candidate& candidate); |
68 void OnWritableState(cricket::TransportChannel* channel); | 79 void OnWritableState(cricket::TransportChannel* channel); |
69 | 80 |
70 // Callback for PseudoTcpAdapter::Connect(). | 81 // Callback for PseudoTcpAdapter::Connect(). |
71 void OnTcpConnected(int result); | 82 void OnTcpConnected(int result); |
72 | 83 |
73 // Callback for Authenticator::SecureAndAuthenticate(); | 84 // Callback for Authenticator::SecureAndAuthenticate(); |
74 void OnAuthenticationDone(net::Error error, | 85 void OnAuthenticationDone(net::Error error, |
75 scoped_ptr<net::StreamSocket> socket); | 86 scoped_ptr<net::StreamSocket> socket); |
76 | 87 |
77 // Callback for jingle_glue::TransportChannelSocketAdapter to notify when the | 88 // Callback for jingle_glue::TransportChannelSocketAdapter to notify when the |
78 // socket is destroyed. | 89 // socket is destroyed. |
79 void OnChannelDestroyed(); | 90 void OnChannelDestroyed(); |
80 | 91 |
81 // Tries to connect by restarting ICE. Called by |reconnect_timer_|. | 92 // Tries to connect by restarting ICE. Called by |reconnect_timer_|. |
82 void TryReconnect(); | 93 void TryReconnect(); |
83 | 94 |
84 // Helper methods to call |callback_|. | 95 // Helper methods to call |callback_|. |
85 void NotifyConnected(scoped_ptr<net::StreamSocket> socket); | 96 void NotifyConnected(scoped_ptr<net::StreamSocket> socket); |
86 void NotifyConnectFailed(); | 97 void NotifyConnectFailed(); |
87 | 98 |
88 cricket::PortAllocator* port_allocator_; | 99 cricket::PortAllocator* port_allocator_; |
89 bool incoming_only_; | 100 NetworkSettings network_settings_; |
90 | 101 |
91 std::string name_; | 102 std::string name_; |
92 EventHandler* event_handler_; | 103 EventHandler* event_handler_; |
93 StreamTransport::ConnectedCallback callback_; | 104 StreamTransport::ConnectedCallback callback_; |
94 scoped_ptr<ChannelAuthenticator> authenticator_; | 105 scoped_ptr<ChannelAuthenticator> authenticator_; |
95 std::string ice_username_fragment_; | 106 std::string ice_username_fragment_; |
96 std::string ice_password_; | 107 std::string ice_password_; |
97 | 108 |
109 bool can_start_; | |
110 | |
111 std::list<cricket::Candidate> pending_candidates_; | |
98 scoped_ptr<cricket::P2PTransportChannel> channel_; | 112 scoped_ptr<cricket::P2PTransportChannel> channel_; |
99 bool channel_was_writable_; | 113 bool channel_was_writable_; |
100 int connect_attempts_left_; | 114 int connect_attempts_left_; |
101 base::RepeatingTimer<LibjingleStreamTransport> reconnect_timer_; | 115 base::RepeatingTimer<LibjingleStreamTransport> reconnect_timer_; |
102 | 116 |
103 // We own |socket_| until it is connected. | 117 // We own |socket_| until it is connected. |
104 scoped_ptr<jingle_glue::PseudoTcpAdapter> socket_; | 118 scoped_ptr<jingle_glue::PseudoTcpAdapter> socket_; |
105 | 119 |
106 DISALLOW_COPY_AND_ASSIGN(LibjingleStreamTransport); | 120 DISALLOW_COPY_AND_ASSIGN(LibjingleStreamTransport); |
107 }; | 121 }; |
108 | 122 |
109 LibjingleStreamTransport::LibjingleStreamTransport( | 123 LibjingleStreamTransport::LibjingleStreamTransport( |
110 cricket::PortAllocator* port_allocator, | 124 cricket::PortAllocator* port_allocator, |
111 bool incoming_only) | 125 const NetworkSettings& network_settings) |
112 : port_allocator_(port_allocator), | 126 : port_allocator_(port_allocator), |
113 incoming_only_(incoming_only), | 127 network_settings_(network_settings), |
114 event_handler_(NULL), | 128 event_handler_(NULL), |
115 ice_username_fragment_( | 129 ice_username_fragment_( |
116 talk_base::CreateRandomString(cricket::ICE_UFRAG_LENGTH)), | 130 talk_base::CreateRandomString(cricket::ICE_UFRAG_LENGTH)), |
117 ice_password_(talk_base::CreateRandomString(cricket::ICE_PWD_LENGTH)), | 131 ice_password_(talk_base::CreateRandomString(cricket::ICE_PWD_LENGTH)), |
132 can_start_(false), | |
118 channel_was_writable_(false), | 133 channel_was_writable_(false), |
119 connect_attempts_left_(kMaxReconnectAttempts) { | 134 connect_attempts_left_(kMaxReconnectAttempts) { |
120 } | 135 } |
121 | 136 |
122 LibjingleStreamTransport::~LibjingleStreamTransport() { | 137 LibjingleStreamTransport::~LibjingleStreamTransport() { |
123 DCHECK(event_handler_); | 138 DCHECK(event_handler_); |
124 event_handler_->OnTransportDeleted(this); | 139 event_handler_->OnTransportDeleted(this); |
125 // Channel should be already destroyed if we were connected. | 140 // Channel should be already destroyed if we were connected. |
126 DCHECK(!is_connected() || socket_.get() == NULL); | 141 DCHECK(!is_connected() || socket_.get() == NULL); |
127 | 142 |
128 if (channel_.get()) { | 143 if (channel_.get()) { |
129 base::ThreadTaskRunnerHandle::Get()->DeleteSoon( | 144 base::ThreadTaskRunnerHandle::Get()->DeleteSoon( |
130 FROM_HERE, channel_.release()); | 145 FROM_HERE, channel_.release()); |
131 } | 146 } |
132 } | 147 } |
133 | 148 |
149 void LibjingleStreamTransport::OnCanStart() { | |
150 DCHECK(CalledOnValidThread()); | |
151 | |
152 DCHECK(!can_start_); | |
153 can_start_ = true; | |
154 | |
155 // If Connect() has been called then start connection. | |
156 if (!callback_.is_null()) | |
157 DoStart(); | |
158 | |
159 while (!pending_candidates_.empty()) { | |
160 channel_->OnCandidate(pending_candidates_.front()); | |
161 pending_candidates_.pop_front(); | |
162 } | |
163 } | |
164 | |
134 void LibjingleStreamTransport::Initialize( | 165 void LibjingleStreamTransport::Initialize( |
135 const std::string& name, | 166 const std::string& name, |
136 Transport::EventHandler* event_handler, | 167 Transport::EventHandler* event_handler, |
137 scoped_ptr<ChannelAuthenticator> authenticator) { | 168 scoped_ptr<ChannelAuthenticator> authenticator) { |
138 DCHECK(CalledOnValidThread()); | 169 DCHECK(CalledOnValidThread()); |
139 | 170 |
140 DCHECK(!name.empty()); | 171 DCHECK(!name.empty()); |
141 DCHECK(event_handler); | 172 DCHECK(event_handler); |
142 | 173 |
143 // Can be initialized only once. | 174 // Can be initialized only once. |
144 DCHECK(name_.empty()); | 175 DCHECK(name_.empty()); |
145 | 176 |
146 name_ = name; | 177 name_ = name; |
147 event_handler_ = event_handler; | 178 event_handler_ = event_handler; |
148 authenticator_ = authenticator.Pass(); | 179 authenticator_ = authenticator.Pass(); |
149 } | 180 } |
150 | 181 |
151 void LibjingleStreamTransport::Connect( | 182 void LibjingleStreamTransport::Connect( |
152 const StreamTransport::ConnectedCallback& callback) { | 183 const StreamTransport::ConnectedCallback& callback) { |
153 DCHECK(CalledOnValidThread()); | 184 DCHECK(CalledOnValidThread()); |
154 | |
155 callback_ = callback; | 185 callback_ = callback; |
156 | 186 |
187 if (can_start_) | |
188 DoStart(); | |
189 } | |
190 | |
191 void LibjingleStreamTransport::DoStart() { | |
157 DCHECK(!channel_.get()); | 192 DCHECK(!channel_.get()); |
158 | 193 |
159 // Create P2PTransportChannel, attach signal handlers and connect it. | 194 // Create P2PTransportChannel, attach signal handlers and connect it. |
160 // TODO(sergeyu): Specify correct component ID for the channel. | 195 // TODO(sergeyu): Specify correct component ID for the channel. |
161 channel_.reset(new cricket::P2PTransportChannel( | 196 channel_.reset(new cricket::P2PTransportChannel( |
162 std::string(), 0, NULL, port_allocator_)); | 197 std::string(), 0, NULL, port_allocator_)); |
163 channel_->SetIceCredentials(ice_username_fragment_, ice_password_); | 198 channel_->SetIceCredentials(ice_username_fragment_, ice_password_); |
164 channel_->SignalRequestSignaling.connect( | 199 channel_->SignalRequestSignaling.connect( |
165 this, &LibjingleStreamTransport::OnRequestSignaling); | 200 this, &LibjingleStreamTransport::OnRequestSignaling); |
166 channel_->SignalCandidateReady.connect( | 201 channel_->SignalCandidateReady.connect( |
167 this, &LibjingleStreamTransport::OnCandidateReady); | 202 this, &LibjingleStreamTransport::OnCandidateReady); |
168 channel_->SignalRouteChange.connect( | 203 channel_->SignalRouteChange.connect( |
169 this, &LibjingleStreamTransport::OnRouteChange); | 204 this, &LibjingleStreamTransport::OnRouteChange); |
170 channel_->SignalWritableState.connect( | 205 channel_->SignalWritableState.connect( |
171 this, &LibjingleStreamTransport::OnWritableState); | 206 this, &LibjingleStreamTransport::OnWritableState); |
172 channel_->set_incoming_only(incoming_only_); | 207 if (network_settings_.nat_traversal_mode == |
208 NetworkSettings::NAT_TRAVERSAL_DISABLED) { | |
209 channel_->set_incoming_only(true); | |
210 } | |
173 | 211 |
174 channel_->Connect(); | 212 channel_->Connect(); |
175 | 213 |
176 --connect_attempts_left_; | 214 --connect_attempts_left_; |
177 | 215 |
178 // Start reconnection timer. | 216 // Start reconnection timer. |
179 reconnect_timer_.Start( | 217 reconnect_timer_.Start( |
180 FROM_HERE, base::TimeDelta::FromSeconds(kReconnectDelaySeconds), | 218 FROM_HERE, base::TimeDelta::FromSeconds(kReconnectDelaySeconds), |
181 this, &LibjingleStreamTransport::TryReconnect); | 219 this, &LibjingleStreamTransport::TryReconnect); |
182 | 220 |
(...skipping 21 matching lines...) Expand all Loading... | |
204 int result = socket_->Connect( | 242 int result = socket_->Connect( |
205 base::Bind(&LibjingleStreamTransport::OnTcpConnected, | 243 base::Bind(&LibjingleStreamTransport::OnTcpConnected, |
206 base::Unretained(this))); | 244 base::Unretained(this))); |
207 if (result != net::ERR_IO_PENDING) | 245 if (result != net::ERR_IO_PENDING) |
208 OnTcpConnected(result); | 246 OnTcpConnected(result); |
209 } | 247 } |
210 | 248 |
211 void LibjingleStreamTransport::AddRemoteCandidate( | 249 void LibjingleStreamTransport::AddRemoteCandidate( |
212 const cricket::Candidate& candidate) { | 250 const cricket::Candidate& candidate) { |
213 DCHECK(CalledOnValidThread()); | 251 DCHECK(CalledOnValidThread()); |
214 channel_->OnCandidate(candidate); | 252 if (channel_) { |
253 channel_->OnCandidate(candidate); | |
254 } else { | |
255 pending_candidates_.push_back(candidate); | |
256 } | |
215 } | 257 } |
216 | 258 |
217 const std::string& LibjingleStreamTransport::name() const { | 259 const std::string& LibjingleStreamTransport::name() const { |
218 DCHECK(CalledOnValidThread()); | 260 DCHECK(CalledOnValidThread()); |
219 return name_; | 261 return name_; |
220 } | 262 } |
221 | 263 |
222 bool LibjingleStreamTransport::is_connected() const { | 264 bool LibjingleStreamTransport::is_connected() const { |
223 DCHECK(CalledOnValidThread()); | 265 DCHECK(CalledOnValidThread()); |
224 return callback_.is_null(); | 266 return callback_.is_null(); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 } | 397 } |
356 | 398 |
357 authenticator_.reset(); | 399 authenticator_.reset(); |
358 | 400 |
359 NotifyConnected(scoped_ptr<net::StreamSocket>()); | 401 NotifyConnected(scoped_ptr<net::StreamSocket>()); |
360 } | 402 } |
361 | 403 |
362 } // namespace | 404 } // namespace |
363 | 405 |
364 LibjingleTransportFactory::LibjingleTransportFactory( | 406 LibjingleTransportFactory::LibjingleTransportFactory( |
407 SignalStrategy* signal_strategy, | |
365 scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator, | 408 scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator, |
366 bool incoming_only) | 409 const NetworkSettings& network_settings) |
367 : port_allocator_(port_allocator.Pass()), | 410 : signal_strategy_(signal_strategy), |
368 incoming_only_(incoming_only) { | 411 port_allocator_(port_allocator.Pass()), |
412 network_settings_(network_settings) { | |
369 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); | 413 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
370 } | 414 } |
371 | 415 |
372 LibjingleTransportFactory::~LibjingleTransportFactory() { | 416 LibjingleTransportFactory::~LibjingleTransportFactory() { |
373 // This method may be called in response to a libjingle signal, so | 417 // This method may be called in response to a libjingle signal, so |
374 // libjingle objects must be deleted asynchronously. | 418 // libjingle objects must be deleted asynchronously. |
375 scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 419 scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
376 base::ThreadTaskRunnerHandle::Get(); | 420 base::ThreadTaskRunnerHandle::Get(); |
377 task_runner->DeleteSoon(FROM_HERE, port_allocator_.release()); | 421 task_runner->DeleteSoon(FROM_HERE, port_allocator_.release()); |
378 } | 422 } |
379 | 423 |
380 void LibjingleTransportFactory::SetTransportConfig( | 424 void LibjingleTransportFactory::PrepareTokens() { |
381 const TransportConfig& config) { | 425 EnsureFreshJingleInfo(); |
382 std::vector<talk_base::SocketAddress> stun_hosts; | |
383 talk_base::SocketAddress stun_address; | |
384 if (stun_address.FromString(config.stun_server)) { | |
385 stun_hosts.push_back(stun_address); | |
386 port_allocator_->SetStunHosts(stun_hosts); | |
387 } else { | |
388 LOG(ERROR) << "Failed to parse stun server address: " | |
389 << config.stun_server; | |
390 } | |
391 | |
392 std::vector<std::string> relay_hosts; | |
393 relay_hosts.push_back(config.relay_server); | |
394 port_allocator_->SetRelayHosts(relay_hosts); | |
395 port_allocator_->SetRelayToken(config.relay_token); | |
396 } | 426 } |
397 | 427 |
398 scoped_ptr<StreamTransport> LibjingleTransportFactory::CreateStreamTransport() { | 428 scoped_ptr<StreamTransport> LibjingleTransportFactory::CreateStreamTransport() { |
399 return scoped_ptr<StreamTransport>( | 429 scoped_ptr<LibjingleStreamTransport> result( |
400 new LibjingleStreamTransport(port_allocator_.get(), incoming_only_)); | 430 new LibjingleStreamTransport(port_allocator_.get(), network_settings_)); |
431 | |
432 EnsureFreshJingleInfo(); | |
433 | |
434 // If there is a pending |jingle_info_request_| delay starting the new | |
435 // transport until the request is finished. | |
436 if (jingle_info_request_) { | |
437 on_jingle_info_callbacks_.push_back( | |
438 base::Bind(&LibjingleStreamTransport::OnCanStart, | |
439 result->AsWeakPtr())); | |
440 } else { | |
441 result->OnCanStart(); | |
442 } | |
443 | |
444 return result.PassAs<StreamTransport>(); | |
401 } | 445 } |
402 | 446 |
403 scoped_ptr<DatagramTransport> | 447 scoped_ptr<DatagramTransport> |
404 LibjingleTransportFactory::CreateDatagramTransport() { | 448 LibjingleTransportFactory::CreateDatagramTransport() { |
405 NOTIMPLEMENTED(); | 449 NOTIMPLEMENTED(); |
406 return scoped_ptr<DatagramTransport>(); | 450 return scoped_ptr<DatagramTransport>(); |
407 } | 451 } |
408 | 452 |
453 void LibjingleTransportFactory::EnsureFreshJingleInfo() { | |
454 if (network_settings_.nat_traversal_mode != | |
455 NetworkSettings::NAT_TRAVERSAL_ENABLED || | |
456 jingle_info_request_) { | |
457 return; | |
458 } | |
459 | |
460 if (base::TimeTicks::Now() - last_jingle_info_update_time_ > | |
461 base::TimeDelta::FromSeconds(kJingleInfoUpdatePeriodSeconds)) { | |
462 jingle_info_request_.reset(new JingleInfoRequest(signal_strategy_)); | |
463 jingle_info_request_->Send(base::Bind( | |
rmsousa
2013/12/13 22:10:40
is this safe if the signal_strategy_ is currently
Sergey Ulanov
2013/12/13 23:54:34
JingleInfoRequest didn't handle this case properly
| |
464 &LibjingleTransportFactory::OnJingleInfo, base::Unretained(this))); | |
465 } | |
466 } | |
467 | |
468 void LibjingleTransportFactory::OnJingleInfo( | |
469 const std::string& relay_token, | |
470 const std::vector<std::string>& relay_hosts, | |
471 const std::vector<talk_base::SocketAddress>& stun_hosts) { | |
472 if (!relay_token.empty() && !relay_hosts.empty()) { | |
473 port_allocator_->SetRelayHosts(relay_hosts); | |
474 port_allocator_->SetRelayToken(relay_token); | |
475 } | |
476 if (!stun_hosts.empty()) { | |
477 port_allocator_->SetStunHosts(stun_hosts); | |
478 } | |
479 | |
480 jingle_info_request_.reset(); | |
481 if ((!relay_token.empty() && !relay_hosts.empty()) || !stun_hosts.empty()) | |
482 last_jingle_info_update_time_ = base::TimeTicks::Now(); | |
483 | |
484 while (!on_jingle_info_callbacks_.empty()) { | |
485 on_jingle_info_callbacks_.begin()->Run(); | |
486 on_jingle_info_callbacks_.pop_front(); | |
487 } | |
488 } | |
489 | |
409 } // namespace protocol | 490 } // namespace protocol |
410 } // namespace remoting | 491 } // namespace remoting |
OLD | NEW |