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

Side by Side Diff: net/http/http_stream_parser_unittest.cc

Issue 2665603003: Add detection of Shoutcast responses and accept them as valid HTTP/0.9 (Closed)
Patch Set: Created 3 years, 10 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
« no previous file with comments | « net/http/http_stream_parser.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "net/http/http_stream_parser.h" 5 #include "net/http/http_stream_parser.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <memory> 10 #include <memory>
(...skipping 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 int size = data.size(); 1206 int size = data.size();
1207 read_buffer_->SetCapacity(offset + size); 1207 read_buffer_->SetCapacity(offset + size);
1208 memcpy(read_buffer_->StartOfBuffer() + offset, data.data(), size); 1208 memcpy(read_buffer_->StartOfBuffer() + offset, data.data(), size);
1209 read_buffer_->set_offset(offset + size); 1209 read_buffer_->set_offset(offset + size);
1210 } 1210 }
1211 1211
1212 void AddRead(const std::string& data) { 1212 void AddRead(const std::string& data) {
1213 reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data())); 1213 reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data()));
1214 } 1214 }
1215 1215
1216 // Simple overload - the above method requires using std::strings that outlive
1217 // the function call. This version works with inlined C-style strings.
1218 void AddRead(const char* data) {
1219 reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data));
1220 }
1221
1216 void SetupParserAndSendRequest() { 1222 void SetupParserAndSendRequest() {
1217 reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF 1223 reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF
1218 1224
1219 data_.reset(new SequencedSocketData(&reads_.front(), reads_.size(), 1225 data_.reset(new SequencedSocketData(&reads_.front(), reads_.size(),
1220 &writes_.front(), writes_.size())); 1226 &writes_.front(), writes_.size()));
1221 socket_handle_ = CreateConnectedSocketHandle(data_.get()); 1227 socket_handle_ = CreateConnectedSocketHandle(data_.get());
1222 1228
1223 request_info_.method = "GET"; 1229 request_info_.method = "GET";
1224 request_info_.url = url_; 1230 request_info_.url = url_;
1225 request_info_.load_flags = LOAD_NORMAL; 1231 request_info_.load_flags = LOAD_NORMAL;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 int sequence_number_; 1280 int sequence_number_;
1275 }; 1281 };
1276 1282
1277 // Test that HTTP/0.9 works as expected, only on ports where it should be 1283 // Test that HTTP/0.9 works as expected, only on ports where it should be
1278 // enabled. 1284 // enabled.
1279 TEST(HttpStreamParser, Http09PortTests) { 1285 TEST(HttpStreamParser, Http09PortTests) {
1280 struct TestCase { 1286 struct TestCase {
1281 const char* url; 1287 const char* url;
1282 bool http_09_on_non_default_ports_enabled; 1288 bool http_09_on_non_default_ports_enabled;
1283 1289
1284 // Expected result when trying to read headers. 1290 // Expected result when trying to read headers and response is an HTTP/0.9
1285 Error expected_header_error; 1291 // non-Shoutcast response.
1292 Error expected_09_header_error;
1293
1294 // Expected result when trying to read headers for a shoutcast response.
1295 Error expected_shoutcast_header_error;
1286 }; 1296 };
1287 1297
1288 const TestCase kTestCases[] = { 1298 const TestCase kTestCases[] = {
1289 // Default ports should work for HTTP/0.9, regardless of whether the port 1299 // Default ports should work for HTTP/0.9, regardless of whether the port
1290 // is explicitly specified or not. 1300 // is explicitly specified or not.
1291 {"http://foo.com/", false, OK}, 1301 {"http://foo.com/", false, OK, OK},
1292 {"http://foo.com:80/", false, OK}, 1302 {"http://foo.com:80/", false, OK, OK},
1293 {"https://foo.com/", false, OK}, 1303 {"https://foo.com/", false, OK, OK},
1294 {"https://foo.com:443/", false, OK}, 1304 {"https://foo.com:443/", false, OK, OK},
1295 1305
1296 // Non-standard ports should not support HTTP/0.9, by default. 1306 // Non-standard ports should not support HTTP/0.9, by default.
1297 {"http://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE}, 1307 {"http://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE, OK},
1298 {"https://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE}, 1308 {"https://foo.com:8080/", false, ERR_INVALID_HTTP_RESPONSE,
1299 {"http://foo.com:443/", false, ERR_INVALID_HTTP_RESPONSE}, 1309 ERR_INVALID_HTTP_RESPONSE},
1300 {"https://foo.com:80/", false, ERR_INVALID_HTTP_RESPONSE}, 1310 {"http://foo.com:443/", false, ERR_INVALID_HTTP_RESPONSE, OK},
1311 {"https://foo.com:80/", false, ERR_INVALID_HTTP_RESPONSE,
1312 ERR_INVALID_HTTP_RESPONSE},
1301 1313
1302 // Allowing non-default ports should not break the default ones. 1314 // Allowing non-default ports should not break the default ones.
1303 {"http://foo.com/", true, OK}, 1315 {"http://foo.com/", true, OK, OK},
1304 {"http://foo.com:80/", true, OK}, 1316 {"http://foo.com:80/", true, OK, OK},
1305 {"https://foo.com/", true, OK}, 1317 {"https://foo.com/", true, OK, OK},
1306 {"https://foo.com:443/", true, OK}, 1318 {"https://foo.com:443/", true, OK, OK},
1307 1319
1308 // Check that non-default ports works. 1320 // Check that non-default ports works.
1309 {"http://foo.com:8080/", true, OK}, 1321 {"http://foo.com:8080/", true, OK, OK},
1310 {"https://foo.com:8080/", true, OK}, 1322 {"https://foo.com:8080/", true, OK, OK},
1311 {"http://foo.com:443/", true, OK}, 1323 {"http://foo.com:443/", true, OK, OK},
1312 {"https://foo.com:80/", true, OK}, 1324 {"https://foo.com:80/", true, OK, OK},
1313 }; 1325 };
1314 1326
1315 std::string response = "hello\r\nworld\r\n"; 1327 const std::string kResponse = "hello\r\nworld\r\n";
1316 int response_size = response.size();
1317 1328
1318 for (const auto& test_case : kTestCases) { 1329 for (const auto& test_case : kTestCases) {
1319 SimpleGetRunner get_runner; 1330 SimpleGetRunner get_runner;
1320 get_runner.set_url(GURL(test_case.url)); 1331 get_runner.set_url(GURL(test_case.url));
1321 get_runner.set_http_09_on_non_default_ports_enabled( 1332 get_runner.set_http_09_on_non_default_ports_enabled(
1322 test_case.http_09_on_non_default_ports_enabled); 1333 test_case.http_09_on_non_default_ports_enabled);
1323 get_runner.AddRead(response); 1334 get_runner.AddRead(kResponse);
1324 get_runner.SetupParserAndSendRequest(); 1335 get_runner.SetupParserAndSendRequest();
1325 1336
1326 get_runner.ReadHeadersExpectingError(test_case.expected_header_error); 1337 get_runner.ReadHeadersExpectingError(test_case.expected_09_header_error);
1327 if (test_case.expected_header_error != OK) 1338 if (test_case.expected_09_header_error != OK)
1328 continue; 1339 continue;
1329 1340
1330 ASSERT_TRUE(get_runner.response_info()->headers); 1341 ASSERT_TRUE(get_runner.response_info()->headers);
1331 EXPECT_EQ("HTTP/0.9 200 OK", 1342 EXPECT_EQ("HTTP/0.9 200 OK",
1332 get_runner.response_info()->headers->GetStatusLine()); 1343 get_runner.response_info()->headers->GetStatusLine());
1333 1344
1334 EXPECT_EQ(0, get_runner.parser()->received_bytes()); 1345 EXPECT_EQ(0, get_runner.parser()->received_bytes());
1335 int read_lengths[] = {response_size, 0}; 1346 int read_lengths[] = {kResponse.size(), 0};
1336 get_runner.ReadBody(response_size, read_lengths); 1347 get_runner.ReadBody(kResponse.size(), read_lengths);
1337 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); 1348 EXPECT_EQ(kResponse.size(),
1349 static_cast<size_t>(get_runner.parser()->received_bytes()));
1350 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9,
1351 get_runner.response_info()->connection_info);
1352 }
1353
1354 const std::string kShoutcastResponse = "ICY 200 blah\r\n\r\n";
1355 for (const auto& test_case : kTestCases) {
1356 SimpleGetRunner get_runner;
1357 get_runner.set_url(GURL(test_case.url));
1358 get_runner.set_http_09_on_non_default_ports_enabled(
1359 test_case.http_09_on_non_default_ports_enabled);
1360 get_runner.AddRead(kShoutcastResponse);
1361 get_runner.SetupParserAndSendRequest();
1362
1363 get_runner.ReadHeadersExpectingError(
1364 test_case.expected_shoutcast_header_error);
1365 if (test_case.expected_shoutcast_header_error != OK)
1366 continue;
1367
1368 ASSERT_TRUE(get_runner.response_info()->headers);
1369 EXPECT_EQ("HTTP/0.9 200 OK",
1370 get_runner.response_info()->headers->GetStatusLine());
1371
1372 EXPECT_EQ(0, get_runner.parser()->received_bytes());
1373 int read_lengths[] = {kShoutcastResponse.size(), 0};
1374 get_runner.ReadBody(kShoutcastResponse.size(), read_lengths);
1375 EXPECT_EQ(kShoutcastResponse.size(),
1376 static_cast<size_t>(get_runner.parser()->received_bytes()));
1338 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9, 1377 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP0_9,
1339 get_runner.response_info()->connection_info); 1378 get_runner.response_info()->connection_info);
1340 } 1379 }
1341 } 1380 }
1342 1381
1382 // Make sure that Shoutcast is recognized when receiving one byte at a time.
1383 TEST(HttpStreamParser, ShoutcastSingleByteReads) {
1384 SimpleGetRunner get_runner;
1385 get_runner.set_url(GURL("http://foo.com:8080/"));
1386 get_runner.set_http_09_on_non_default_ports_enabled(false);
1387 get_runner.AddRead("i");
1388 get_runner.AddRead("c");
1389 get_runner.AddRead("Y");
1390 // Needed because HttpStreamParser::Read returns ERR_CONNECTION_CLOSED on
1391 // small response headers, which HttpNetworkTransaction replaces with net::OK.
1392 // TODO(mmenke): Can we just change that behavior?
1393 get_runner.AddRead(" Extra stuff");
1394 get_runner.SetupParserAndSendRequest();
1395
1396 get_runner.ReadHeadersExpectingError(OK);
1397 EXPECT_EQ("HTTP/0.9 200 OK",
1398 get_runner.response_info()->headers->GetStatusLine());
1399 }
1400
1401 // Make sure that Shoutcast is recognized when receiving any string starting
1402 // with "ICY", regardless of capitalization, and without a space following it
1403 // (The latter behavior is just to match HTTP detection).
1404 TEST(HttpStreamParser, ShoutcastWeirdHeader) {
1405 SimpleGetRunner get_runner;
1406 get_runner.set_url(GURL("http://foo.com:8080/"));
1407 get_runner.set_http_09_on_non_default_ports_enabled(false);
1408 get_runner.AddRead("iCyCreamSundae");
1409 get_runner.SetupParserAndSendRequest();
1410
1411 get_runner.ReadHeadersExpectingError(OK);
1412 EXPECT_EQ("HTTP/0.9 200 OK",
1413 get_runner.response_info()->headers->GetStatusLine());
1414 }
1415
1343 // Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird 1416 // Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird
1344 // port. 1417 // port.
1345 TEST(HttpStreamParser, Http09TruncatedHeaderPortTest) { 1418 TEST(HttpStreamParser, Http09TruncatedHeaderPortTest) {
1346 SimpleGetRunner get_runner; 1419 SimpleGetRunner get_runner;
1347 get_runner.set_url(GURL("http://foo.com:8080/")); 1420 get_runner.set_url(GURL("http://foo.com:8080/"));
1348 std::string response = "HT"; 1421 std::string response = "HT";
1349 get_runner.AddRead(response); 1422 get_runner.AddRead(response);
1350 get_runner.SetupParserAndSendRequest(); 1423 get_runner.SetupParserAndSendRequest();
1351 1424
1352 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE); 1425 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 ASSERT_EQ(kBodySize, parser.ReadResponseBody( 1689 ASSERT_EQ(kBodySize, parser.ReadResponseBody(
1617 body_buffer.get(), kBodySize, callback.callback())); 1690 body_buffer.get(), kBodySize, callback.callback()));
1618 1691
1619 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); 1692 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes());
1620 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); 1693 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes());
1621 } 1694 }
1622 1695
1623 } // namespace 1696 } // namespace
1624 1697
1625 } // namespace net 1698 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_stream_parser.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698