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 "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
6 | 6 |
7 #include "net/base/ip_endpoint.h" | 7 #include "net/base/ip_endpoint.h" |
8 #include "net/base/net_log_unittest.h" | 8 #include "net/base/net_log_unittest.h" |
9 #include "net/base/request_priority.h" | 9 #include "net/base/request_priority.h" |
10 #include "net/base/test_data_directory.h" | 10 #include "net/base/test_data_directory.h" |
(...skipping 1910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1921 | 1921 |
1922 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); | 1922 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
1923 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); | 1923 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); |
1924 | 1924 |
1925 data.RunFor(3); | 1925 data.RunFor(3); |
1926 | 1926 |
1927 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); | 1927 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
1928 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); | 1928 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); |
1929 } | 1929 } |
1930 | 1930 |
| 1931 // A delegate that drops any received data. |
| 1932 class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate { |
| 1933 public: |
| 1934 DropReceivedDataDelegate(const scoped_refptr<SpdyStream>& stream, |
| 1935 base::StringPiece data) |
| 1936 : StreamDelegateSendImmediate( |
| 1937 stream, scoped_ptr<SpdyHeaderBlock>(), data) {} |
| 1938 |
| 1939 virtual ~DropReceivedDataDelegate() {} |
| 1940 |
| 1941 // Drop any received data. |
| 1942 virtual int OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE { |
| 1943 return OK; |
| 1944 } |
| 1945 }; |
| 1946 |
| 1947 // Send data back and forth but use a delegate that drops its received |
| 1948 // data. The receive window should still increase to its original |
| 1949 // value, i.e. we shouldn't "leak" receive window bytes. |
| 1950 TEST_F(SpdySessionSpdy3Test, SessionFlowControlNoReceiveLeaks31) { |
| 1951 const char kStreamUrl[] = "http://www.google.com/"; |
| 1952 |
| 1953 session_deps_.enable_spdy_31 = true; |
| 1954 |
| 1955 const int32 msg_data_size = 100; |
| 1956 const std::string msg_data(msg_data_size, 'a'); |
| 1957 |
| 1958 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1959 |
| 1960 scoped_ptr<SpdyFrame> initial_window_update( |
| 1961 ConstructSpdyWindowUpdate( |
| 1962 kSessionFlowControlStreamId, |
| 1963 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); |
| 1964 scoped_ptr<SpdyFrame> req( |
| 1965 ConstructSpdyPost(kStreamUrl, 1, msg_data_size, MEDIUM, NULL, 0)); |
| 1966 scoped_ptr<SpdyFrame> msg( |
| 1967 ConstructSpdyBodyFrame(1, msg_data.data(), msg_data_size, false)); |
| 1968 MockWrite writes[] = { |
| 1969 CreateMockWrite(*initial_window_update, 0), |
| 1970 CreateMockWrite(*req, 1), |
| 1971 CreateMockWrite(*msg, 3), |
| 1972 }; |
| 1973 |
| 1974 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1975 scoped_ptr<SpdyFrame> echo( |
| 1976 ConstructSpdyBodyFrame(1, msg_data.data(), msg_data_size, false)); |
| 1977 scoped_ptr<SpdyFrame> window_update( |
| 1978 ConstructSpdyWindowUpdate( |
| 1979 kSessionFlowControlStreamId, msg_data_size)); |
| 1980 MockRead reads[] = { |
| 1981 CreateMockRead(*resp, 2), |
| 1982 CreateMockRead(*echo, 4), |
| 1983 MockRead(ASYNC, 0, 5) // EOF |
| 1984 }; |
| 1985 |
| 1986 // Create SpdySession and SpdyStream and send the request. |
| 1987 DeterministicSocketData data(reads, arraysize(reads), |
| 1988 writes, arraysize(writes)); |
| 1989 data.set_connect_data(connect_data); |
| 1990 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1991 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1992 |
| 1993 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1994 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1995 |
| 1996 CreateDeterministicNetworkSession(); |
| 1997 |
| 1998 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1999 |
| 2000 GURL url(kStreamUrl); |
| 2001 scoped_refptr<SpdyStream> stream = |
| 2002 CreateStreamSynchronously(session, url, MEDIUM, BoundNetLog()); |
| 2003 ASSERT_TRUE(stream.get() != NULL); |
| 2004 EXPECT_EQ(0u, stream->stream_id()); |
| 2005 |
| 2006 DropReceivedDataDelegate delegate(stream, msg_data); |
| 2007 stream->SetDelegate(&delegate); |
| 2008 |
| 2009 stream->set_spdy_headers( |
| 2010 ConstructPostHeaderBlock(url.spec(), msg_data_size)); |
| 2011 EXPECT_TRUE(stream->HasUrl()); |
| 2012 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); |
| 2013 |
| 2014 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
| 2015 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); |
| 2016 |
| 2017 data.RunFor(5); |
| 2018 |
| 2019 EXPECT_TRUE(data.at_write_eof()); |
| 2020 EXPECT_TRUE(data.at_read_eof()); |
| 2021 |
| 2022 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
| 2023 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); |
| 2024 |
| 2025 stream->Close(); |
| 2026 |
| 2027 EXPECT_EQ(OK, delegate.WaitForClose()); |
| 2028 |
| 2029 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
| 2030 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); |
| 2031 } |
| 2032 |
1931 // Send data back and forth; the send and receive windows should | 2033 // Send data back and forth; the send and receive windows should |
1932 // change appropriately. | 2034 // change appropriately. |
1933 TEST_F(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31) { | 2035 TEST_F(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31) { |
1934 const char kStreamUrl[] = "http://www.google.com/"; | 2036 const char kStreamUrl[] = "http://www.google.com/"; |
1935 | 2037 |
1936 session_deps_.enable_spdy_31 = true; | 2038 session_deps_.enable_spdy_31 = true; |
1937 | 2039 |
1938 const int32 msg_data_size = 100; | 2040 const int32 msg_data_size = 100; |
1939 const std::string msg_data(msg_data_size, 'a'); | 2041 const std::string msg_data(msg_data_size, 'a'); |
1940 | 2042 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2031 data.RunFor(1); | 2133 data.RunFor(1); |
2032 | 2134 |
2033 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); | 2135 EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); |
2034 EXPECT_EQ(kDefaultInitialRecvWindowSize - msg_data_size, | 2136 EXPECT_EQ(kDefaultInitialRecvWindowSize - msg_data_size, |
2035 session->session_recv_window_size_); | 2137 session->session_recv_window_size_); |
2036 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); | 2138 EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); |
2037 | 2139 |
2038 EXPECT_TRUE(data.at_write_eof()); | 2140 EXPECT_TRUE(data.at_write_eof()); |
2039 EXPECT_TRUE(data.at_read_eof()); | 2141 EXPECT_TRUE(data.at_read_eof()); |
2040 | 2142 |
2041 // Normally done by the delegate, but not by our test delegate. | 2143 EXPECT_EQ(msg_data, delegate.TakeReceivedData()); |
2042 session->IncreaseRecvWindowSize(msg_data_size); | |
2043 | 2144 |
| 2145 // Draining the delegate's read queue should increase our receive |
| 2146 // window. |
2044 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); | 2147 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
2045 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); | 2148 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); |
2046 | 2149 |
2047 stream->Close(); | 2150 stream->Close(); |
2048 | 2151 |
2049 EXPECT_EQ(OK, delegate.WaitForClose()); | 2152 EXPECT_EQ(OK, delegate.WaitForClose()); |
| 2153 |
| 2154 EXPECT_EQ(kDefaultInitialRecvWindowSize, session->session_recv_window_size_); |
| 2155 EXPECT_EQ(msg_data_size, session->session_unacked_recv_window_bytes_); |
2050 } | 2156 } |
2051 | 2157 |
2052 // Cause a stall by reducing the flow control send window to 0. The | 2158 // Cause a stall by reducing the flow control send window to 0. The |
2053 // stream should resume when that window is then increased. | 2159 // stream should resume when that window is then increased. |
2054 TEST_F(SpdySessionSpdy3Test, ResumeAfterSendWindowSizeIncrease31) { | 2160 TEST_F(SpdySessionSpdy3Test, ResumeAfterSendWindowSizeIncrease31) { |
2055 const char kStreamUrl[] = "http://www.google.com/"; | 2161 const char kStreamUrl[] = "http://www.google.com/"; |
2056 GURL url(kStreamUrl); | 2162 GURL url(kStreamUrl); |
2057 | 2163 |
2058 session_deps_.enable_spdy_31 = true; | 2164 session_deps_.enable_spdy_31 = true; |
2059 session_deps_.host_resolver->set_synchronous_mode(true); | 2165 session_deps_.host_resolver->set_synchronous_mode(true); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2125 | 2231 |
2126 EXPECT_FALSE(stream->send_stalled_by_flow_control()); | 2232 EXPECT_FALSE(stream->send_stalled_by_flow_control()); |
2127 | 2233 |
2128 data.RunFor(3); | 2234 data.RunFor(3); |
2129 | 2235 |
2130 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); | 2236 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); |
2131 | 2237 |
2132 EXPECT_TRUE(delegate.send_headers_completed()); | 2238 EXPECT_TRUE(delegate.send_headers_completed()); |
2133 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); | 2239 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); |
2134 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); | 2240 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); |
2135 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate.received_data()); | 2241 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate.TakeReceivedData()); |
2136 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate.body_data_sent()); | 2242 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate.body_data_sent()); |
2137 } | 2243 } |
2138 | 2244 |
2139 // Cause a stall by reducing the flow control send window to 0. The | 2245 // Cause a stall by reducing the flow control send window to 0. The |
2140 // streams should resume in priority order when that window is then | 2246 // streams should resume in priority order when that window is then |
2141 // increased. | 2247 // increased. |
2142 TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { | 2248 TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { |
2143 const char kStreamUrl[] = "http://www.google.com/"; | 2249 const char kStreamUrl[] = "http://www.google.com/"; |
2144 GURL url(kStreamUrl); | 2250 GURL url(kStreamUrl); |
2145 | 2251 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); | 2367 EXPECT_FALSE(stream2->send_stalled_by_flow_control()); |
2262 | 2368 |
2263 data.RunFor(3); | 2369 data.RunFor(3); |
2264 | 2370 |
2265 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); | 2371 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); |
2266 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); | 2372 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); |
2267 | 2373 |
2268 EXPECT_TRUE(delegate1.send_headers_completed()); | 2374 EXPECT_TRUE(delegate1.send_headers_completed()); |
2269 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); | 2375 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); |
2270 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); | 2376 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); |
2271 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate1.received_data()); | 2377 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate1.TakeReceivedData()); |
2272 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate1.body_data_sent()); | 2378 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate1.body_data_sent()); |
2273 | 2379 |
2274 EXPECT_TRUE(delegate2.send_headers_completed()); | 2380 EXPECT_TRUE(delegate2.send_headers_completed()); |
2275 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); | 2381 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); |
2276 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); | 2382 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); |
2277 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate2.received_data()); | 2383 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate2.TakeReceivedData()); |
2278 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate2.body_data_sent()); | 2384 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate2.body_data_sent()); |
2279 } | 2385 } |
2280 | 2386 |
2281 // Delegate that closes a given stream after sending its body. | 2387 // Delegate that closes a given stream after sending its body. |
2282 class StreamClosingDelegate : public test::StreamDelegateWithBody { | 2388 class StreamClosingDelegate : public test::StreamDelegateWithBody { |
2283 public: | 2389 public: |
2284 StreamClosingDelegate(const scoped_refptr<SpdyStream>& stream, | 2390 StreamClosingDelegate(const scoped_refptr<SpdyStream>& stream, |
2285 base::StringPiece data) | 2391 base::StringPiece data) |
2286 : StreamDelegateWithBody(stream, data) {} | 2392 : StreamDelegateWithBody(stream, data) {} |
2287 | 2393 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2455 | 2561 |
2456 data.RunFor(3); | 2562 data.RunFor(3); |
2457 | 2563 |
2458 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); | 2564 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); |
2459 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); | 2565 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); |
2460 EXPECT_EQ(OK, delegate3.WaitForClose()); | 2566 EXPECT_EQ(OK, delegate3.WaitForClose()); |
2461 | 2567 |
2462 EXPECT_TRUE(delegate1.send_headers_completed()); | 2568 EXPECT_TRUE(delegate1.send_headers_completed()); |
2463 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); | 2569 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); |
2464 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); | 2570 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); |
2465 EXPECT_EQ("", delegate1.received_data()); | 2571 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); |
2466 EXPECT_EQ(0, delegate1.body_data_sent()); | 2572 EXPECT_EQ(0, delegate1.body_data_sent()); |
2467 | 2573 |
2468 EXPECT_TRUE(delegate2.send_headers_completed()); | 2574 EXPECT_TRUE(delegate2.send_headers_completed()); |
2469 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); | 2575 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); |
2470 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); | 2576 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); |
2471 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate2.received_data()); | 2577 EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate2.TakeReceivedData()); |
2472 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate2.body_data_sent()); | 2578 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate2.body_data_sent()); |
2473 | 2579 |
2474 EXPECT_TRUE(delegate3.send_headers_completed()); | 2580 EXPECT_TRUE(delegate3.send_headers_completed()); |
2475 EXPECT_EQ("200", delegate3.GetResponseHeaderValue(":status")); | 2581 EXPECT_EQ("200", delegate3.GetResponseHeaderValue(":status")); |
2476 EXPECT_EQ("HTTP/1.1", delegate3.GetResponseHeaderValue(":version")); | 2582 EXPECT_EQ("HTTP/1.1", delegate3.GetResponseHeaderValue(":version")); |
2477 EXPECT_EQ("", delegate3.received_data()); | 2583 EXPECT_EQ(std::string(), delegate3.TakeReceivedData()); |
2478 EXPECT_EQ(0, delegate3.body_data_sent()); | 2584 EXPECT_EQ(0, delegate3.body_data_sent()); |
2479 } | 2585 } |
2480 | 2586 |
2481 // Delegate that closes a given session after sending its body. | 2587 // Delegate that closes a given session after sending its body. |
2482 class SessionClosingDelegate : public test::StreamDelegateWithBody { | 2588 class SessionClosingDelegate : public test::StreamDelegateWithBody { |
2483 public: | 2589 public: |
2484 SessionClosingDelegate(const scoped_refptr<SpdyStream>& stream, | 2590 SessionClosingDelegate(const scoped_refptr<SpdyStream>& stream, |
2485 base::StringPiece data) | 2591 base::StringPiece data) |
2486 : StreamDelegateWithBody(stream, data) {} | 2592 : StreamDelegateWithBody(stream, data) {} |
2487 | 2593 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2616 session = NULL; | 2722 session = NULL; |
2617 | 2723 |
2618 EXPECT_FALSE(spdy_session_pool_->HasSession(pair_)); | 2724 EXPECT_FALSE(spdy_session_pool_->HasSession(pair_)); |
2619 | 2725 |
2620 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); | 2726 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); |
2621 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); | 2727 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); |
2622 | 2728 |
2623 EXPECT_TRUE(delegate1.send_headers_completed()); | 2729 EXPECT_TRUE(delegate1.send_headers_completed()); |
2624 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); | 2730 EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); |
2625 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); | 2731 EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); |
2626 EXPECT_EQ("", delegate1.received_data()); | 2732 EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); |
2627 EXPECT_EQ(0, delegate1.body_data_sent()); | 2733 EXPECT_EQ(0, delegate1.body_data_sent()); |
2628 | 2734 |
2629 EXPECT_TRUE(delegate2.send_headers_completed()); | 2735 EXPECT_TRUE(delegate2.send_headers_completed()); |
2630 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); | 2736 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); |
2631 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); | 2737 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); |
2632 EXPECT_EQ("", delegate2.received_data()); | 2738 EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); |
2633 EXPECT_EQ(0, delegate2.body_data_sent()); | 2739 EXPECT_EQ(0, delegate2.body_data_sent()); |
2634 } | 2740 } |
2635 | 2741 |
2636 } // namespace net | 2742 } // namespace net |
OLD | NEW |