socks_connect_job_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. // Copyright 2019 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. #include "net/socket/socks_connect_job.h"
  5. #include "base/callback.h"
  6. #include "base/containers/flat_set.h"
  7. #include "base/containers/span.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/time/time.h"
  11. #include "build/build_config.h"
  12. #include "net/base/load_states.h"
  13. #include "net/base/load_timing_info.h"
  14. #include "net/base/load_timing_info_test_util.h"
  15. #include "net/base/net_errors.h"
  16. #include "net/base/network_isolation_key.h"
  17. #include "net/dns/mock_host_resolver.h"
  18. #include "net/dns/public/secure_dns_policy.h"
  19. #include "net/log/net_log.h"
  20. #include "net/socket/client_socket_factory.h"
  21. #include "net/socket/client_socket_handle.h"
  22. #include "net/socket/connect_job_test_util.h"
  23. #include "net/socket/socket_tag.h"
  24. #include "net/socket/socket_test_util.h"
  25. #include "net/socket/socks_connect_job.h"
  26. #include "net/socket/transport_client_socket_pool_test_util.h"
  27. #include "net/socket/transport_connect_job.h"
  28. #include "net/test/gtest_util.h"
  29. #include "net/test/test_with_task_environment.h"
  30. #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
  31. #include "testing/gmock/include/gmock/gmock.h"
  32. #include "testing/gtest/include/gtest/gtest.h"
  33. namespace net {
  34. namespace {
  35. const char kProxyHostName[] = "proxy.test";
  36. const int kProxyPort = 4321;
  37. constexpr base::TimeDelta kTinyTime = base::Microseconds(1);
  38. class SOCKSConnectJobTest : public testing::Test, public WithTaskEnvironment {
  39. public:
  40. enum class SOCKSVersion {
  41. V4,
  42. V5,
  43. };
  44. SOCKSConnectJobTest()
  45. : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
  46. common_connect_job_params_(
  47. &client_socket_factory_,
  48. &host_resolver_,
  49. nullptr /* http_auth_cache */,
  50. nullptr /* http_auth_handler_factory */,
  51. nullptr /* spdy_session_pool */,
  52. nullptr /* quic_supported_versions */,
  53. nullptr /* quic_stream_factory */,
  54. nullptr /* proxy_delegate */,
  55. nullptr /* http_user_agent_settings */,
  56. nullptr /* ssl_client_context */,
  57. nullptr /* socket_performance_watcher_factory */,
  58. nullptr /* network_quality_estimator */,
  59. NetLog::Get(),
  60. nullptr /* websocket_endpoint_lock_manager */) {}
  61. ~SOCKSConnectJobTest() override = default;
  62. static scoped_refptr<SOCKSSocketParams> CreateSOCKSParams(
  63. SOCKSVersion socks_version,
  64. SecureDnsPolicy secure_dns_policy = SecureDnsPolicy::kAllow) {
  65. return base::MakeRefCounted<SOCKSSocketParams>(
  66. base::MakeRefCounted<TransportSocketParams>(
  67. HostPortPair(kProxyHostName, kProxyPort), NetworkIsolationKey(),
  68. secure_dns_policy, OnHostResolutionCallback(),
  69. /*supported_alpns=*/base::flat_set<std::string>()),
  70. socks_version == SOCKSVersion::V5,
  71. socks_version == SOCKSVersion::V4
  72. ? HostPortPair(kSOCKS4TestHost, kSOCKS4TestPort)
  73. : HostPortPair(kSOCKS5TestHost, kSOCKS5TestPort),
  74. NetworkIsolationKey(), TRAFFIC_ANNOTATION_FOR_TESTS);
  75. }
  76. protected:
  77. MockHostResolver host_resolver_{/*default_result=*/MockHostResolverBase::
  78. RuleResolver::GetLocalhostResult()};
  79. MockTaggingClientSocketFactory client_socket_factory_;
  80. const CommonConnectJobParams common_connect_job_params_;
  81. };
  82. TEST_F(SOCKSConnectJobTest, HostResolutionFailure) {
  83. host_resolver_.rules()->AddSimulatedTimeoutFailure(kProxyHostName);
  84. for (bool failure_synchronous : {false, true}) {
  85. host_resolver_.set_synchronous_mode(failure_synchronous);
  86. TestConnectJobDelegate test_delegate;
  87. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  88. &common_connect_job_params_,
  89. CreateSOCKSParams(SOCKSVersion::V5),
  90. &test_delegate, nullptr /* net_log */);
  91. test_delegate.StartJobExpectingResult(
  92. &socks_connect_job, ERR_PROXY_CONNECTION_FAILED, failure_synchronous);
  93. EXPECT_THAT(socks_connect_job.GetResolveErrorInfo().error,
  94. test::IsError(ERR_DNS_TIMED_OUT));
  95. }
  96. }
  97. TEST_F(SOCKSConnectJobTest, HostResolutionFailureSOCKS4Endpoint) {
  98. const char hostname[] = "google.com";
  99. host_resolver_.rules()->AddSimulatedTimeoutFailure(hostname);
  100. for (bool failure_synchronous : {false, true}) {
  101. host_resolver_.set_synchronous_mode(failure_synchronous);
  102. SequencedSocketData sequenced_socket_data{base::span<MockRead>(),
  103. base::span<MockWrite>()};
  104. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  105. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  106. scoped_refptr<SOCKSSocketParams> socket_params =
  107. base::MakeRefCounted<SOCKSSocketParams>(
  108. base::MakeRefCounted<TransportSocketParams>(
  109. HostPortPair(kProxyHostName, kProxyPort), NetworkIsolationKey(),
  110. SecureDnsPolicy::kAllow, OnHostResolutionCallback(),
  111. /*supported_alpns=*/base::flat_set<std::string>()),
  112. false /* socks_v5 */, HostPortPair(hostname, kSOCKS4TestPort),
  113. NetworkIsolationKey(), TRAFFIC_ANNOTATION_FOR_TESTS);
  114. TestConnectJobDelegate test_delegate;
  115. SOCKSConnectJob socks_connect_job(
  116. DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
  117. socket_params, &test_delegate, nullptr /* net_log */);
  118. test_delegate.StartJobExpectingResult(
  119. &socks_connect_job, ERR_NAME_NOT_RESOLVED, failure_synchronous);
  120. EXPECT_THAT(socks_connect_job.GetResolveErrorInfo().error,
  121. test::IsError(ERR_DNS_TIMED_OUT));
  122. }
  123. }
  124. TEST_F(SOCKSConnectJobTest, HandshakeError) {
  125. for (bool host_resolution_synchronous : {false, true}) {
  126. for (bool write_failure_synchronous : {false, true}) {
  127. host_resolver_.set_synchronous_mode(host_resolution_synchronous);
  128. // No need to distinguish which part of the handshake fails. Those details
  129. // are all handled at the StreamSocket layer, not the SOCKSConnectJob.
  130. MockWrite writes[] = {
  131. MockWrite(write_failure_synchronous ? SYNCHRONOUS : ASYNC,
  132. ERR_UNEXPECTED, 0),
  133. };
  134. SequencedSocketData sequenced_socket_data(base::span<MockRead>(), writes);
  135. // Host resolution is used to switch between sync and async connection
  136. // behavior. The SOCKS layer can't distinguish between sync and async host
  137. // resolution vs sync and async connection establishment, so just always
  138. // make connection establishment synchroonous.
  139. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  140. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  141. TestConnectJobDelegate test_delegate;
  142. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  143. &common_connect_job_params_,
  144. CreateSOCKSParams(SOCKSVersion::V5),
  145. &test_delegate, nullptr /* net_log */);
  146. test_delegate.StartJobExpectingResult(
  147. &socks_connect_job, ERR_UNEXPECTED,
  148. host_resolution_synchronous && write_failure_synchronous);
  149. }
  150. }
  151. }
  152. TEST_F(SOCKSConnectJobTest, SOCKS4) {
  153. for (bool host_resolution_synchronous : {false, true}) {
  154. for (bool read_and_writes_synchronous : {true}) {
  155. host_resolver_.set_synchronous_mode(host_resolution_synchronous);
  156. MockWrite writes[] = {
  157. MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
  158. kSOCKS4OkRequestLocalHostPort80Length, 0),
  159. };
  160. MockRead reads[] = {
  161. MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength, 1),
  162. };
  163. SequencedSocketData sequenced_socket_data(reads, writes);
  164. // Host resolution is used to switch between sync and async connection
  165. // behavior. The SOCKS layer can't distinguish between sync and async host
  166. // resolution vs sync and async connection establishment, so just always
  167. // make connection establishment synchroonous.
  168. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  169. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  170. TestConnectJobDelegate test_delegate;
  171. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  172. &common_connect_job_params_,
  173. CreateSOCKSParams(SOCKSVersion::V4),
  174. &test_delegate, nullptr /* net_log */);
  175. test_delegate.StartJobExpectingResult(
  176. &socks_connect_job, OK,
  177. host_resolution_synchronous && read_and_writes_synchronous);
  178. // Proxies should not set any DNS aliases.
  179. EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
  180. }
  181. }
  182. }
  183. TEST_F(SOCKSConnectJobTest, SOCKS5) {
  184. for (bool host_resolution_synchronous : {false, true}) {
  185. for (bool read_and_writes_synchronous : {true}) {
  186. host_resolver_.set_synchronous_mode(host_resolution_synchronous);
  187. MockWrite writes[] = {
  188. MockWrite(SYNCHRONOUS, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength,
  189. 0),
  190. MockWrite(SYNCHRONOUS, kSOCKS5OkRequest, kSOCKS5OkRequestLength, 2),
  191. };
  192. MockRead reads[] = {
  193. MockRead(SYNCHRONOUS, kSOCKS5GreetResponse,
  194. kSOCKS5GreetResponseLength, 1),
  195. MockRead(SYNCHRONOUS, kSOCKS5OkResponse, kSOCKS5OkResponseLength, 3),
  196. };
  197. SequencedSocketData sequenced_socket_data(reads, writes);
  198. // Host resolution is used to switch between sync and async connection
  199. // behavior. The SOCKS layer can't distinguish between sync and async host
  200. // resolution vs sync and async connection establishment, so just always
  201. // make connection establishment synchroonous.
  202. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  203. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  204. TestConnectJobDelegate test_delegate;
  205. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  206. &common_connect_job_params_,
  207. CreateSOCKSParams(SOCKSVersion::V5),
  208. &test_delegate, nullptr /* net_log */);
  209. test_delegate.StartJobExpectingResult(
  210. &socks_connect_job, OK,
  211. host_resolution_synchronous && read_and_writes_synchronous);
  212. // Proxies should not set any DNS aliases.
  213. EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
  214. }
  215. }
  216. }
  217. TEST_F(SOCKSConnectJobTest, HasEstablishedConnection) {
  218. host_resolver_.set_ondemand_mode(true);
  219. MockWrite writes[] = {
  220. MockWrite(ASYNC, kSOCKS4OkRequestLocalHostPort80,
  221. kSOCKS4OkRequestLocalHostPort80Length, 0),
  222. };
  223. MockRead reads[] = {
  224. MockRead(ASYNC, ERR_IO_PENDING, 1),
  225. MockRead(ASYNC, kSOCKS4OkReply, kSOCKS4OkReplyLength, 2),
  226. };
  227. SequencedSocketData sequenced_socket_data(reads, writes);
  228. sequenced_socket_data.set_connect_data(MockConnect(ASYNC, OK));
  229. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  230. TestConnectJobDelegate test_delegate;
  231. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  232. &common_connect_job_params_,
  233. CreateSOCKSParams(SOCKSVersion::V4),
  234. &test_delegate, nullptr /* net_log */);
  235. socks_connect_job.Connect();
  236. EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, socks_connect_job.GetLoadState());
  237. EXPECT_FALSE(socks_connect_job.HasEstablishedConnection());
  238. host_resolver_.ResolveNow(1);
  239. EXPECT_EQ(LOAD_STATE_CONNECTING, socks_connect_job.GetLoadState());
  240. EXPECT_FALSE(socks_connect_job.HasEstablishedConnection());
  241. sequenced_socket_data.RunUntilPaused();
  242. // "LOAD_STATE_CONNECTING" is also returned when negotiating a SOCKS
  243. // connection.
  244. EXPECT_EQ(LOAD_STATE_CONNECTING, socks_connect_job.GetLoadState());
  245. EXPECT_TRUE(socks_connect_job.HasEstablishedConnection());
  246. EXPECT_FALSE(test_delegate.has_result());
  247. sequenced_socket_data.Resume();
  248. EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
  249. EXPECT_TRUE(test_delegate.has_result());
  250. }
  251. // Check that TransportConnectJob's timeout is respected for the nested
  252. // TransportConnectJob.
  253. TEST_F(SOCKSConnectJobTest, TimeoutDuringDnsResolution) {
  254. // Set HostResolver to hang.
  255. host_resolver_.set_ondemand_mode(true);
  256. TestConnectJobDelegate test_delegate;
  257. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  258. &common_connect_job_params_,
  259. CreateSOCKSParams(SOCKSVersion::V5),
  260. &test_delegate, nullptr /* net_log */);
  261. socks_connect_job.Connect();
  262. // Just before the TransportConnectJob's timeout, nothing should have
  263. // happened.
  264. FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
  265. EXPECT_TRUE(host_resolver_.has_pending_requests());
  266. EXPECT_FALSE(test_delegate.has_result());
  267. // Wait for exactly the TransportConnectJob's timeout to have passed. The Job
  268. // should time out.
  269. FastForwardBy(kTinyTime);
  270. EXPECT_TRUE(test_delegate.has_result());
  271. EXPECT_THAT(test_delegate.WaitForResult(),
  272. test::IsError(ERR_PROXY_CONNECTION_FAILED));
  273. }
  274. // Check that SOCKSConnectJob's timeout is respected for the handshake phase.
  275. TEST_F(SOCKSConnectJobTest, TimeoutDuringHandshake) {
  276. host_resolver_.set_ondemand_mode(true);
  277. MockWrite writes[] = {
  278. MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 0),
  279. };
  280. SequencedSocketData sequenced_socket_data(base::span<MockRead>(), writes);
  281. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  282. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  283. TestConnectJobDelegate test_delegate;
  284. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  285. &common_connect_job_params_,
  286. CreateSOCKSParams(SOCKSVersion::V5),
  287. &test_delegate, nullptr /* net_log */);
  288. socks_connect_job.Connect();
  289. // Just before the TransportConnectJob's timeout, nothing should have
  290. // happened.
  291. FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
  292. EXPECT_FALSE(test_delegate.has_result());
  293. EXPECT_TRUE(host_resolver_.has_pending_requests());
  294. // DNS resolution completes, and the socket connects. The request should not
  295. // time out, even after the TransportConnectJob's timeout passes. The
  296. // SOCKSConnectJob's handshake timer should also be started.
  297. host_resolver_.ResolveAllPending();
  298. // Waiting until just before the SOCKS handshake times out. There should cause
  299. // no observable change in the SOCKSConnectJob's status.
  300. FastForwardBy(SOCKSConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
  301. EXPECT_FALSE(test_delegate.has_result());
  302. // Wait for exactly the SOCKSConnectJob's handshake timeout has fully elapsed.
  303. // The Job should time out.
  304. FastForwardBy(kTinyTime);
  305. EXPECT_FALSE(host_resolver_.has_pending_requests());
  306. EXPECT_TRUE(test_delegate.has_result());
  307. EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
  308. }
  309. // Check initial priority is passed to the HostResolver, and priority can be
  310. // modified.
  311. TEST_F(SOCKSConnectJobTest, Priority) {
  312. host_resolver_.set_ondemand_mode(true);
  313. for (int initial_priority = MINIMUM_PRIORITY;
  314. initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
  315. for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
  316. ++new_priority) {
  317. // Don't try changing priority to itself, as APIs may not allow that.
  318. if (new_priority == initial_priority)
  319. continue;
  320. TestConnectJobDelegate test_delegate;
  321. SOCKSConnectJob socks_connect_job(
  322. static_cast<RequestPriority>(initial_priority), SocketTag(),
  323. &common_connect_job_params_, CreateSOCKSParams(SOCKSVersion::V4),
  324. &test_delegate, nullptr /* net_log */);
  325. ASSERT_THAT(socks_connect_job.Connect(), test::IsError(ERR_IO_PENDING));
  326. ASSERT_TRUE(host_resolver_.has_pending_requests());
  327. int request_id = host_resolver_.num_resolve();
  328. EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
  329. // Change priority.
  330. socks_connect_job.ChangePriority(
  331. static_cast<RequestPriority>(new_priority));
  332. EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
  333. // Restore initial priority.
  334. socks_connect_job.ChangePriority(
  335. static_cast<RequestPriority>(initial_priority));
  336. EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
  337. }
  338. }
  339. }
  340. TEST_F(SOCKSConnectJobTest, SecureDnsPolicy) {
  341. for (auto secure_dns_policy :
  342. {SecureDnsPolicy::kAllow, SecureDnsPolicy::kDisable}) {
  343. TestConnectJobDelegate test_delegate;
  344. SOCKSConnectJob socks_connect_job(
  345. DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
  346. CreateSOCKSParams(SOCKSVersion::V4, secure_dns_policy), &test_delegate,
  347. nullptr /* net_log */);
  348. ASSERT_THAT(socks_connect_job.Connect(), test::IsError(ERR_IO_PENDING));
  349. EXPECT_EQ(secure_dns_policy, host_resolver_.last_secure_dns_policy());
  350. }
  351. }
  352. TEST_F(SOCKSConnectJobTest, ConnectTiming) {
  353. host_resolver_.set_ondemand_mode(true);
  354. MockWrite writes[] = {
  355. MockWrite(ASYNC, ERR_IO_PENDING, 0),
  356. MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength, 1),
  357. MockWrite(SYNCHRONOUS, kSOCKS5OkRequest, kSOCKS5OkRequestLength, 3),
  358. };
  359. MockRead reads[] = {
  360. MockRead(SYNCHRONOUS, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength,
  361. 2),
  362. MockRead(SYNCHRONOUS, kSOCKS5OkResponse, kSOCKS5OkResponseLength, 4),
  363. };
  364. SequencedSocketData sequenced_socket_data(reads, writes);
  365. // Host resolution is used to switch between sync and async connection
  366. // behavior. The SOCKS layer can't distinguish between sync and async host
  367. // resolution vs sync and async connection establishment, so just always
  368. // make connection establishment synchroonous.
  369. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  370. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  371. TestConnectJobDelegate test_delegate;
  372. SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, SocketTag(),
  373. &common_connect_job_params_,
  374. CreateSOCKSParams(SOCKSVersion::V5),
  375. &test_delegate, nullptr /* net_log */);
  376. base::TimeTicks start = base::TimeTicks::Now();
  377. socks_connect_job.Connect();
  378. // DNS resolution completes after a short delay. The connection should be
  379. // immediately established as well. The first write to the socket stalls.
  380. FastForwardBy(kTinyTime);
  381. host_resolver_.ResolveAllPending();
  382. RunUntilIdle();
  383. // After another short delay, data is received from the server.
  384. FastForwardBy(kTinyTime);
  385. sequenced_socket_data.Resume();
  386. EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
  387. // Proxy name resolution is not considered resolving the host name for
  388. // ConnectionInfo. For SOCKS4, where the host name is also looked up via DNS,
  389. // the resolution time is not currently reported.
  390. EXPECT_EQ(base::TimeTicks(), socks_connect_job.connect_timing().dns_start);
  391. EXPECT_EQ(base::TimeTicks(), socks_connect_job.connect_timing().dns_end);
  392. // The "connect" time for socks proxies includes DNS resolution time.
  393. EXPECT_EQ(start, socks_connect_job.connect_timing().connect_start);
  394. EXPECT_EQ(start + 2 * kTinyTime,
  395. socks_connect_job.connect_timing().connect_end);
  396. // Since SSL was not negotiated, SSL times are null.
  397. EXPECT_EQ(base::TimeTicks(), socks_connect_job.connect_timing().ssl_start);
  398. EXPECT_EQ(base::TimeTicks(), socks_connect_job.connect_timing().ssl_end);
  399. }
  400. TEST_F(SOCKSConnectJobTest, CancelDuringDnsResolution) {
  401. // Set HostResolver to hang.
  402. host_resolver_.set_ondemand_mode(true);
  403. TestConnectJobDelegate test_delegate;
  404. std::unique_ptr<SOCKSConnectJob> socks_connect_job =
  405. std::make_unique<SOCKSConnectJob>(DEFAULT_PRIORITY, SocketTag(),
  406. &common_connect_job_params_,
  407. CreateSOCKSParams(SOCKSVersion::V5),
  408. &test_delegate, nullptr /* net_log */);
  409. socks_connect_job->Connect();
  410. EXPECT_TRUE(host_resolver_.has_pending_requests());
  411. socks_connect_job.reset();
  412. RunUntilIdle();
  413. EXPECT_FALSE(host_resolver_.has_pending_requests());
  414. EXPECT_FALSE(test_delegate.has_result());
  415. }
  416. TEST_F(SOCKSConnectJobTest, CancelDuringConnect) {
  417. host_resolver_.set_synchronous_mode(true);
  418. SequencedSocketData sequenced_socket_data{base::span<MockRead>(),
  419. base::span<MockWrite>()};
  420. sequenced_socket_data.set_connect_data(MockConnect(ASYNC, OK));
  421. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  422. TestConnectJobDelegate test_delegate;
  423. std::unique_ptr<SOCKSConnectJob> socks_connect_job =
  424. std::make_unique<SOCKSConnectJob>(DEFAULT_PRIORITY, SocketTag(),
  425. &common_connect_job_params_,
  426. CreateSOCKSParams(SOCKSVersion::V5),
  427. &test_delegate, nullptr /* net_log */);
  428. socks_connect_job->Connect();
  429. // Host resolution should resolve immediately. The ConnectJob should currently
  430. // be trying to connect.
  431. EXPECT_FALSE(host_resolver_.has_pending_requests());
  432. socks_connect_job.reset();
  433. RunUntilIdle();
  434. EXPECT_FALSE(test_delegate.has_result());
  435. // Socket should have been destroyed.
  436. EXPECT_FALSE(sequenced_socket_data.socket());
  437. }
  438. TEST_F(SOCKSConnectJobTest, CancelDuringHandshake) {
  439. host_resolver_.set_synchronous_mode(true);
  440. // Hang at start of handshake.
  441. MockWrite writes[] = {
  442. MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 0),
  443. };
  444. SequencedSocketData sequenced_socket_data(base::span<MockRead>(), writes);
  445. sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
  446. client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
  447. TestConnectJobDelegate test_delegate;
  448. std::unique_ptr<SOCKSConnectJob> socks_connect_job =
  449. std::make_unique<SOCKSConnectJob>(DEFAULT_PRIORITY, SocketTag(),
  450. &common_connect_job_params_,
  451. CreateSOCKSParams(SOCKSVersion::V5),
  452. &test_delegate, nullptr /* net_log */);
  453. socks_connect_job->Connect();
  454. // Host resolution should resolve immediately. The socket connecting, and the
  455. // ConnectJob should currently be trying to send the SOCKS handshake.
  456. EXPECT_FALSE(host_resolver_.has_pending_requests());
  457. socks_connect_job.reset();
  458. RunUntilIdle();
  459. EXPECT_FALSE(test_delegate.has_result());
  460. // Socket should have been destroyed.
  461. EXPECT_FALSE(sequenced_socket_data.socket());
  462. EXPECT_TRUE(sequenced_socket_data.AllWriteDataConsumed());
  463. }
  464. } // namespace
  465. } // namespace net