OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
6 | 6 |
7 #include <math.h> // ceil | 7 #include <math.h> // ceil |
8 #include <stdarg.h> | 8 #include <stdarg.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 12750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12761 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( | 12761 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( |
12762 HostPortPair("www.example.com", 443), &client_cert, | 12762 HostPortPair("www.example.com", 443), &client_cert, |
12763 &client_private_key)); | 12763 &client_private_key)); |
12764 } | 12764 } |
12765 } | 12765 } |
12766 | 12766 |
12767 TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) { | 12767 TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) { |
12768 // Set up a special HttpNetworkSession with a MockCachingHostResolver. | 12768 // Set up a special HttpNetworkSession with a MockCachingHostResolver. |
12769 session_deps_.host_resolver.reset(new MockCachingHostResolver()); | 12769 session_deps_.host_resolver.reset(new MockCachingHostResolver()); |
12770 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); | 12770 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); |
12771 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); | |
12772 pool_peer.DisableDomainAuthenticationVerification(); | |
12773 | 12771 |
12774 SSLSocketDataProvider ssl(ASYNC, OK); | 12772 SSLSocketDataProvider ssl(ASYNC, OK); |
12775 ssl.next_proto = kProtoHTTP2; | 12773 ssl.next_proto = kProtoHTTP2; |
| 12774 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); |
| 12775 ASSERT_TRUE(ssl.cert); |
12776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); | 12776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
12777 | 12777 |
12778 SpdySerializedFrame host1_req( | 12778 SpdySerializedFrame host1_req( |
12779 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); | 12779 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); |
12780 spdy_util_.UpdateWithStreamDestruction(1); | 12780 spdy_util_.UpdateWithStreamDestruction(1); |
12781 SpdySerializedFrame host2_req( | 12781 SpdySerializedFrame host2_req( |
12782 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST)); | 12782 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST)); |
12783 MockWrite spdy_writes[] = { | 12783 MockWrite spdy_writes[] = { |
12784 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), | 12784 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), |
12785 }; | 12785 }; |
12786 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); | 12786 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); |
12787 SpdySerializedFrame host1_resp_body( | 12787 SpdySerializedFrame host1_resp_body( |
12788 spdy_util_.ConstructSpdyDataFrame(1, true)); | 12788 spdy_util_.ConstructSpdyDataFrame(1, true)); |
12789 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); | 12789 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); |
12790 SpdySerializedFrame host2_resp_body( | 12790 SpdySerializedFrame host2_resp_body( |
12791 spdy_util_.ConstructSpdyDataFrame(3, true)); | 12791 spdy_util_.ConstructSpdyDataFrame(3, true)); |
12792 MockRead spdy_reads[] = { | 12792 MockRead spdy_reads[] = { |
(...skipping 21 matching lines...) Expand all Loading... |
12814 | 12814 |
12815 const HttpResponseInfo* response = trans1.GetResponseInfo(); | 12815 const HttpResponseInfo* response = trans1.GetResponseInfo(); |
12816 ASSERT_TRUE(response); | 12816 ASSERT_TRUE(response); |
12817 ASSERT_TRUE(response->headers); | 12817 ASSERT_TRUE(response->headers); |
12818 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); | 12818 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); |
12819 | 12819 |
12820 std::string response_data; | 12820 std::string response_data; |
12821 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); | 12821 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); |
12822 EXPECT_EQ("hello!", response_data); | 12822 EXPECT_EQ("hello!", response_data); |
12823 | 12823 |
12824 // Preload www.gmail.com into HostCache. | 12824 // Preload mail.example.com into HostCache. |
12825 HostPortPair host_port("www.gmail.com", 443); | 12825 HostPortPair host_port("mail.example.com", 443); |
12826 HostResolver::RequestInfo resolve_info(host_port); | 12826 HostResolver::RequestInfo resolve_info(host_port); |
12827 AddressList ignored; | 12827 AddressList ignored; |
12828 std::unique_ptr<HostResolver::Request> request; | 12828 std::unique_ptr<HostResolver::Request> request; |
12829 rv = session_deps_.host_resolver->Resolve(resolve_info, DEFAULT_PRIORITY, | 12829 rv = session_deps_.host_resolver->Resolve(resolve_info, DEFAULT_PRIORITY, |
12830 &ignored, callback.callback(), | 12830 &ignored, callback.callback(), |
12831 &request, NetLogWithSource()); | 12831 &request, NetLogWithSource()); |
12832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); | 12832 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); |
12833 rv = callback.WaitForResult(); | 12833 rv = callback.WaitForResult(); |
12834 EXPECT_THAT(rv, IsOk()); | 12834 EXPECT_THAT(rv, IsOk()); |
12835 | 12835 |
12836 HttpRequestInfo request2; | 12836 HttpRequestInfo request2; |
12837 request2.method = "GET"; | 12837 request2.method = "GET"; |
12838 request2.url = GURL("https://www.gmail.com/"); | 12838 request2.url = GURL("https://mail.example.com/"); |
12839 request2.load_flags = 0; | 12839 request2.load_flags = 0; |
12840 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); | 12840 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); |
12841 | 12841 |
12842 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); | 12842 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); |
12843 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); | 12843 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); |
12844 EXPECT_THAT(callback.WaitForResult(), IsOk()); | 12844 EXPECT_THAT(callback.WaitForResult(), IsOk()); |
12845 | 12845 |
12846 response = trans2.GetResponseInfo(); | 12846 response = trans2.GetResponseInfo(); |
12847 ASSERT_TRUE(response); | 12847 ASSERT_TRUE(response); |
12848 ASSERT_TRUE(response->headers); | 12848 ASSERT_TRUE(response->headers); |
12849 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); | 12849 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); |
12850 EXPECT_TRUE(response->was_fetched_via_spdy); | 12850 EXPECT_TRUE(response->was_fetched_via_spdy); |
12851 EXPECT_TRUE(response->was_alpn_negotiated); | 12851 EXPECT_TRUE(response->was_alpn_negotiated); |
12852 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk()); | 12852 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk()); |
12853 EXPECT_EQ("hello!", response_data); | 12853 EXPECT_EQ("hello!", response_data); |
12854 } | 12854 } |
12855 | 12855 |
12856 TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) { | 12856 TEST_F(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) { |
12857 // Set up a special HttpNetworkSession with a MockCachingHostResolver. | 12857 // Set up a special HttpNetworkSession with a MockCachingHostResolver. |
12858 session_deps_.host_resolver.reset(new MockCachingHostResolver()); | 12858 session_deps_.host_resolver.reset(new MockCachingHostResolver()); |
12859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); | 12859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); |
12860 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); | |
12861 pool_peer.DisableDomainAuthenticationVerification(); | |
12862 | 12860 |
12863 SSLSocketDataProvider ssl(ASYNC, OK); | 12861 SSLSocketDataProvider ssl(ASYNC, OK); |
12864 ssl.next_proto = kProtoHTTP2; | 12862 ssl.next_proto = kProtoHTTP2; |
| 12863 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); |
| 12864 ASSERT_TRUE(ssl.cert); |
12865 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); | 12865 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
12866 | 12866 |
12867 SpdySerializedFrame host1_req( | 12867 SpdySerializedFrame host1_req( |
12868 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); | 12868 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); |
12869 spdy_util_.UpdateWithStreamDestruction(1); | 12869 spdy_util_.UpdateWithStreamDestruction(1); |
12870 SpdySerializedFrame host2_req( | 12870 SpdySerializedFrame host2_req( |
12871 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST)); | 12871 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST)); |
12872 MockWrite spdy_writes[] = { | 12872 MockWrite spdy_writes[] = { |
12873 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), | 12873 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), |
12874 }; | 12874 }; |
12875 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); | 12875 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); |
12876 SpdySerializedFrame host1_resp_body( | 12876 SpdySerializedFrame host1_resp_body( |
12877 spdy_util_.ConstructSpdyDataFrame(1, true)); | 12877 spdy_util_.ConstructSpdyDataFrame(1, true)); |
12878 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); | 12878 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); |
12879 SpdySerializedFrame host2_resp_body( | 12879 SpdySerializedFrame host2_resp_body( |
12880 spdy_util_.ConstructSpdyDataFrame(3, true)); | 12880 spdy_util_.ConstructSpdyDataFrame(3, true)); |
12881 MockRead spdy_reads[] = { | 12881 MockRead spdy_reads[] = { |
(...skipping 23 matching lines...) Expand all Loading... |
12905 ASSERT_TRUE(response); | 12905 ASSERT_TRUE(response); |
12906 ASSERT_TRUE(response->headers); | 12906 ASSERT_TRUE(response->headers); |
12907 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); | 12907 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); |
12908 | 12908 |
12909 std::string response_data; | 12909 std::string response_data; |
12910 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); | 12910 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); |
12911 EXPECT_EQ("hello!", response_data); | 12911 EXPECT_EQ("hello!", response_data); |
12912 | 12912 |
12913 HttpRequestInfo request2; | 12913 HttpRequestInfo request2; |
12914 request2.method = "GET"; | 12914 request2.method = "GET"; |
12915 request2.url = GURL("https://www.gmail.com/"); | 12915 request2.url = GURL("https://mail.example.com/"); |
12916 request2.load_flags = 0; | 12916 request2.load_flags = 0; |
12917 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); | 12917 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); |
12918 | 12918 |
12919 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); | 12919 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); |
12920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); | 12920 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); |
12921 EXPECT_THAT(callback.WaitForResult(), IsOk()); | 12921 EXPECT_THAT(callback.WaitForResult(), IsOk()); |
12922 | 12922 |
12923 response = trans2.GetResponseInfo(); | 12923 response = trans2.GetResponseInfo(); |
12924 ASSERT_TRUE(response); | 12924 ASSERT_TRUE(response); |
12925 ASSERT_TRUE(response->headers); | 12925 ASSERT_TRUE(response->headers); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12963 } | 12963 } |
12964 | 12964 |
12965 private: | 12965 private: |
12966 MockCachingHostResolver host_resolver_; | 12966 MockCachingHostResolver host_resolver_; |
12967 const HostPortPair host_port_; | 12967 const HostPortPair host_port_; |
12968 }; | 12968 }; |
12969 | 12969 |
12970 TEST_F(HttpNetworkTransactionTest, | 12970 TEST_F(HttpNetworkTransactionTest, |
12971 UseIPConnectionPoolingWithHostCacheExpiration) { | 12971 UseIPConnectionPoolingWithHostCacheExpiration) { |
12972 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver. | 12972 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver. |
12973 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443)); | 12973 OneTimeCachingHostResolver host_resolver( |
| 12974 HostPortPair("mail.example.com", 443)); |
12974 HttpNetworkSession::Params params = | 12975 HttpNetworkSession::Params params = |
12975 SpdySessionDependencies::CreateSessionParams(&session_deps_); | 12976 SpdySessionDependencies::CreateSessionParams(&session_deps_); |
12976 params.host_resolver = &host_resolver; | 12977 params.host_resolver = &host_resolver; |
12977 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); | 12978 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); |
12978 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); | |
12979 pool_peer.DisableDomainAuthenticationVerification(); | |
12980 | 12979 |
12981 SSLSocketDataProvider ssl(ASYNC, OK); | 12980 SSLSocketDataProvider ssl(ASYNC, OK); |
12982 ssl.next_proto = kProtoHTTP2; | 12981 ssl.next_proto = kProtoHTTP2; |
| 12982 ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); |
| 12983 ASSERT_TRUE(ssl.cert); |
12983 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); | 12984 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
12984 | 12985 |
12985 SpdySerializedFrame host1_req( | 12986 SpdySerializedFrame host1_req( |
12986 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); | 12987 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); |
12987 spdy_util_.UpdateWithStreamDestruction(1); | 12988 spdy_util_.UpdateWithStreamDestruction(1); |
12988 SpdySerializedFrame host2_req( | 12989 SpdySerializedFrame host2_req( |
12989 spdy_util_.ConstructSpdyGet("https://www.gmail.com", 3, LOWEST)); | 12990 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST)); |
12990 MockWrite spdy_writes[] = { | 12991 MockWrite spdy_writes[] = { |
12991 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), | 12992 CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), |
12992 }; | 12993 }; |
12993 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); | 12994 SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); |
12994 SpdySerializedFrame host1_resp_body( | 12995 SpdySerializedFrame host1_resp_body( |
12995 spdy_util_.ConstructSpdyDataFrame(1, true)); | 12996 spdy_util_.ConstructSpdyDataFrame(1, true)); |
12996 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); | 12997 SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); |
12997 SpdySerializedFrame host2_resp_body( | 12998 SpdySerializedFrame host2_resp_body( |
12998 spdy_util_.ConstructSpdyDataFrame(3, true)); | 12999 spdy_util_.ConstructSpdyDataFrame(3, true)); |
12999 MockRead spdy_reads[] = { | 13000 MockRead spdy_reads[] = { |
(...skipping 22 matching lines...) Expand all Loading... |
13022 const HttpResponseInfo* response = trans1.GetResponseInfo(); | 13023 const HttpResponseInfo* response = trans1.GetResponseInfo(); |
13023 ASSERT_TRUE(response); | 13024 ASSERT_TRUE(response); |
13024 ASSERT_TRUE(response->headers); | 13025 ASSERT_TRUE(response->headers); |
13025 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); | 13026 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); |
13026 | 13027 |
13027 std::string response_data; | 13028 std::string response_data; |
13028 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); | 13029 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); |
13029 EXPECT_EQ("hello!", response_data); | 13030 EXPECT_EQ("hello!", response_data); |
13030 | 13031 |
13031 // Preload cache entries into HostCache. | 13032 // Preload cache entries into HostCache. |
13032 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443)); | 13033 HostResolver::RequestInfo resolve_info(HostPortPair("mail.example.com", 443)); |
13033 AddressList ignored; | 13034 AddressList ignored; |
13034 std::unique_ptr<HostResolver::Request> request; | 13035 std::unique_ptr<HostResolver::Request> request; |
13035 rv = host_resolver.Resolve(resolve_info, DEFAULT_PRIORITY, &ignored, | 13036 rv = host_resolver.Resolve(resolve_info, DEFAULT_PRIORITY, &ignored, |
13036 callback.callback(), &request, NetLogWithSource()); | 13037 callback.callback(), &request, NetLogWithSource()); |
13037 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); | 13038 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); |
13038 rv = callback.WaitForResult(); | 13039 rv = callback.WaitForResult(); |
13039 EXPECT_THAT(rv, IsOk()); | 13040 EXPECT_THAT(rv, IsOk()); |
13040 | 13041 |
13041 HttpRequestInfo request2; | 13042 HttpRequestInfo request2; |
13042 request2.method = "GET"; | 13043 request2.method = "GET"; |
13043 request2.url = GURL("https://www.gmail.com/"); | 13044 request2.url = GURL("https://mail.example.com/"); |
13044 request2.load_flags = 0; | 13045 request2.load_flags = 0; |
13045 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); | 13046 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); |
13046 | 13047 |
13047 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); | 13048 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); |
13048 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); | 13049 EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); |
13049 EXPECT_THAT(callback.WaitForResult(), IsOk()); | 13050 EXPECT_THAT(callback.WaitForResult(), IsOk()); |
13050 | 13051 |
13051 response = trans2.GetResponseInfo(); | 13052 response = trans2.GetResponseInfo(); |
13052 ASSERT_TRUE(response); | 13053 ASSERT_TRUE(response); |
13053 ASSERT_TRUE(response->headers); | 13054 ASSERT_TRUE(response->headers); |
(...skipping 2524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15578 base::RunLoop().RunUntilIdle(); | 15579 base::RunLoop().RunUntilIdle(); |
15579 | 15580 |
15580 EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy); | 15581 EXPECT_TRUE(trans.GetResponseInfo()->was_fetched_via_spdy); |
15581 HttpRequestHeaders headers; | 15582 HttpRequestHeaders headers; |
15582 ASSERT_TRUE(trans.GetFullRequestHeaders(&headers)); | 15583 ASSERT_TRUE(trans.GetFullRequestHeaders(&headers)); |
15583 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding)); | 15584 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding)); |
15584 } | 15585 } |
15585 #endif // !defined(OS_IOS) | 15586 #endif // !defined(OS_IOS) |
15586 | 15587 |
15587 } // namespace net | 15588 } // namespace net |
OLD | NEW |