OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/protocol/quic_channel_factory.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "base/run_loop.h" | |
10 #include "net/base/io_buffer.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/test_completion_callback.h" | |
13 #include "net/quic/p2p/quic_p2p_session.h" | |
14 #include "net/quic/p2p/quic_p2p_stream.h" | |
15 #include "net/socket/socket.h" | |
16 #include "remoting/base/constants.h" | |
17 #include "remoting/protocol/connection_tester.h" | |
18 #include "remoting/protocol/fake_datagram_socket.h" | |
19 #include "remoting/protocol/p2p_stream_socket.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using testing::_; | |
24 using testing::AtMost; | |
25 using testing::InvokeWithoutArgs; | |
26 | |
27 namespace remoting { | |
28 namespace protocol { | |
29 | |
30 namespace { | |
31 | |
32 const int kMessageSize = 1024; | |
33 const int kMessages = 100; | |
34 | |
35 const char kTestSessionId[] = "123123"; | |
36 const char kTestChannelName[] = "test"; | |
37 const char kTestChannelName2[] = "test2"; | |
38 | |
39 } // namespace | |
40 | |
41 class QuicChannelFactoryTest : public testing::Test, | |
42 public testing::WithParamInterface<bool> { | |
43 public: | |
44 void DeleteAll() { | |
45 host_channel1_.reset(); | |
46 host_channel2_.reset(); | |
47 client_channel1_.reset(); | |
48 client_channel2_.reset(); | |
49 host_quic_.reset(); | |
50 client_quic_.reset(); | |
51 } | |
52 | |
53 void FailedReadDeleteAll(int result) { | |
54 EXPECT_NE(net::OK, result); | |
55 DeleteAll(); | |
56 } | |
57 | |
58 void OnChannelConnected(scoped_ptr<P2PStreamSocket>* storage, | |
59 int* counter, | |
60 base::RunLoop* run_loop, | |
61 scoped_ptr<P2PStreamSocket> socket) { | |
62 *storage = socket.Pass(); | |
63 if (counter) { | |
64 --(*counter); | |
65 EXPECT_GE(*counter, 0); | |
66 if (*counter == 0) | |
67 run_loop->Quit(); | |
68 } | |
69 } | |
70 | |
71 void OnChannelConnectedExpectFail(scoped_ptr<P2PStreamSocket> socket) { | |
72 EXPECT_FALSE(socket); | |
73 host_quic_->CancelChannelCreation(kTestChannelName2); | |
74 DeleteAll(); | |
75 } | |
76 | |
77 void OnChannelConnectedNotReached(scoped_ptr<P2PStreamSocket> socket) { | |
78 NOTREACHED(); | |
79 } | |
80 | |
81 protected: | |
82 void TearDown() override { | |
83 DeleteAll(); | |
84 // QuicChannelFactory destroys the internals asynchronously. Run all pending | |
85 // tasks to avoid leaking memory. | |
86 base::RunLoop().RunUntilIdle(); | |
87 } | |
88 | |
89 void Initialize() { | |
90 host_base_channel_factory_.PairWith(&client_base_channel_factory_); | |
91 host_base_channel_factory_.set_asynchronous_create(GetParam()); | |
92 client_base_channel_factory_.set_asynchronous_create(GetParam()); | |
93 | |
94 host_quic_.reset(new QuicChannelFactory(kTestSessionId, true)); | |
95 client_quic_.reset(new QuicChannelFactory(kTestSessionId, false)); | |
96 | |
97 session_initiate_message_ = | |
98 client_quic_->CreateSessionInitiateConfigMessage(); | |
99 EXPECT_TRUE(host_quic_->ProcessSessionInitiateConfigMessage( | |
100 session_initiate_message_)); | |
101 | |
102 session_accept_message_ = host_quic_->CreateSessionAcceptConfigMessage(); | |
103 EXPECT_TRUE(client_quic_->ProcessSessionAcceptConfigMessage( | |
104 session_accept_message_)); | |
105 | |
106 const char kTestSharedSecret[] = "Shared Secret"; | |
107 host_quic_->Start(&host_base_channel_factory_, kTestSharedSecret); | |
108 client_quic_->Start(&client_base_channel_factory_, kTestSharedSecret); | |
109 | |
110 FakeDatagramSocket* host_base_channel = | |
111 host_base_channel_factory_.GetFakeChannel(kQuicChannelName); | |
112 if (host_base_channel) | |
113 host_base_channel->set_async_send(GetParam()); | |
114 | |
115 FakeDatagramSocket* client_base_channel = | |
116 client_base_channel_factory_.GetFakeChannel(kQuicChannelName); | |
117 if (client_base_channel) | |
118 client_base_channel->set_async_send(GetParam()); | |
119 } | |
120 | |
121 void CreateChannel(const std::string& name, | |
122 scoped_ptr<P2PStreamSocket>* host_channel, | |
123 scoped_ptr<P2PStreamSocket>* client_channel) { | |
124 int counter = 2; | |
125 base::RunLoop run_loop; | |
126 host_quic_->CreateChannel( | |
127 name, | |
128 base::Bind(&QuicChannelFactoryTest::OnChannelConnected, | |
129 base::Unretained(this), host_channel, &counter, &run_loop)); | |
130 client_quic_->CreateChannel( | |
131 name, base::Bind(&QuicChannelFactoryTest::OnChannelConnected, | |
132 base::Unretained(this), client_channel, &counter, | |
133 &run_loop)); | |
134 | |
135 run_loop.Run(); | |
136 | |
137 EXPECT_TRUE(host_channel->get()); | |
138 EXPECT_TRUE(client_channel->get()); | |
139 } | |
140 | |
141 scoped_refptr<net::IOBufferWithSize> CreateTestBuffer(int size) { | |
142 scoped_refptr<net::IOBufferWithSize> result = | |
143 new net::IOBufferWithSize(size); | |
144 for (int i = 0; i < size; ++i) { | |
145 result->data()[i] = rand() % 256; | |
146 } | |
147 return result; | |
148 } | |
149 | |
150 base::MessageLoop message_loop_; | |
151 | |
152 FakeDatagramChannelFactory host_base_channel_factory_; | |
153 FakeDatagramChannelFactory client_base_channel_factory_; | |
154 | |
155 scoped_ptr<QuicChannelFactory> host_quic_; | |
156 scoped_ptr<QuicChannelFactory> client_quic_; | |
157 | |
158 scoped_ptr<P2PStreamSocket> host_channel1_; | |
159 scoped_ptr<P2PStreamSocket> client_channel1_; | |
160 scoped_ptr<P2PStreamSocket> host_channel2_; | |
161 scoped_ptr<P2PStreamSocket> client_channel2_; | |
162 | |
163 std::string session_initiate_message_; | |
164 std::string session_accept_message_; | |
165 }; | |
166 | |
167 INSTANTIATE_TEST_CASE_P(SyncWrite, | |
168 QuicChannelFactoryTest, | |
169 ::testing::Values(false)); | |
170 INSTANTIATE_TEST_CASE_P(AsyncWrite, | |
171 QuicChannelFactoryTest, | |
172 ::testing::Values(true)); | |
173 | |
174 TEST_P(QuicChannelFactoryTest, OneChannel) { | |
175 Initialize(); | |
176 | |
177 scoped_ptr<P2PStreamSocket> host_channel; | |
178 scoped_ptr<P2PStreamSocket> client_channel; | |
179 ASSERT_NO_FATAL_FAILURE( | |
180 CreateChannel(kTestChannelName, &host_channel, &client_channel)); | |
181 | |
182 StreamConnectionTester tester(host_channel.get(), client_channel.get(), | |
183 kMessageSize, kMessages); | |
184 tester.Start(); | |
185 message_loop_.Run(); | |
186 tester.CheckResults(); | |
187 } | |
188 | |
189 TEST_P(QuicChannelFactoryTest, TwoChannels) { | |
190 Initialize(); | |
191 | |
192 scoped_ptr<P2PStreamSocket> host_channel1_; | |
193 scoped_ptr<P2PStreamSocket> client_channel1_; | |
194 ASSERT_NO_FATAL_FAILURE( | |
195 CreateChannel(kTestChannelName, &host_channel1_, &client_channel1_)); | |
196 | |
197 scoped_ptr<P2PStreamSocket> host_channel2_; | |
198 scoped_ptr<P2PStreamSocket> client_channel2_; | |
199 ASSERT_NO_FATAL_FAILURE( | |
200 CreateChannel(kTestChannelName2, &host_channel2_, &client_channel2_)); | |
201 | |
202 StreamConnectionTester tester1(host_channel1_.get(), client_channel1_.get(), | |
203 kMessageSize, kMessages); | |
204 StreamConnectionTester tester2(host_channel2_.get(), client_channel2_.get(), | |
205 kMessageSize, kMessages); | |
206 tester1.Start(); | |
207 tester2.Start(); | |
208 while (!tester1.done() || !tester2.done()) { | |
209 message_loop_.Run(); | |
210 } | |
211 tester1.CheckResults(); | |
212 tester2.CheckResults(); | |
213 } | |
214 | |
215 TEST_P(QuicChannelFactoryTest, SendFail) { | |
216 Initialize(); | |
217 | |
218 scoped_ptr<P2PStreamSocket> host_channel1_; | |
219 scoped_ptr<P2PStreamSocket> client_channel1_; | |
220 ASSERT_NO_FATAL_FAILURE( | |
221 CreateChannel(kTestChannelName, &host_channel1_, &client_channel1_)); | |
222 | |
223 scoped_ptr<P2PStreamSocket> host_channel2_; | |
224 scoped_ptr<P2PStreamSocket> client_channel2_; | |
225 ASSERT_NO_FATAL_FAILURE( | |
226 CreateChannel(kTestChannelName2, &host_channel2_, &client_channel2_)); | |
227 | |
228 host_base_channel_factory_.GetFakeChannel(kQuicChannelName) | |
229 ->set_next_send_error(net::ERR_FAILED); | |
230 | |
231 scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100); | |
232 | |
233 | |
234 // Try writing to a channel. This should result in all stream being closed due | |
235 // to an error. | |
236 { | |
237 net::TestCompletionCallback write_cb_1; | |
238 host_channel1_->Write(buf.get(), buf->size(), write_cb_1.callback()); | |
239 base::RunLoop().RunUntilIdle(); | |
240 } | |
241 | |
242 // Repeated attempt to write should result in an error. | |
243 { | |
244 net::TestCompletionCallback write_cb_1; | |
245 net::TestCompletionCallback write_cb_2; | |
246 EXPECT_NE(net::OK, host_channel1_->Write(buf.get(), buf->size(), | |
247 write_cb_1.callback())); | |
248 EXPECT_FALSE(write_cb_1.have_result()); | |
249 EXPECT_NE(net::OK, host_channel1_->Write(buf.get(), buf->size(), | |
250 write_cb_2.callback())); | |
251 EXPECT_FALSE(write_cb_2.have_result()); | |
252 } | |
253 } | |
254 | |
255 TEST_P(QuicChannelFactoryTest, DeleteWhenFailed) { | |
256 Initialize(); | |
257 | |
258 ASSERT_NO_FATAL_FAILURE( | |
259 CreateChannel(kTestChannelName, &host_channel1_, &client_channel1_)); | |
260 ASSERT_NO_FATAL_FAILURE( | |
261 CreateChannel(kTestChannelName2, &host_channel2_, &client_channel2_)); | |
262 | |
263 host_base_channel_factory_.GetFakeChannel(kQuicChannelName) | |
264 ->set_next_send_error(net::ERR_FAILED); | |
265 | |
266 scoped_refptr<net::IOBufferWithSize> read_buf = | |
267 new net::IOBufferWithSize(100); | |
268 | |
269 EXPECT_EQ(net::ERR_IO_PENDING, | |
270 host_channel1_->Read( | |
271 read_buf.get(), read_buf->size(), | |
272 base::Bind(&QuicChannelFactoryTest::FailedReadDeleteAll, | |
273 base::Unretained(this)))); | |
274 | |
275 // Try writing to a channel. This should result it DeleteAll() called and the | |
276 // connection torn down. | |
277 scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100); | |
278 net::TestCompletionCallback write_cb_1; | |
279 host_channel1_->Write(buf.get(), buf->size(), write_cb_1.callback()); | |
280 | |
281 base::RunLoop().RunUntilIdle(); | |
282 | |
283 // Check that the connection was torn down. | |
284 EXPECT_FALSE(host_quic_); | |
285 } | |
286 | |
287 TEST_P(QuicChannelFactoryTest, SessionFail) { | |
288 host_base_channel_factory_.set_fail_create(true); | |
289 Initialize(); | |
290 | |
291 host_quic_->CreateChannel( | |
292 kTestChannelName, | |
293 base::Bind(&QuicChannelFactoryTest::OnChannelConnectedExpectFail, | |
294 base::Unretained(this))); | |
295 | |
296 // host_quic_ may be destroyed at this point in sync mode. | |
297 if (host_quic_) { | |
298 host_quic_->CreateChannel( | |
299 kTestChannelName2, | |
300 base::Bind(&QuicChannelFactoryTest::OnChannelConnectedNotReached, | |
301 base::Unretained(this))); | |
302 } | |
303 | |
304 base::RunLoop().RunUntilIdle(); | |
305 | |
306 // Check that DeleteAll() was called and the connection was torn down. | |
307 EXPECT_FALSE(host_quic_); | |
308 } | |
309 | |
310 // Verify that the host just ignores incoming stream with unexpected name. | |
311 TEST_P(QuicChannelFactoryTest, UnknownName) { | |
312 Initialize(); | |
313 | |
314 // Create a new channel from the client side. | |
315 client_quic_->CreateChannel( | |
316 kTestChannelName, base::Bind(&QuicChannelFactoryTest::OnChannelConnected, | |
317 base::Unretained(this), &client_channel1_, | |
318 nullptr, nullptr)); | |
319 base::RunLoop().RunUntilIdle(); | |
320 | |
321 EXPECT_EQ(0U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
322 } | |
323 | |
324 // Verify that incoming streams that have received only partial name are | |
325 // destroyed correctly. | |
326 TEST_P(QuicChannelFactoryTest, SendPartialName) { | |
327 Initialize(); | |
328 | |
329 base::RunLoop().RunUntilIdle(); | |
330 | |
331 net::QuicP2PSession* session = client_quic_->GetP2PSessionForTests(); | |
332 net::QuicP2PStream* stream = session->CreateOutgoingDynamicStream(); | |
333 | |
334 std::string name = kTestChannelName; | |
335 // Send only half of the name to the host. | |
336 stream->WriteHeader(std::string(1, static_cast<char>(name.size())) + | |
337 name.substr(0, name.size() / 2)); | |
338 | |
339 base::RunLoop().RunUntilIdle(); | |
340 | |
341 // Host should have received the new stream and is still waiting for the name. | |
342 EXPECT_EQ(1U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
343 | |
344 session->CloseStream(stream->id()); | |
345 base::RunLoop().RunUntilIdle(); | |
346 | |
347 // Verify that the stream was closed on the host side. | |
348 EXPECT_EQ(0U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
349 | |
350 // Create another stream with only partial name and tear down connection while | |
351 // it's still pending. | |
352 stream = session->CreateOutgoingDynamicStream(); | |
353 stream->WriteHeader(std::string(1, static_cast<char>(name.size())) + | |
354 name.substr(0, name.size() / 2)); | |
355 base::RunLoop().RunUntilIdle(); | |
356 EXPECT_EQ(1U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
357 } | |
358 | |
359 // Verify that correct HKDF input suffix is used to generate encryption keys. | |
360 TEST_P(QuicChannelFactoryTest, HkdfInputSuffix) { | |
361 Initialize(); | |
362 base::RunLoop().RunUntilIdle(); | |
363 | |
364 net::QuicCryptoStream* crypto_stream = | |
365 reinterpret_cast<net::QuicCryptoStream*>( | |
366 host_quic_->GetP2PSessionForTests()->GetStream(net::kCryptoStreamId)); | |
367 const std::string& suffix = | |
368 crypto_stream->crypto_negotiated_params().hkdf_input_suffix; | |
369 EXPECT_EQ(strlen(kTestSessionId) + 1 + strlen(kQuicChannelName) + 1 + | |
370 session_initiate_message_.size() + | |
371 session_accept_message_.size(), | |
372 suffix.size()); | |
373 EXPECT_EQ(std::string(kTestSessionId) + '\0' + kQuicChannelName + '\0' + | |
374 session_initiate_message_ + session_accept_message_, | |
375 suffix); | |
376 } | |
377 | |
378 } // namespace protocol | |
379 } // namespace remoting | |
OLD | NEW |