| 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 <stddef.h> | 5 #include <stddef.h> |
| 6 #include <sys/epoll.h> | 6 #include <sys/epoll.h> |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 : initialized_(false), | 259 : initialized_(false), |
| 260 server_address_(IPEndPoint(Loopback4(), 0)), | 260 server_address_(IPEndPoint(Loopback4(), 0)), |
| 261 server_hostname_("example.com"), | 261 server_hostname_("example.com"), |
| 262 server_started_(false), | 262 server_started_(false), |
| 263 strike_register_no_startup_period_(false), | 263 strike_register_no_startup_period_(false), |
| 264 chlo_multiplier_(0), | 264 chlo_multiplier_(0), |
| 265 stream_factory_(nullptr) { | 265 stream_factory_(nullptr) { |
| 266 client_supported_versions_ = GetParam().client_supported_versions; | 266 client_supported_versions_ = GetParam().client_supported_versions; |
| 267 server_supported_versions_ = GetParam().server_supported_versions; | 267 server_supported_versions_ = GetParam().server_supported_versions; |
| 268 negotiated_version_ = GetParam().negotiated_version; | 268 negotiated_version_ = GetParam().negotiated_version; |
| 269 FLAGS_enable_quic_fec = GetParam().use_fec; | |
| 270 | 269 |
| 271 VLOG(1) << "Using Configuration: " << GetParam(); | 270 VLOG(1) << "Using Configuration: " << GetParam(); |
| 272 | 271 |
| 273 // Use different flow control windows for client/server. | 272 // Use different flow control windows for client/server. |
| 274 client_config_.SetInitialStreamFlowControlWindowToSend( | 273 client_config_.SetInitialStreamFlowControlWindowToSend( |
| 275 2 * kInitialStreamFlowControlWindowForTest); | 274 2 * kInitialStreamFlowControlWindowForTest); |
| 276 client_config_.SetInitialSessionFlowControlWindowToSend( | 275 client_config_.SetInitialSessionFlowControlWindowToSend( |
| 277 2 * kInitialSessionFlowControlWindowForTest); | 276 2 * kInitialSessionFlowControlWindowForTest); |
| 278 server_config_.SetInitialStreamFlowControlWindowToSend( | 277 server_config_.SetInitialStreamFlowControlWindowToSend( |
| 279 3 * kInitialStreamFlowControlWindowForTest); | 278 3 * kInitialStreamFlowControlWindowForTest); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 copt.push_back(kAFCW); | 363 copt.push_back(kAFCW); |
| 365 copt.push_back(kIFW5); | 364 copt.push_back(kIFW5); |
| 366 } | 365 } |
| 367 client_config_.SetConnectionOptionsToSend(copt); | 366 client_config_.SetConnectionOptionsToSend(copt); |
| 368 | 367 |
| 369 // Start the server first, because CreateQuicClient() attempts | 368 // Start the server first, because CreateQuicClient() attempts |
| 370 // to connect to the server. | 369 // to connect to the server. |
| 371 StartServer(); | 370 StartServer(); |
| 372 | 371 |
| 373 client_.reset(CreateQuicClient(client_writer_)); | 372 client_.reset(CreateQuicClient(client_writer_)); |
| 374 if (GetParam().use_fec) { | |
| 375 // Set FecPolicy to always protect data on all streams. | |
| 376 client_->SetFecPolicy(FEC_PROTECT_ALWAYS); | |
| 377 } | |
| 378 static EpollEvent event(EPOLLOUT, false); | 373 static EpollEvent event(EPOLLOUT, false); |
| 379 client_writer_->Initialize( | 374 client_writer_->Initialize( |
| 380 reinterpret_cast<QuicEpollConnectionHelper*>( | 375 reinterpret_cast<QuicEpollConnectionHelper*>( |
| 381 QuicConnectionPeer::GetHelper( | 376 QuicConnectionPeer::GetHelper( |
| 382 client_->client()->session()->connection())), | 377 client_->client()->session()->connection())), |
| 383 new ClientDelegate(client_->client())); | 378 new ClientDelegate(client_->client())); |
| 384 initialized_ = true; | 379 initialized_ = true; |
| 385 return client_->client()->connected(); | 380 return client_->client()->connected(); |
| 386 } | 381 } |
| 387 | 382 |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kIW10)); | 986 ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kIW10)); |
| 992 EXPECT_TRUE( | 987 EXPECT_TRUE( |
| 993 ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kPRST)); | 988 ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kPRST)); |
| 994 } | 989 } |
| 995 | 990 |
| 996 TEST_P(EndToEndTest, CorrectlyConfiguredFec) { | 991 TEST_P(EndToEndTest, CorrectlyConfiguredFec) { |
| 997 ASSERT_TRUE(Initialize()); | 992 ASSERT_TRUE(Initialize()); |
| 998 client_->client()->WaitForCryptoHandshakeConfirmed(); | 993 client_->client()->WaitForCryptoHandshakeConfirmed(); |
| 999 server_thread_->WaitForCryptoHandshakeConfirmed(); | 994 server_thread_->WaitForCryptoHandshakeConfirmed(); |
| 1000 | 995 |
| 1001 FecPolicy expected_policy = | 996 FecPolicy expected_policy = FEC_PROTECT_OPTIONAL; |
| 1002 GetParam().use_fec ? FEC_PROTECT_ALWAYS : FEC_PROTECT_OPTIONAL; | |
| 1003 | 997 |
| 1004 // Verify that server's FEC configuration is correct. | 998 // Verify that server's FEC configuration is correct. |
| 1005 server_thread_->Pause(); | 999 server_thread_->Pause(); |
| 1006 QuicDispatcher* dispatcher = | 1000 QuicDispatcher* dispatcher = |
| 1007 QuicServerPeer::GetDispatcher(server_thread_->server()); | 1001 QuicServerPeer::GetDispatcher(server_thread_->server()); |
| 1008 ASSERT_EQ(1u, dispatcher->session_map().size()); | 1002 ASSERT_EQ(1u, dispatcher->session_map().size()); |
| 1009 QuicSpdySession* session = dispatcher->session_map().begin()->second; | 1003 QuicSpdySession* session = dispatcher->session_map().begin()->second; |
| 1010 EXPECT_EQ(expected_policy, | 1004 EXPECT_EQ(expected_policy, |
| 1011 QuicSpdySessionPeer::GetHeadersStream(session)->fec_policy()); | 1005 QuicSpdySessionPeer::GetHeadersStream(session)->fec_policy()); |
| 1012 server_thread_->Resume(); | 1006 server_thread_->Resume(); |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 | 1495 |
| 1502 // Store the client address which was used to send the first request. | 1496 // Store the client address which was used to send the first request. |
| 1503 IPEndPoint old_address = client_->client()->GetLatestClientAddress(); | 1497 IPEndPoint old_address = client_->client()->GetLatestClientAddress(); |
| 1504 | 1498 |
| 1505 // Stop listening and close the old FD. | 1499 // Stop listening and close the old FD. |
| 1506 QuicClientPeer::CleanUpUDPSocket(client_->client(), | 1500 QuicClientPeer::CleanUpUDPSocket(client_->client(), |
| 1507 client_->client()->GetLatestFD()); | 1501 client_->client()->GetLatestFD()); |
| 1508 | 1502 |
| 1509 // Create a new socket before closing the old one, which will result in a new | 1503 // Create a new socket before closing the old one, which will result in a new |
| 1510 // ephemeral port. | 1504 // ephemeral port. |
| 1511 QuicClientPeer::CreateUDPSocket(client_->client()); | 1505 QuicClientPeer::CreateUDPSocketAndBind(client_->client()); |
| 1512 | 1506 |
| 1513 // The packet writer needs to be updated to use the new FD. | 1507 // The packet writer needs to be updated to use the new FD. |
| 1514 client_->client()->CreateQuicPacketWriter(); | 1508 client_->client()->CreateQuicPacketWriter(); |
| 1515 | 1509 |
| 1516 // Change the internal state of the client and connection to use the new port, | 1510 // Change the internal state of the client and connection to use the new port, |
| 1517 // this is done because in a real NAT rebinding the client wouldn't see any | 1511 // this is done because in a real NAT rebinding the client wouldn't see any |
| 1518 // port change, and so expects no change to incoming port. | 1512 // port change, and so expects no change to incoming port. |
| 1519 // This is kind of ugly, but needed as we are simply swapping out the client | 1513 // This is kind of ugly, but needed as we are simply swapping out the client |
| 1520 // FD rather than any more complex NAT rebinding simulation. | 1514 // FD rather than any more complex NAT rebinding simulation. |
| 1521 int new_port = client_->client()->GetLatestClientAddress().port(); | 1515 int new_port = client_->client()->GetLatestClientAddress().port(); |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2146 // (This is OK despite already waiting for a response.) | 2140 // (This is OK despite already waiting for a response.) |
| 2147 client_->WaitForResponse(); | 2141 client_->WaitForResponse(); |
| 2148 // There should be no buffered data to write in the client's stream. | 2142 // There should be no buffered data to write in the client's stream. |
| 2149 ReliableQuicStream* stream = | 2143 ReliableQuicStream* stream = |
| 2150 client_->client()->session()->GetStream(kClientDataStreamId1); | 2144 client_->client()->session()->GetStream(kClientDataStreamId1); |
| 2151 EXPECT_FALSE(stream != nullptr && stream->HasBufferedData()); | 2145 EXPECT_FALSE(stream != nullptr && stream->HasBufferedData()); |
| 2152 } | 2146 } |
| 2153 | 2147 |
| 2154 TEST_P(EndToEndTest, Trailers) { | 2148 TEST_P(EndToEndTest, Trailers) { |
| 2155 // Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames). | 2149 // Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames). |
| 2156 ValueRestore<bool> old_flag(&FLAGS_quic_supports_trailers, true); | |
| 2157 ASSERT_TRUE(Initialize()); | 2150 ASSERT_TRUE(Initialize()); |
| 2158 client_->client()->WaitForCryptoHandshakeConfirmed(); | 2151 client_->client()->WaitForCryptoHandshakeConfirmed(); |
| 2159 | 2152 |
| 2160 // Set reordering to ensure that Trailers arriving before body is ok. | 2153 // Set reordering to ensure that Trailers arriving before body is ok. |
| 2161 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); | 2154 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); |
| 2162 SetReorderPercentage(30); | 2155 SetReorderPercentage(30); |
| 2163 | 2156 |
| 2164 // Add a response with headers, body, and trailers. | 2157 // Add a response with headers, body, and trailers. |
| 2165 const string kBody = "body content"; | 2158 const string kBody = "body content"; |
| 2166 | 2159 |
| 2167 SpdyHeaderBlock headers; | 2160 SpdyHeaderBlock headers; |
| 2168 headers[":status"] = "200"; | 2161 headers[":status"] = "200"; |
| 2169 headers[":version"] = "HTTP/1.1"; | 2162 headers[":version"] = "HTTP/1.1"; |
| 2170 headers["content-length"] = IntToString(kBody.size()); | 2163 headers["content-length"] = IntToString(kBody.size()); |
| 2171 | 2164 |
| 2172 SpdyHeaderBlock trailers; | 2165 SpdyHeaderBlock trailers; |
| 2173 trailers["some-trailing-header"] = "trailing-header-value"; | 2166 trailers["some-trailing-header"] = "trailing-header-value"; |
| 2174 | 2167 |
| 2175 QuicInMemoryCache::GetInstance()->AddResponse( | 2168 QuicInMemoryCache::GetInstance()->AddResponse( |
| 2176 "www.google.com", "/trailer_url", headers, kBody, trailers); | 2169 "www.google.com", "/trailer_url", headers, kBody, trailers); |
| 2177 | 2170 |
| 2178 EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url")); | 2171 EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url")); |
| 2179 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); | 2172 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); |
| 2180 EXPECT_EQ(trailers, client_->response_trailers()); | 2173 EXPECT_EQ(trailers, client_->response_trailers()); |
| 2181 } | 2174 } |
| 2182 | 2175 |
| 2183 TEST_P(EndToEndTest, ServerPush) { | 2176 class EndToEndTestServerPush : public EndToEndTest { |
| 2184 FLAGS_quic_supports_push_promise = true; | 2177 protected: |
| 2178 const size_t kNumMaxStreams = 10; |
| 2179 |
| 2180 EndToEndTestServerPush() : EndToEndTest() { |
| 2181 FLAGS_quic_supports_push_promise = true; |
| 2182 FLAGS_quic_different_max_num_open_streams = true; |
| 2183 client_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams); |
| 2184 } |
| 2185 |
| 2186 // Add a request with its response and |num_resources| push resources into |
| 2187 // cache. |
| 2188 // If |resource_size| == 0, response body of push resources use default string |
| 2189 // concatenating with resource url. Otherwise, generate a string of |
| 2190 // |resource_size| as body. |
| 2191 void AddRequestAndResponseWithServerPush(string host, |
| 2192 string path, |
| 2193 string response_body, |
| 2194 string* push_urls, |
| 2195 const size_t num_resources, |
| 2196 const size_t resource_size) { |
| 2197 bool use_large_response = resource_size != 0; |
| 2198 string large_resource; |
| 2199 if (use_large_response) { |
| 2200 // Generate a response common body larger than flow control window for |
| 2201 // push response. |
| 2202 test::GenerateBody(&large_resource, resource_size); |
| 2203 } |
| 2204 list<QuicInMemoryCache::ServerPushInfo> push_resources; |
| 2205 for (size_t i = 0; i < num_resources; ++i) { |
| 2206 string url = push_urls[i]; |
| 2207 GURL resource_url(url); |
| 2208 string body = use_large_response |
| 2209 ? large_resource |
| 2210 : "This is server push response body for " + url; |
| 2211 SpdyHeaderBlock response_headers; |
| 2212 response_headers[":version"] = "HTTP/1.1"; |
| 2213 response_headers[":status"] = "200"; |
| 2214 response_headers["content-length"] = IntToString(body.size()); |
| 2215 push_resources.push_back(QuicInMemoryCache::ServerPushInfo( |
| 2216 resource_url, response_headers, kV3LowestPriority, body)); |
| 2217 } |
| 2218 |
| 2219 QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources( |
| 2220 host, path, 200, response_body, push_resources); |
| 2221 } |
| 2222 }; |
| 2223 |
| 2224 TEST_P(EndToEndTestServerPush, ServerPush) { |
| 2185 ASSERT_TRUE(Initialize()); | 2225 ASSERT_TRUE(Initialize()); |
| 2186 client_->client()->WaitForCryptoHandshakeConfirmed(); | 2226 client_->client()->WaitForCryptoHandshakeConfirmed(); |
| 2187 | 2227 |
| 2188 // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. | 2228 // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. |
| 2189 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); | 2229 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); |
| 2190 SetReorderPercentage(30); | 2230 SetReorderPercentage(30); |
| 2191 | 2231 |
| 2192 // Add a response with headers, body, and trailers. | 2232 // Add a response with headers, body, and push resources. |
| 2193 const string kBody = "body content"; | 2233 const string kBody = "body content"; |
| 2194 | 2234 size_t kNumResources = 4; |
| 2195 list<QuicInMemoryCache::ServerPushInfo> push_resources; | |
| 2196 | |
| 2197 string push_urls[] = { | 2235 string push_urls[] = { |
| 2198 "https://google.com/font.woff", "https://google.com/script.js", | 2236 "https://google.com/font.woff", "https://google.com/script.js", |
| 2199 "https://fonts.google.com/font.woff", "https://google.com/logo-hires.jpg", | 2237 "https://fonts.google.com/font.woff", "https://google.com/logo-hires.jpg", |
| 2200 }; | 2238 }; |
| 2201 for (const string& url : push_urls) { | 2239 AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, |
| 2202 GURL resource_url(url); | 2240 push_urls, kNumResources, 0); |
| 2203 string body = "This is server push response body for " + url; | |
| 2204 SpdyHeaderBlock response_headers; | |
| 2205 response_headers[":version"] = "HTTP/1.1"; | |
| 2206 response_headers[":status"] = "200"; | |
| 2207 response_headers["content-length"] = IntToString(body.size()); | |
| 2208 push_resources.push_back(QuicInMemoryCache::ServerPushInfo( | |
| 2209 resource_url, response_headers, kV3LowestPriority, body)); | |
| 2210 } | |
| 2211 | |
| 2212 QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources( | |
| 2213 "google.com", "/push_example", 200, kBody, push_resources); | |
| 2214 | 2241 |
| 2215 client_->client()->set_response_listener(new TestResponseListener); | 2242 client_->client()->set_response_listener(new TestResponseListener); |
| 2216 | 2243 |
| 2217 DVLOG(1) << "send request for /push_example"; | 2244 DVLOG(1) << "send request for /push_example"; |
| 2218 EXPECT_EQ(kBody, | 2245 EXPECT_EQ(kBody, client_->SendSynchronousRequest( |
| 2219 client_->SendSynchronousRequest("https://google.com/push_example")); | 2246 "https://example.com/push_example")); |
| 2220 for (const string& url : push_urls) { | 2247 for (const string& url : push_urls) { |
| 2221 DVLOG(1) << "send request for pushed stream on url " << url; | 2248 DVLOG(1) << "send request for pushed stream on url " << url; |
| 2222 string expected_body = "This is server push response body for " + url; | 2249 string expected_body = "This is server push response body for " + url; |
| 2223 string response_body = client_->SendSynchronousRequest(url); | 2250 string response_body = client_->SendSynchronousRequest(url); |
| 2224 DVLOG(1) << "response body " << response_body; | 2251 DVLOG(1) << "response body " << response_body; |
| 2225 EXPECT_EQ(expected_body, response_body); | 2252 EXPECT_EQ(expected_body, response_body); |
| 2226 } | 2253 } |
| 2227 } | 2254 } |
| 2228 | 2255 |
| 2256 TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) { |
| 2257 // Tests that sending a request which has 4 push resources will trigger server |
| 2258 // to push those 4 resources and client can handle pushed resources and match |
| 2259 // them with requests later. |
| 2260 ASSERT_TRUE(Initialize()); |
| 2261 |
| 2262 client_->client()->WaitForCryptoHandshakeConfirmed(); |
| 2263 |
| 2264 // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. |
| 2265 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); |
| 2266 SetReorderPercentage(30); |
| 2267 |
| 2268 // Add a response with headers, body, and push resources. |
| 2269 const string kBody = "body content"; |
| 2270 size_t const kNumResources = 4; |
| 2271 string push_urls[] = { |
| 2272 "https://example.com/font.woff", "https://example.com/script.js", |
| 2273 "https://fonts.example.com/font.woff", |
| 2274 "https://example.com/logo-hires.jpg", |
| 2275 }; |
| 2276 AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, |
| 2277 push_urls, kNumResources, 0); |
| 2278 client_->client()->set_response_listener(new TestResponseListener); |
| 2279 |
| 2280 // Send the first request: this will trigger the server to send all the push |
| 2281 // resources associated with this request, and these will be cached by the |
| 2282 // client. |
| 2283 EXPECT_EQ(kBody, client_->SendSynchronousRequest( |
| 2284 "https://example.com/push_example")); |
| 2285 EXPECT_EQ(1u + kNumResources, client_->num_responses()); |
| 2286 |
| 2287 for (string url : push_urls) { |
| 2288 // Sending subsequent requesets will not actually send anything on the wire, |
| 2289 // as the responses are already in the client's cache. |
| 2290 DVLOG(1) << "send request for pushed stream on url " << url; |
| 2291 string expected_body = "This is server push response body for " + url; |
| 2292 string response_body = client_->SendSynchronousRequest(url); |
| 2293 DVLOG(1) << "response body " << response_body; |
| 2294 EXPECT_EQ(expected_body, response_body); |
| 2295 } |
| 2296 // Expect only original request has been sent and push responses have been |
| 2297 // received as normal response. |
| 2298 EXPECT_EQ(1u, client_->num_requests()); |
| 2299 } |
| 2300 |
| 2301 TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) { |
| 2302 // Tests that when streams are not blocked by flow control or congestion |
| 2303 // control, pushing even more resources than max number of open outgoing |
| 2304 // streams should still work because all response streams get closed |
| 2305 // immediately after pushing resources. |
| 2306 ASSERT_TRUE(Initialize()); |
| 2307 client_->client()->WaitForCryptoHandshakeConfirmed(); |
| 2308 |
| 2309 // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. |
| 2310 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); |
| 2311 SetReorderPercentage(30); |
| 2312 |
| 2313 // Add a response with headers, body, and push resources. |
| 2314 const string kBody = "body content"; |
| 2315 |
| 2316 // One more resource than max number of outgoing stream of this session. |
| 2317 const size_t kNumResources = 1 + kNumMaxStreams; // 11. |
| 2318 string push_urls[11]; |
| 2319 for (uint32_t i = 0; i < kNumResources; ++i) { |
| 2320 push_urls[i] = "https://example.com/push_resources" + base::UintToString(i); |
| 2321 } |
| 2322 AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, |
| 2323 push_urls, kNumResources, 0); |
| 2324 client_->client()->set_response_listener(new TestResponseListener); |
| 2325 |
| 2326 // Send the first request: this will trigger the server to send all the push |
| 2327 // resources associated with this request, and these will be cached by the |
| 2328 // client. |
| 2329 EXPECT_EQ(kBody, client_->SendSynchronousRequest( |
| 2330 "https://example.com/push_example")); |
| 2331 // The responses to the original request and all the promised resources |
| 2332 // should have been received. |
| 2333 EXPECT_EQ(12u, client_->num_responses()); |
| 2334 |
| 2335 for (const string& url : push_urls) { |
| 2336 // Sending subsequent requesets will not actually send anything on the wire, |
| 2337 // as the responses are already in the client's cache. |
| 2338 EXPECT_EQ("This is server push response body for " + url, |
| 2339 client_->SendSynchronousRequest(url)); |
| 2340 } |
| 2341 |
| 2342 // Only 1 request should have been sent. |
| 2343 EXPECT_EQ(1u, client_->num_requests()); |
| 2344 } |
| 2345 |
| 2346 TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) { |
| 2347 // Tests that when server tries to send more large resources(large enough to |
| 2348 // be blocked by flow control window or congestion control window) than max |
| 2349 // open outgoing streams , server can open upto max number of outgoing |
| 2350 // streams for them, and the rest will be queued up. |
| 2351 |
| 2352 // Reset flow control windows. |
| 2353 size_t kFlowControlWnd = 20 * 1024; // 20KB. |
| 2354 // Response body is larger than 1 flow controlblock window. |
| 2355 size_t kBodySize = kFlowControlWnd * 2; |
| 2356 set_client_initial_stream_flow_control_receive_window(kFlowControlWnd); |
| 2357 // Make sure conntection level flow control window is large enough not to |
| 2358 // block data being sent out though they will be blocked by stream level one. |
| 2359 set_client_initial_session_flow_control_receive_window( |
| 2360 kBodySize * kNumMaxStreams + 1024); |
| 2361 |
| 2362 ASSERT_TRUE(Initialize()); |
| 2363 client_->client()->WaitForCryptoHandshakeConfirmed(); |
| 2364 |
| 2365 // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. |
| 2366 SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); |
| 2367 SetReorderPercentage(30); |
| 2368 |
| 2369 // Add a response with headers, body, and push resources. |
| 2370 const string kBody = "body content"; |
| 2371 |
| 2372 const size_t kNumResources = kNumMaxStreams + 1; |
| 2373 string push_urls[11]; |
| 2374 for (uint32_t i = 0; i < kNumResources; ++i) { |
| 2375 push_urls[i] = "http://example.com/push_resources" + base::UintToString(i); |
| 2376 } |
| 2377 AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, |
| 2378 push_urls, kNumResources, kBodySize); |
| 2379 |
| 2380 client_->client()->set_response_listener(new TestResponseListener); |
| 2381 |
| 2382 client_->SendRequest("https://example.com/push_example"); |
| 2383 |
| 2384 // Pause after the first response arrives. |
| 2385 while (!client_->response_complete()) { |
| 2386 // Because of priority, the first response arrived should be to original |
| 2387 // request. |
| 2388 client_->WaitForResponse(); |
| 2389 } |
| 2390 |
| 2391 // Check server session to see if it has max number of outgoing streams opened |
| 2392 // though more resources need to be pushed. |
| 2393 server_thread_->Pause(); |
| 2394 QuicDispatcher* dispatcher = |
| 2395 QuicServerPeer::GetDispatcher(server_thread_->server()); |
| 2396 ASSERT_EQ(1u, dispatcher->session_map().size()); |
| 2397 QuicSession* session = dispatcher->session_map().begin()->second; |
| 2398 EXPECT_EQ(kNumMaxStreams, session->GetNumOpenOutgoingStreams()); |
| 2399 server_thread_->Resume(); |
| 2400 |
| 2401 EXPECT_EQ(1u, client_->num_requests()); |
| 2402 EXPECT_EQ(1u, client_->num_responses()); |
| 2403 EXPECT_EQ(kBody, client_->response_body()); |
| 2404 |
| 2405 // "Send" request for a promised resources will not really send out it because |
| 2406 // its response is being pushed(but blocked). And the following ack and |
| 2407 // flow control behavior of SendSynchronousRequests() |
| 2408 // will unblock the stream to finish receiving response. |
| 2409 client_->SendSynchronousRequest(push_urls[0]); |
| 2410 EXPECT_EQ(1u, client_->num_requests()); |
| 2411 EXPECT_EQ(2u, client_->num_responses()); |
| 2412 |
| 2413 // Do same thing for the rest 10 resources. |
| 2414 for (uint32_t i = 1; i < kNumResources; ++i) { |
| 2415 client_->SendSynchronousRequest(push_urls[i]); |
| 2416 } |
| 2417 |
| 2418 // Because of server push, client gets all pushed resources without actually |
| 2419 // sending requests for them. |
| 2420 EXPECT_EQ(1u, client_->num_requests()); |
| 2421 // Including response to original request, 12 responses in total were |
| 2422 // recieved. |
| 2423 EXPECT_EQ(12u, client_->num_responses()); |
| 2424 } |
| 2425 |
| 2229 } // namespace | 2426 } // namespace |
| 2230 } // namespace test | 2427 } // namespace test |
| 2231 } // namespace net | 2428 } // namespace net |
| OLD | NEW |