OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/base64.h" | 5 #include "base/base64.h" |
6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "base/single_thread_task_runner.h" | 9 #include "base/single_thread_task_runner.h" |
10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
11 #include "base/thread_task_runner_handle.h" | 11 #include "base/thread_task_runner_handle.h" |
| 12 #include "jingle/glue/thread_wrapper.h" |
12 #include "net/base/test_data_directory.h" | 13 #include "net/base/test_data_directory.h" |
13 #include "net/url_request/url_request_context_getter.h" | 14 #include "net/url_request/url_request_context_getter.h" |
14 #include "remoting/base/rsa_key_pair.h" | 15 #include "remoting/base/rsa_key_pair.h" |
15 #include "remoting/client/audio_player.h" | 16 #include "remoting/client/audio_player.h" |
16 #include "remoting/client/chromoting_client.h" | 17 #include "remoting/client/chromoting_client.h" |
17 #include "remoting/client/client_context.h" | 18 #include "remoting/client/client_context.h" |
18 #include "remoting/client/client_user_interface.h" | 19 #include "remoting/client/client_user_interface.h" |
19 #include "remoting/client/video_renderer.h" | 20 #include "remoting/client/video_renderer.h" |
20 #include "remoting/host/chromoting_host.h" | 21 #include "remoting/host/chromoting_host.h" |
21 #include "remoting/host/chromoting_host_context.h" | 22 #include "remoting/host/chromoting_host_context.h" |
(...skipping 15 matching lines...) Expand all Loading... |
37 const char kHostJid[] = "host_jid@example.com/host"; | 38 const char kHostJid[] = "host_jid@example.com/host"; |
38 const char kHostOwner[] = "jane.doe@example.com"; | 39 const char kHostOwner[] = "jane.doe@example.com"; |
39 const char kClientJid[] = "jane.doe@example.com/client"; | 40 const char kClientJid[] = "jane.doe@example.com/client"; |
40 | 41 |
41 class ProtocolPerfTest : public testing::Test, | 42 class ProtocolPerfTest : public testing::Test, |
42 public ClientUserInterface, | 43 public ClientUserInterface, |
43 public VideoRenderer, | 44 public VideoRenderer, |
44 public HostStatusObserver { | 45 public HostStatusObserver { |
45 public: | 46 public: |
46 ProtocolPerfTest() | 47 ProtocolPerfTest() |
47 : capture_thread_("capture"), | 48 : host_thread_("host"), |
| 49 capture_thread_("capture"), |
48 encode_thread_("encode") { | 50 encode_thread_("encode") { |
49 VideoScheduler::EnableTimestampsForTests(); | 51 VideoScheduler::EnableTimestampsForTests(); |
| 52 host_thread_.StartWithOptions( |
| 53 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
50 capture_thread_.Start(); | 54 capture_thread_.Start(); |
51 encode_thread_.Start(); | 55 encode_thread_.Start(); |
52 } | 56 } |
53 ~ProtocolPerfTest() { | 57 ~ProtocolPerfTest() { |
| 58 host_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, host_.release()); |
| 59 host_thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, |
| 60 host_signaling_.release()); |
54 message_loop_.RunUntilIdle(); | 61 message_loop_.RunUntilIdle(); |
55 } | 62 } |
56 | 63 |
57 // ClientUserInterface interface. | 64 // ClientUserInterface interface. |
58 virtual void OnConnectionState(protocol::ConnectionToHost::State state, | 65 virtual void OnConnectionState(protocol::ConnectionToHost::State state, |
59 protocol::ErrorCode error) OVERRIDE { | 66 protocol::ErrorCode error) OVERRIDE { |
60 if (state == protocol::ConnectionToHost::CONNECTED) { | 67 if (state == protocol::ConnectionToHost::CONNECTED) { |
61 client_connected_ = true; | 68 client_connected_ = true; |
62 if (host_connected_) | 69 if (host_connected_) |
63 connecting_loop_->Quit(); | 70 connecting_loop_->Quit(); |
(...skipping 29 matching lines...) Expand all Loading... |
93 last_video_packet_ = video_packet.Pass(); | 100 last_video_packet_ = video_packet.Pass(); |
94 | 101 |
95 if (!on_frame_task_.is_null()) | 102 if (!on_frame_task_.is_null()) |
96 on_frame_task_.Run(); | 103 on_frame_task_.Run(); |
97 | 104 |
98 done.Run(); | 105 done.Run(); |
99 } | 106 } |
100 | 107 |
101 // HostStatusObserver interface. | 108 // HostStatusObserver interface. |
102 virtual void OnClientConnected(const std::string& jid) { | 109 virtual void OnClientConnected(const std::string& jid) { |
103 host_connected_ = true; | 110 message_loop_.PostTask( |
104 if (client_connected_) | 111 FROM_HERE, |
105 connecting_loop_->Quit(); | 112 base::Bind(&ProtocolPerfTest::OnHostConnectedMainThread, |
| 113 base::Unretained(this))); |
106 } | 114 } |
107 | 115 |
108 protected: | 116 protected: |
109 void WaitConnected() { | 117 void WaitConnected() { |
110 client_connected_ = false; | 118 client_connected_ = false; |
111 host_connected_ = false; | 119 host_connected_ = false; |
112 | 120 |
113 connecting_loop_.reset(new base::RunLoop()); | 121 connecting_loop_.reset(new base::RunLoop()); |
114 connecting_loop_->Run(); | 122 connecting_loop_->Run(); |
115 | 123 |
116 ASSERT_TRUE(client_connected_ && host_connected_); | 124 ASSERT_TRUE(client_connected_ && host_connected_); |
117 } | 125 } |
118 | 126 |
| 127 void OnHostConnectedMainThread() { |
| 128 host_connected_ = true; |
| 129 if (client_connected_) |
| 130 connecting_loop_->Quit(); |
| 131 } |
| 132 |
119 void ReceiveFrame(base::TimeDelta* latency) { | 133 void ReceiveFrame(base::TimeDelta* latency) { |
120 waiting_frames_loop_.reset(new base::RunLoop()); | 134 waiting_frames_loop_.reset(new base::RunLoop()); |
121 on_frame_task_ = waiting_frames_loop_->QuitClosure(); | 135 on_frame_task_ = waiting_frames_loop_->QuitClosure(); |
122 waiting_frames_loop_->Run(); | 136 waiting_frames_loop_->Run(); |
123 | 137 |
124 if (latency) { | 138 if (latency) { |
125 base::TimeTicks timestamp = | 139 base::TimeTicks timestamp = |
126 base::TimeTicks::FromInternalValue(last_video_packet_->timestamp()); | 140 base::TimeTicks::FromInternalValue(last_video_packet_->timestamp()); |
127 *latency = base::TimeTicks::Now() - timestamp; | 141 *latency = base::TimeTicks::Now() - timestamp; |
128 } | 142 } |
129 } | 143 } |
130 | 144 |
131 void ReceiveFrames(int frames, base::TimeDelta* max_latency) { | 145 void ReceiveFrames(int frames, base::TimeDelta* max_latency) { |
132 if (max_latency) | 146 if (max_latency) |
133 *max_latency = base::TimeDelta(); | 147 *max_latency = base::TimeDelta(); |
134 | 148 |
135 for (int i = 0; i < frames; ++i) { | 149 for (int i = 0; i < frames; ++i) { |
136 base::TimeDelta latency; | 150 base::TimeDelta latency; |
137 | 151 |
138 ReceiveFrame(&latency); | 152 ReceiveFrame(&latency); |
139 | 153 |
140 if (max_latency && latency > *max_latency) { | 154 if (max_latency && latency > *max_latency) { |
141 *max_latency = latency; | 155 *max_latency = latency; |
142 } | 156 } |
143 } | 157 } |
144 } | 158 } |
145 | 159 |
| 160 // Creates test host and client and starts connection between them. Caller |
| 161 // should call WaitConnected() to wait until connection is established. The |
| 162 // host is started on |host_thread_| while the client works on the main |
| 163 // thread. |
146 void StartHostAndClient(protocol::ChannelConfig::Codec video_codec) { | 164 void StartHostAndClient(protocol::ChannelConfig::Codec video_codec) { |
| 165 client_signaling_.reset(new FakeSignalStrategy(kClientJid)); |
| 166 |
| 167 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
| 168 |
| 169 protocol_config_ = protocol::CandidateSessionConfig::CreateDefault(); |
| 170 protocol_config_->DisableAudioChannel(); |
| 171 protocol_config_->mutable_video_configs()->clear(); |
| 172 protocol_config_->mutable_video_configs()->push_back( |
| 173 protocol::ChannelConfig( |
| 174 protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec)); |
| 175 |
| 176 host_thread_.message_loop_proxy()->PostTask( |
| 177 FROM_HERE, |
| 178 base::Bind(&ProtocolPerfTest::StartHost, base::Unretained(this))); |
| 179 } |
| 180 |
| 181 void StartHost() { |
| 182 DCHECK(host_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| 183 |
| 184 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); |
| 185 |
147 host_signaling_.reset(new FakeSignalStrategy(kHostJid)); | 186 host_signaling_.reset(new FakeSignalStrategy(kHostJid)); |
148 client_signaling_.reset(new FakeSignalStrategy(kClientJid)); | 187 host_signaling_->ConnectTo(client_signaling_.get()); |
149 FakeSignalStrategy::Connect(host_signaling_.get(), client_signaling_.get()); | |
150 | 188 |
151 protocol::NetworkSettings network_settings( | 189 protocol::NetworkSettings network_settings( |
152 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); | 190 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); |
153 | 191 |
154 scoped_ptr<protocol::CandidateSessionConfig> protocol_config = | |
155 protocol::CandidateSessionConfig::CreateDefault(); | |
156 protocol_config->DisableAudioChannel(); | |
157 protocol_config->mutable_video_configs()->clear(); | |
158 protocol_config->mutable_video_configs()->push_back(protocol::ChannelConfig( | |
159 protocol::ChannelConfig::TRANSPORT_STREAM, 2, video_codec)); | |
160 | |
161 // TODO(sergeyu): Replace with a fake port allocator. | 192 // TODO(sergeyu): Replace with a fake port allocator. |
162 scoped_ptr<cricket::HttpPortAllocatorBase> host_port_allocator = | 193 scoped_ptr<cricket::HttpPortAllocatorBase> host_port_allocator = |
163 protocol::ChromiumPortAllocator::Create(NULL, network_settings) | 194 protocol::ChromiumPortAllocator::Create(NULL, network_settings) |
164 .PassAs<cricket::HttpPortAllocatorBase>(); | 195 .PassAs<cricket::HttpPortAllocatorBase>(); |
165 | 196 |
166 scoped_ptr<protocol::TransportFactory> host_transport_factory( | 197 scoped_ptr<protocol::TransportFactory> host_transport_factory( |
167 new protocol::LibjingleTransportFactory( | 198 new protocol::LibjingleTransportFactory( |
168 host_signaling_.get(), | 199 host_signaling_.get(), |
169 host_port_allocator.Pass(), | 200 host_port_allocator.Pass(), |
170 network_settings)); | 201 network_settings)); |
171 | 202 |
172 scoped_ptr<protocol::SessionManager> session_manager( | 203 scoped_ptr<protocol::SessionManager> session_manager( |
173 new protocol::JingleSessionManager(host_transport_factory.Pass())); | 204 new protocol::JingleSessionManager(host_transport_factory.Pass())); |
174 | 205 |
175 // Encoder runs on a separate thread, main thread is used for everything | 206 // Encoder runs on a separate thread, main thread is used for everything |
176 // else. | 207 // else. |
177 host_.reset(new ChromotingHost(host_signaling_.get(), | 208 host_.reset(new ChromotingHost(host_signaling_.get(), |
178 &desktop_environment_factory_, | 209 &desktop_environment_factory_, |
179 session_manager.Pass(), | 210 session_manager.Pass(), |
180 message_loop_.message_loop_proxy(), | 211 host_thread_.message_loop_proxy(), |
181 message_loop_.message_loop_proxy(), | 212 host_thread_.message_loop_proxy(), |
182 capture_thread_.message_loop_proxy(), | 213 capture_thread_.message_loop_proxy(), |
183 encode_thread_.message_loop_proxy(), | 214 encode_thread_.message_loop_proxy(), |
184 message_loop_.message_loop_proxy(), | 215 host_thread_.message_loop_proxy(), |
185 message_loop_.message_loop_proxy())); | 216 host_thread_.message_loop_proxy())); |
186 | 217 |
187 base::FilePath certs_dir(net::GetTestCertsDirectory()); | 218 base::FilePath certs_dir(net::GetTestCertsDirectory()); |
188 | 219 |
189 std::string host_cert; | 220 std::string host_cert; |
190 ASSERT_TRUE(base::ReadFileToString( | 221 ASSERT_TRUE(base::ReadFileToString( |
191 certs_dir.AppendASCII("unittest.selfsigned.der"), &host_cert)); | 222 certs_dir.AppendASCII("unittest.selfsigned.der"), &host_cert)); |
192 | 223 |
193 base::FilePath key_path = certs_dir.AppendASCII("unittest.key.bin"); | 224 base::FilePath key_path = certs_dir.AppendASCII("unittest.key.bin"); |
194 std::string key_string; | 225 std::string key_string; |
195 ASSERT_TRUE(base::ReadFileToString(key_path, &key_string)); | 226 ASSERT_TRUE(base::ReadFileToString(key_path, &key_string)); |
196 std::string key_base64; | 227 std::string key_base64; |
197 base::Base64Encode(key_string, &key_base64); | 228 base::Base64Encode(key_string, &key_base64); |
198 scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::FromString(key_base64); | 229 scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::FromString(key_base64); |
199 ASSERT_TRUE(key_pair.get()); | 230 ASSERT_TRUE(key_pair.get()); |
200 | 231 |
201 | 232 |
202 protocol::SharedSecretHash host_secret; | 233 protocol::SharedSecretHash host_secret; |
203 host_secret.hash_function = protocol::AuthenticationMethod::NONE; | 234 host_secret.hash_function = protocol::AuthenticationMethod::NONE; |
204 host_secret.value = "123456"; | 235 host_secret.value = "123456"; |
205 scoped_ptr<protocol::AuthenticatorFactory> auth_factory = | 236 scoped_ptr<protocol::AuthenticatorFactory> auth_factory = |
206 protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret( | 237 protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret( |
207 true, kHostOwner, host_cert, key_pair, host_secret, NULL); | 238 true, kHostOwner, host_cert, key_pair, host_secret, NULL); |
208 host_->SetAuthenticatorFactory(auth_factory.Pass()); | 239 host_->SetAuthenticatorFactory(auth_factory.Pass()); |
209 | 240 |
210 host_->AddStatusObserver(this); | 241 host_->AddStatusObserver(this); |
211 host_->set_protocol_config(protocol_config->Clone()); | 242 host_->set_protocol_config(protocol_config_->Clone()); |
212 host_->Start(kHostOwner); | 243 host_->Start(kHostOwner); |
213 | 244 |
| 245 message_loop_.PostTask(FROM_HERE, |
| 246 base::Bind(&ProtocolPerfTest::StartClientAfterHost, |
| 247 base::Unretained(this))); |
| 248 } |
| 249 |
| 250 void StartClientAfterHost() { |
| 251 client_signaling_->ConnectTo(host_signaling_.get()); |
| 252 |
| 253 protocol::NetworkSettings network_settings( |
| 254 protocol::NetworkSettings::NAT_TRAVERSAL_OUTGOING); |
| 255 |
214 // Initialize client. | 256 // Initialize client. |
215 client_context_.reset( | 257 client_context_.reset( |
216 new ClientContext(base::ThreadTaskRunnerHandle::Get())); | 258 new ClientContext(base::ThreadTaskRunnerHandle::Get())); |
217 | 259 |
218 // TODO(sergeyu): Replace with a fake port allocator | 260 // TODO(sergeyu): Replace with a fake port allocator |
219 scoped_ptr<cricket::HttpPortAllocatorBase> client_port_allocator = | 261 scoped_ptr<cricket::HttpPortAllocatorBase> client_port_allocator = |
220 protocol::ChromiumPortAllocator::Create(NULL, network_settings) | 262 protocol::ChromiumPortAllocator::Create(NULL, network_settings) |
221 .PassAs<cricket::HttpPortAllocatorBase>(); | 263 .PassAs<cricket::HttpPortAllocatorBase>(); |
222 | 264 |
223 scoped_ptr<protocol::TransportFactory> client_transport_factory( | 265 scoped_ptr<protocol::TransportFactory> client_transport_factory( |
224 new protocol::LibjingleTransportFactory(client_signaling_.get(), | 266 new protocol::LibjingleTransportFactory(client_signaling_.get(), |
225 client_port_allocator.Pass(), | 267 client_port_allocator.Pass(), |
226 network_settings)); | 268 network_settings)); |
227 | 269 |
228 std::vector<protocol::AuthenticationMethod> auth_methods; | 270 std::vector<protocol::AuthenticationMethod> auth_methods; |
229 auth_methods.push_back(protocol::AuthenticationMethod::Spake2( | 271 auth_methods.push_back(protocol::AuthenticationMethod::Spake2( |
230 protocol::AuthenticationMethod::NONE)); | 272 protocol::AuthenticationMethod::NONE)); |
231 scoped_ptr<protocol::Authenticator> client_authenticator( | 273 scoped_ptr<protocol::Authenticator> client_authenticator( |
232 new protocol::NegotiatingClientAuthenticator( | 274 new protocol::NegotiatingClientAuthenticator( |
233 std::string(), // client_pairing_id | 275 std::string(), // client_pairing_id |
234 std::string(), // client_pairing_secret | 276 std::string(), // client_pairing_secret |
235 std::string(), // authentication_tag | 277 std::string(), // authentication_tag |
236 base::Bind(&ProtocolPerfTest::FetchPin, base::Unretained(this)), | 278 base::Bind(&ProtocolPerfTest::FetchPin, base::Unretained(this)), |
237 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(), | 279 scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>(), |
238 auth_methods)); | 280 auth_methods)); |
239 client_.reset(new ChromotingClient( | 281 client_.reset(new ChromotingClient( |
240 client_context_.get(), this, this, scoped_ptr<AudioPlayer>())); | 282 client_context_.get(), this, this, scoped_ptr<AudioPlayer>())); |
241 client_->SetProtocolConfigForTests(protocol_config->Clone()); | 283 client_->SetProtocolConfigForTests(protocol_config_->Clone()); |
242 client_->Start( | 284 client_->Start( |
243 client_signaling_.get(), client_authenticator.Pass(), | 285 client_signaling_.get(), client_authenticator.Pass(), |
244 client_transport_factory.Pass(), kHostJid, std::string()); | 286 client_transport_factory.Pass(), kHostJid, std::string()); |
245 } | 287 } |
246 | 288 |
247 void FetchPin( | 289 void FetchPin( |
248 bool pairing_supported, | 290 bool pairing_supported, |
249 const protocol::SecretFetchedCallback& secret_fetched_callback) { | 291 const protocol::SecretFetchedCallback& secret_fetched_callback) { |
250 secret_fetched_callback.Run("123456"); | 292 secret_fetched_callback.Run("123456"); |
251 } | 293 } |
252 | 294 |
253 base::MessageLoopForIO message_loop_; | 295 base::MessageLoopForIO message_loop_; |
254 | 296 |
255 FakeDesktopEnvironmentFactory desktop_environment_factory_; | 297 base::Thread host_thread_; |
256 base::Thread capture_thread_; | 298 base::Thread capture_thread_; |
257 base::Thread encode_thread_; | 299 base::Thread encode_thread_; |
| 300 FakeDesktopEnvironmentFactory desktop_environment_factory_; |
| 301 |
| 302 scoped_ptr<protocol::CandidateSessionConfig> protocol_config_; |
258 | 303 |
259 scoped_ptr<FakeSignalStrategy> host_signaling_; | 304 scoped_ptr<FakeSignalStrategy> host_signaling_; |
260 scoped_ptr<FakeSignalStrategy> client_signaling_; | 305 scoped_ptr<FakeSignalStrategy> client_signaling_; |
261 | 306 |
262 scoped_ptr<ChromotingHost> host_; | 307 scoped_ptr<ChromotingHost> host_; |
263 scoped_ptr<ClientContext> client_context_; | 308 scoped_ptr<ClientContext> client_context_; |
264 scoped_ptr<ChromotingClient> client_; | 309 scoped_ptr<ChromotingClient> client_; |
265 | 310 |
266 scoped_ptr<base::RunLoop> connecting_loop_; | 311 scoped_ptr<base::RunLoop> connecting_loop_; |
267 scoped_ptr<base::RunLoop> waiting_frames_loop_; | 312 scoped_ptr<base::RunLoop> waiting_frames_loop_; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 base::TimeDelta latency; | 393 base::TimeDelta latency; |
349 ReceiveFrame(&latency); | 394 ReceiveFrame(&latency); |
350 LOG(INFO) << "Latency: " << latency.InMillisecondsF() | 395 LOG(INFO) << "Latency: " << latency.InMillisecondsF() |
351 << "ms Encode: " << last_video_packet_->encode_time_ms() | 396 << "ms Encode: " << last_video_packet_->encode_time_ms() |
352 << "ms Capture: " << last_video_packet_->capture_time_ms() | 397 << "ms Capture: " << last_video_packet_->capture_time_ms() |
353 << "ms"; | 398 << "ms"; |
354 } | 399 } |
355 } | 400 } |
356 | 401 |
357 } // namespace remoting | 402 } // namespace remoting |
OLD | NEW |