| Index: webrtc/base/socket_unittest.cc
|
| diff --git a/webrtc/base/socket_unittest.cc b/webrtc/base/socket_unittest.cc
|
| deleted file mode 100644
|
| index 2342007129a97e4a8c483966c8de4814699063ce..0000000000000000000000000000000000000000
|
| --- a/webrtc/base/socket_unittest.cc
|
| +++ /dev/null
|
| @@ -1,1046 +0,0 @@
|
| -/*
|
| - * Copyright 2007 The WebRTC Project Authors. All rights reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include <memory>
|
| -
|
| -#include "webrtc/base/socket_unittest.h"
|
| -
|
| -#include "webrtc/base/arraysize.h"
|
| -#include "webrtc/base/asyncudpsocket.h"
|
| -#include "webrtc/base/buffer.h"
|
| -#include "webrtc/base/gunit.h"
|
| -#include "webrtc/base/nethelpers.h"
|
| -#include "webrtc/base/ptr_util.h"
|
| -#include "webrtc/base/socketserver.h"
|
| -#include "webrtc/base/testclient.h"
|
| -#include "webrtc/base/testutils.h"
|
| -#include "webrtc/base/thread.h"
|
| -
|
| -namespace rtc {
|
| -
|
| -using webrtc::testing::SSE_CLOSE;
|
| -using webrtc::testing::SSE_ERROR;
|
| -using webrtc::testing::SSE_OPEN;
|
| -using webrtc::testing::SSE_READ;
|
| -using webrtc::testing::SSE_WRITE;
|
| -using webrtc::testing::StreamSink;
|
| -
|
| -#define MAYBE_SKIP_IPV6 \
|
| - if (!HasIPv6Enabled()) { \
|
| - LOG(LS_INFO) << "No IPv6... skipping"; \
|
| - return; \
|
| - }
|
| -
|
| -// Data size to be used in TcpInternal tests.
|
| -static const size_t kTcpInternalDataSize = 1024 * 1024; // bytes
|
| -
|
| -void SocketTest::TestConnectIPv4() {
|
| - ConnectInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ConnectInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWithDnsLookupIPv4() {
|
| - ConnectWithDnsLookupInternal(kIPv4Loopback, "localhost");
|
| -}
|
| -
|
| -void SocketTest::TestConnectWithDnsLookupIPv6() {
|
| - // TODO: Enable this when DNS resolution supports IPv6.
|
| - LOG(LS_INFO) << "Skipping IPv6 DNS test";
|
| - // ConnectWithDnsLookupInternal(kIPv6Loopback, "localhost6");
|
| -}
|
| -
|
| -void SocketTest::TestConnectFailIPv4() {
|
| - ConnectFailInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectFailIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ConnectFailInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWithDnsLookupFailIPv4() {
|
| - ConnectWithDnsLookupFailInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWithDnsLookupFailIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ConnectWithDnsLookupFailInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWithClosedSocketIPv4() {
|
| - ConnectWithClosedSocketInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWithClosedSocketIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ConnectWithClosedSocketInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWhileNotClosedIPv4() {
|
| - ConnectWhileNotClosedInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestConnectWhileNotClosedIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ConnectWhileNotClosedInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestServerCloseDuringConnectIPv4() {
|
| - ServerCloseDuringConnectInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestServerCloseDuringConnectIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ServerCloseDuringConnectInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestClientCloseDuringConnectIPv4() {
|
| - ClientCloseDuringConnectInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestClientCloseDuringConnectIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ClientCloseDuringConnectInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestServerCloseIPv4() {
|
| - ServerCloseInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestServerCloseIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - ServerCloseInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestCloseInClosedCallbackIPv4() {
|
| - CloseInClosedCallbackInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestCloseInClosedCallbackIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - CloseInClosedCallbackInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestSocketServerWaitIPv4() {
|
| - SocketServerWaitInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestSocketServerWaitIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - SocketServerWaitInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestTcpIPv4() {
|
| - TcpInternal(kIPv4Loopback, kTcpInternalDataSize, -1);
|
| -}
|
| -
|
| -void SocketTest::TestTcpIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - TcpInternal(kIPv6Loopback, kTcpInternalDataSize, -1);
|
| -}
|
| -
|
| -void SocketTest::TestSingleFlowControlCallbackIPv4() {
|
| - SingleFlowControlCallbackInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestSingleFlowControlCallbackIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - SingleFlowControlCallbackInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestUdpIPv4() {
|
| - UdpInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestUdpIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - UdpInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestUdpReadyToSendIPv4() {
|
| -#if !defined(WEBRTC_MAC)
|
| - // TODO(ronghuawu): Enable this test on mac/ios.
|
| - UdpReadyToSend(kIPv4Loopback);
|
| -#endif
|
| -}
|
| -
|
| -void SocketTest::TestUdpReadyToSendIPv6() {
|
| -#if defined(WEBRTC_WIN)
|
| - // TODO(ronghuawu): Enable this test (currently flakey) on mac and linux.
|
| - MAYBE_SKIP_IPV6;
|
| - UdpReadyToSend(kIPv6Loopback);
|
| -#endif
|
| -}
|
| -
|
| -void SocketTest::TestGetSetOptionsIPv4() {
|
| - GetSetOptionsInternal(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestGetSetOptionsIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - GetSetOptionsInternal(kIPv6Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestSocketRecvTimestampIPv4() {
|
| - SocketRecvTimestamp(kIPv4Loopback);
|
| -}
|
| -
|
| -void SocketTest::TestSocketRecvTimestampIPv6() {
|
| - MAYBE_SKIP_IPV6;
|
| - SocketRecvTimestamp(kIPv6Loopback);
|
| -}
|
| -
|
| -// For unbound sockets, GetLocalAddress / GetRemoteAddress return AF_UNSPEC
|
| -// values on Windows, but an empty address of the same family on Linux/MacOS X.
|
| -bool IsUnspecOrEmptyIP(const IPAddress& address) {
|
| -#if !defined(WEBRTC_WIN)
|
| - return IPIsAny(address);
|
| -#else
|
| - return address.family() == AF_UNSPEC;
|
| -#endif
|
| -}
|
| -
|
| -void SocketTest::ConnectInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| - EXPECT_EQ(AsyncSocket::CS_CLOSED, client->GetState());
|
| - EXPECT_PRED1(IsUnspecOrEmptyIP, client->GetLocalAddress().ipaddr());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTING, server->GetState());
|
| -
|
| - // Ensure no pending server connections, since we haven't done anything yet.
|
| - EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
|
| - EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
|
| - EXPECT_TRUE(accept_addr.IsNil());
|
| -
|
| - // Attempt connect to listening socket.
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| - EXPECT_FALSE(client->GetLocalAddress().IsNil());
|
| - EXPECT_NE(server->GetLocalAddress(), client->GetLocalAddress());
|
| -
|
| - // Client is connecting, outcome not yet determined.
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTING, client->GetState());
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| -
|
| - // Server has pending connection, accept it.
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - EXPECT_FALSE(accept_addr.IsNil());
|
| - EXPECT_EQ(accepted->GetRemoteAddress(), accept_addr);
|
| -
|
| - // Connected from server perspective, check the addresses are correct.
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, accepted->GetState());
|
| - EXPECT_EQ(server->GetLocalAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(client->GetLocalAddress(), accepted->GetRemoteAddress());
|
| -
|
| - // Connected from client perspective, check the addresses are correct.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| -}
|
| -
|
| -void SocketTest::ConnectWithDnsLookupInternal(const IPAddress& loopback,
|
| - const std::string& host) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connect to listening socket.
|
| - SocketAddress dns_addr(server->GetLocalAddress());
|
| - dns_addr.SetIP(host);
|
| - EXPECT_EQ(0, client->Connect(dns_addr));
|
| - // TODO: Bind when doing DNS lookup.
|
| - //EXPECT_NE(kEmptyAddr, client->GetLocalAddress()); // Implicit Bind
|
| -
|
| - // Client is connecting, outcome not yet determined.
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTING, client->GetState());
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| -
|
| - // Server has pending connection, accept it.
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - EXPECT_FALSE(accept_addr.IsNil());
|
| - EXPECT_EQ(accepted->GetRemoteAddress(), accept_addr);
|
| -
|
| - // Connected from server perspective, check the addresses are correct.
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, accepted->GetState());
|
| - EXPECT_EQ(server->GetLocalAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(client->GetLocalAddress(), accepted->GetRemoteAddress());
|
| -
|
| - // Connected from client perspective, check the addresses are correct.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| -}
|
| -
|
| -void SocketTest::ConnectFailInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server, but don't listen yet.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| -
|
| - // Attempt connect to a non-existent socket.
|
| - // We don't connect to the server socket created above, since on
|
| - // MacOS it takes about 75 seconds to get back an error!
|
| - SocketAddress bogus_addr(loopback, 65535);
|
| - EXPECT_EQ(0, client->Connect(bogus_addr));
|
| -
|
| - // Wait for connection to fail (ECONNREFUSED).
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout);
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_ERROR));
|
| - EXPECT_TRUE(client->GetRemoteAddress().IsNil());
|
| -
|
| - // Should be no pending server connections.
|
| - EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
|
| - EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
|
| - EXPECT_EQ(IPAddress(), accept_addr.ipaddr());
|
| -}
|
| -
|
| -void SocketTest::ConnectWithDnsLookupFailInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server, but don't listen yet.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| -
|
| - // Attempt connect to a non-existent host.
|
| - // We don't connect to the server socket created above, since on
|
| - // MacOS it takes about 75 seconds to get back an error!
|
| - SocketAddress bogus_dns_addr("not-a-real-hostname", 65535);
|
| - EXPECT_EQ(0, client->Connect(bogus_dns_addr));
|
| -
|
| - // Wait for connection to fail (EHOSTNOTFOUND).
|
| - bool dns_lookup_finished = false;
|
| - WAIT_(client->GetState() == AsyncSocket::CS_CLOSED, kTimeout,
|
| - dns_lookup_finished);
|
| - if (!dns_lookup_finished) {
|
| - LOG(LS_WARNING) << "Skipping test; DNS resolution took longer than 5 "
|
| - << "seconds.";
|
| - return;
|
| - }
|
| -
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout);
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_ERROR));
|
| - EXPECT_TRUE(client->GetRemoteAddress().IsNil());
|
| - // Should be no pending server connections.
|
| - EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
|
| - EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
|
| - EXPECT_TRUE(accept_addr.IsNil());
|
| -}
|
| -
|
| -void SocketTest::ConnectWithClosedSocketInternal(const IPAddress& loopback) {
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Create a client and put in to CS_CLOSED state.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - EXPECT_EQ(0, client->Close());
|
| - EXPECT_EQ(AsyncSocket::CS_CLOSED, client->GetState());
|
| -
|
| - // Connect() should reinitialize the socket, and put it in to CS_CONNECTING.
|
| - EXPECT_EQ(0, client->Connect(SocketAddress(server->GetLocalAddress())));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTING, client->GetState());
|
| -}
|
| -
|
| -void SocketTest::ConnectWhileNotClosedInternal(const IPAddress& loopback) {
|
| - // Create server and listen.
|
| - StreamSink sink;
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| - // Create client, connect.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - EXPECT_EQ(0, client->Connect(SocketAddress(server->GetLocalAddress())));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTING, client->GetState());
|
| - // Try to connect again. Should fail, but not interfere with original attempt.
|
| - EXPECT_EQ(SOCKET_ERROR,
|
| - client->Connect(SocketAddress(server->GetLocalAddress())));
|
| -
|
| - // Accept the original connection.
|
| - SocketAddress accept_addr;
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - EXPECT_FALSE(accept_addr.IsNil());
|
| -
|
| - // Check the states and addresses.
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, accepted->GetState());
|
| - EXPECT_EQ(server->GetLocalAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(client->GetLocalAddress(), accepted->GetRemoteAddress());
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| -
|
| - // Try to connect again, to an unresolved hostname.
|
| - // Shouldn't break anything.
|
| - EXPECT_EQ(SOCKET_ERROR,
|
| - client->Connect(SocketAddress("localhost",
|
| - server->GetLocalAddress().port())));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, accepted->GetState());
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, client->GetState());
|
| - EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| -}
|
| -
|
| -void SocketTest::ServerCloseDuringConnectInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connect to listening socket.
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| -
|
| - // Close down the server while the socket is in the accept queue.
|
| - EXPECT_TRUE_WAIT(sink.Check(server.get(), SSE_READ), kTimeout);
|
| - server->Close();
|
| -
|
| - // This should fail the connection for the client. Clean up.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_ERROR));
|
| - client->Close();
|
| -}
|
| -
|
| -void SocketTest::ClientCloseDuringConnectInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connect to listening socket.
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| -
|
| - // Close down the client while the socket is in the accept queue.
|
| - EXPECT_TRUE_WAIT(sink.Check(server.get(), SSE_READ), kTimeout);
|
| - client->Close();
|
| -
|
| - // The connection should still be able to be accepted.
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - sink.Monitor(accepted.get());
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, accepted->GetState());
|
| -
|
| - // The accepted socket should then close (possibly with err, timing-related)
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, accepted->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(accepted.get(), SSE_CLOSE) ||
|
| - sink.Check(accepted.get(), SSE_ERROR));
|
| -
|
| - // The client should not get a close event.
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| -}
|
| -
|
| -void SocketTest::ServerCloseInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connection.
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| -
|
| - // Accept connection.
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - sink.Monitor(accepted.get());
|
| -
|
| - // Both sides are now connected.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(accepted->GetRemoteAddress(), client->GetLocalAddress());
|
| -
|
| - // Send data to the client, and then close the connection.
|
| - EXPECT_EQ(1, accepted->Send("a", 1));
|
| - accepted->Close();
|
| - EXPECT_EQ(AsyncSocket::CS_CLOSED, accepted->GetState());
|
| -
|
| - // Expect that the client is notified, and has not yet closed.
|
| - EXPECT_TRUE_WAIT(sink.Check(client.get(), SSE_READ), kTimeout);
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, client->GetState());
|
| -
|
| - // Ensure the data can be read.
|
| - char buffer[10];
|
| - EXPECT_EQ(1, client->Recv(buffer, sizeof(buffer), nullptr));
|
| - EXPECT_EQ('a', buffer[0]);
|
| -
|
| - // Now we should close, but the remote address will remain.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_FALSE(client->GetRemoteAddress().IsAnyIP());
|
| -
|
| - // The closer should not get a close signal.
|
| - EXPECT_FALSE(sink.Check(accepted.get(), SSE_CLOSE));
|
| - EXPECT_TRUE(accepted->GetRemoteAddress().IsNil());
|
| -
|
| - // And the closee should only get a single signal.
|
| - Thread::Current()->ProcessMessages(0);
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| -
|
| - // Close down the client and ensure all is good.
|
| - client->Close();
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_TRUE(client->GetRemoteAddress().IsNil());
|
| -}
|
| -
|
| -class SocketCloser : public sigslot::has_slots<> {
|
| - public:
|
| - void OnClose(AsyncSocket* socket, int error) {
|
| - socket->Close(); // Deleting here would blow up the vector of handlers
|
| - // for the socket's signal.
|
| - }
|
| -};
|
| -
|
| -void SocketTest::CloseInClosedCallbackInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketCloser closer;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| - client->SignalCloseEvent.connect(&closer, &SocketCloser::OnClose);
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connection.
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| -
|
| - // Accept connection.
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - sink.Monitor(accepted.get());
|
| -
|
| - // Both sides are now connected.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(accepted->GetRemoteAddress(), client->GetLocalAddress());
|
| -
|
| - // Send data to the client, and then close the connection.
|
| - accepted->Close();
|
| - EXPECT_EQ(AsyncSocket::CS_CLOSED, accepted->GetState());
|
| -
|
| - // Expect that the client is notified, and has not yet closed.
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, client->GetState());
|
| -
|
| - // Now we should be closed and invalidated
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_TRUE(Socket::CS_CLOSED == client->GetState());
|
| -}
|
| -
|
| -class Sleeper : public MessageHandler {
|
| - public:
|
| - Sleeper() {}
|
| - void OnMessage(Message* msg) {
|
| - Thread::Current()->SleepMs(500);
|
| - }
|
| -};
|
| -
|
| -void SocketTest::SocketServerWaitInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create & connect server and client sockets.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| -
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - sink.Monitor(accepted.get());
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, accepted->GetState());
|
| - EXPECT_EQ(server->GetLocalAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(client->GetLocalAddress(), accepted->GetRemoteAddress());
|
| -
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
|
| - EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| -
|
| - // Do an i/o operation, triggering an eventual callback.
|
| - EXPECT_FALSE(sink.Check(accepted.get(), SSE_READ));
|
| - char buf[1024] = {0};
|
| -
|
| - EXPECT_EQ(1024, client->Send(buf, 1024));
|
| - EXPECT_FALSE(sink.Check(accepted.get(), SSE_READ));
|
| -
|
| - // Shouldn't signal when blocked in a thread Send, where process_io is false.
|
| - std::unique_ptr<Thread> thread(new Thread());
|
| - thread->Start();
|
| - Sleeper sleeper;
|
| - TypedMessageData<AsyncSocket*> data(client.get());
|
| - thread->Send(RTC_FROM_HERE, &sleeper, 0, &data);
|
| - EXPECT_FALSE(sink.Check(accepted.get(), SSE_READ));
|
| -
|
| - // But should signal when process_io is true.
|
| - EXPECT_TRUE_WAIT((sink.Check(accepted.get(), SSE_READ)), kTimeout);
|
| - EXPECT_LT(0, accepted->Recv(buf, 1024, nullptr));
|
| -}
|
| -
|
| -void SocketTest::TcpInternal(const IPAddress& loopback, size_t data_size,
|
| - ptrdiff_t max_send_size) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create receiving client.
|
| - std::unique_ptr<AsyncSocket> receiver(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(receiver.get());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connection.
|
| - EXPECT_EQ(0, receiver->Connect(server->GetLocalAddress()));
|
| -
|
| - // Accept connection which will be used for sending.
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> sender(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(sender);
|
| - sink.Monitor(sender.get());
|
| -
|
| - // Both sides are now connected.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, receiver->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(receiver.get(), SSE_OPEN));
|
| - EXPECT_EQ(receiver->GetRemoteAddress(), sender->GetLocalAddress());
|
| - EXPECT_EQ(sender->GetRemoteAddress(), receiver->GetLocalAddress());
|
| -
|
| - // Create test data.
|
| - rtc::Buffer send_buffer(0, data_size);
|
| - rtc::Buffer recv_buffer(0, data_size);
|
| - for (size_t i = 0; i < data_size; ++i) {
|
| - char ch = static_cast<char>(i % 256);
|
| - send_buffer.AppendData(&ch, sizeof(ch));
|
| - }
|
| - rtc::Buffer recved_data(0, data_size);
|
| -
|
| - // Send and receive a bunch of data.
|
| - size_t sent_size = 0;
|
| - bool writable = true;
|
| - bool send_called = false;
|
| - bool readable = false;
|
| - bool recv_called = false;
|
| - while (recv_buffer.size() < send_buffer.size()) {
|
| - // Send as much as we can while we're cleared to send.
|
| - while (writable && sent_size < send_buffer.size()) {
|
| - int unsent_size = static_cast<int>(send_buffer.size() - sent_size);
|
| - int sent = sender->Send(send_buffer.data() + sent_size, unsent_size);
|
| - if (!send_called) {
|
| - // The first Send() after connecting or getting writability should
|
| - // succeed and send some data.
|
| - EXPECT_GT(sent, 0);
|
| - send_called = true;
|
| - }
|
| - if (sent >= 0) {
|
| - EXPECT_LE(sent, unsent_size);
|
| - sent_size += sent;
|
| - if (max_send_size >= 0) {
|
| - EXPECT_LE(static_cast<ptrdiff_t>(sent), max_send_size);
|
| - if (sent < unsent_size) {
|
| - // If max_send_size is limiting the amount to send per call such
|
| - // that the sent amount is less than the unsent amount, we simulate
|
| - // that the socket is no longer writable.
|
| - writable = false;
|
| - }
|
| - }
|
| - } else {
|
| - ASSERT_TRUE(sender->IsBlocking());
|
| - writable = false;
|
| - }
|
| - }
|
| -
|
| - // Read all the sent data.
|
| - while (recv_buffer.size() < sent_size) {
|
| - if (!readable) {
|
| - // Wait until data is available.
|
| - EXPECT_TRUE_WAIT(sink.Check(receiver.get(), SSE_READ), kTimeout);
|
| - readable = true;
|
| - recv_called = false;
|
| - }
|
| -
|
| - // Receive as much as we can get in a single recv call.
|
| - int recved_size = receiver->Recv(recved_data.data(), data_size, nullptr);
|
| -
|
| - if (!recv_called) {
|
| - // The first Recv() after getting readability should succeed and receive
|
| - // some data.
|
| - // TODO: The following line is disabled due to flakey pulse
|
| - // builds. Re-enable if/when possible.
|
| - // EXPECT_GT(recved_size, 0);
|
| - recv_called = true;
|
| - }
|
| - if (recved_size >= 0) {
|
| - EXPECT_LE(static_cast<size_t>(recved_size),
|
| - sent_size - recv_buffer.size());
|
| - recv_buffer.AppendData(recved_data.data(), recved_size);
|
| - } else {
|
| - ASSERT_TRUE(receiver->IsBlocking());
|
| - readable = false;
|
| - }
|
| - }
|
| -
|
| - // Once all that we've sent has been received, expect to be able to send
|
| - // again.
|
| - if (!writable) {
|
| - ASSERT_TRUE_WAIT(sink.Check(sender.get(), SSE_WRITE), kTimeout);
|
| - writable = true;
|
| - send_called = false;
|
| - }
|
| - }
|
| -
|
| - // The received data matches the sent data.
|
| - EXPECT_EQ(data_size, sent_size);
|
| - EXPECT_EQ(data_size, recv_buffer.size());
|
| - EXPECT_EQ(recv_buffer, send_buffer);
|
| -
|
| - // Close down.
|
| - sender->Close();
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, receiver->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(receiver.get(), SSE_CLOSE));
|
| - receiver->Close();
|
| -}
|
| -
|
| -void SocketTest::SingleFlowControlCallbackInternal(const IPAddress& loopback) {
|
| - StreamSink sink;
|
| - SocketAddress accept_addr;
|
| -
|
| - // Create client.
|
| - std::unique_ptr<AsyncSocket> client(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(client.get());
|
| -
|
| - // Create server and listen.
|
| - std::unique_ptr<AsyncSocket> server(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| - sink.Monitor(server.get());
|
| - EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| - EXPECT_EQ(0, server->Listen(5));
|
| -
|
| - // Attempt connection.
|
| - EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
|
| -
|
| - // Accept connection.
|
| - EXPECT_TRUE_WAIT((sink.Check(server.get(), SSE_READ)), kTimeout);
|
| - std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| - ASSERT_TRUE(accepted);
|
| - sink.Monitor(accepted.get());
|
| -
|
| - // Both sides are now connected.
|
| - EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
|
| - EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
|
| - EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
|
| - EXPECT_EQ(accepted->GetRemoteAddress(), client->GetLocalAddress());
|
| -
|
| - // Expect a writable callback from the connect.
|
| - EXPECT_TRUE_WAIT(sink.Check(accepted.get(), SSE_WRITE), kTimeout);
|
| -
|
| - // Fill the socket buffer.
|
| - char buf[1024 * 16] = {0};
|
| - int sends = 0;
|
| - while (++sends && accepted->Send(&buf, arraysize(buf)) != -1) {}
|
| - EXPECT_TRUE(accepted->IsBlocking());
|
| -
|
| - // Wait until data is available.
|
| - EXPECT_TRUE_WAIT(sink.Check(client.get(), SSE_READ), kTimeout);
|
| -
|
| - // Pull data.
|
| - for (int i = 0; i < sends; ++i) {
|
| - client->Recv(buf, arraysize(buf), nullptr);
|
| - }
|
| -
|
| - // Expect at least one additional writable callback.
|
| - EXPECT_TRUE_WAIT(sink.Check(accepted.get(), SSE_WRITE), kTimeout);
|
| -
|
| - // Adding data in response to the writeable callback shouldn't cause infinite
|
| - // callbacks.
|
| - int extras = 0;
|
| - for (int i = 0; i < 100; ++i) {
|
| - accepted->Send(&buf, arraysize(buf));
|
| - rtc::Thread::Current()->ProcessMessages(1);
|
| - if (sink.Check(accepted.get(), SSE_WRITE)) {
|
| - extras++;
|
| - }
|
| - }
|
| - EXPECT_LT(extras, 2);
|
| -
|
| - // Close down.
|
| - accepted->Close();
|
| - client->Close();
|
| -}
|
| -
|
| -void SocketTest::UdpInternal(const IPAddress& loopback) {
|
| - SocketAddress empty = EmptySocketAddressWithFamily(loopback.family());
|
| - // Test basic bind and connect behavior.
|
| - AsyncSocket* socket =
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_DGRAM);
|
| - EXPECT_EQ(AsyncSocket::CS_CLOSED, socket->GetState());
|
| - EXPECT_EQ(0, socket->Bind(SocketAddress(loopback, 0)));
|
| - SocketAddress addr1 = socket->GetLocalAddress();
|
| - EXPECT_EQ(0, socket->Connect(addr1));
|
| - EXPECT_EQ(AsyncSocket::CS_CONNECTED, socket->GetState());
|
| - socket->Close();
|
| - EXPECT_EQ(AsyncSocket::CS_CLOSED, socket->GetState());
|
| - delete socket;
|
| -
|
| - // Test send/receive behavior.
|
| - std::unique_ptr<TestClient> client1(
|
| - new TestClient(WrapUnique(AsyncUDPSocket::Create(ss_, addr1))));
|
| - std::unique_ptr<TestClient> client2(
|
| - new TestClient(WrapUnique(AsyncUDPSocket::Create(ss_, empty))));
|
| -
|
| - SocketAddress addr2;
|
| - EXPECT_EQ(3, client2->SendTo("foo", 3, addr1));
|
| - EXPECT_TRUE(client1->CheckNextPacket("foo", 3, &addr2));
|
| -
|
| - SocketAddress addr3;
|
| - EXPECT_EQ(6, client1->SendTo("bizbaz", 6, addr2));
|
| - EXPECT_TRUE(client2->CheckNextPacket("bizbaz", 6, &addr3));
|
| - EXPECT_EQ(addr3, addr1);
|
| - // TODO: figure out what the intent is here
|
| - for (int i = 0; i < 10; ++i) {
|
| - client2.reset(
|
| - new TestClient(WrapUnique(AsyncUDPSocket::Create(ss_, empty))));
|
| -
|
| - SocketAddress addr4;
|
| - EXPECT_EQ(3, client2->SendTo("foo", 3, addr1));
|
| - EXPECT_TRUE(client1->CheckNextPacket("foo", 3, &addr4));
|
| - EXPECT_EQ(addr4.ipaddr(), addr2.ipaddr());
|
| -
|
| - SocketAddress addr5;
|
| - EXPECT_EQ(6, client1->SendTo("bizbaz", 6, addr4));
|
| - EXPECT_TRUE(client2->CheckNextPacket("bizbaz", 6, &addr5));
|
| - EXPECT_EQ(addr5, addr1);
|
| -
|
| - addr2 = addr4;
|
| - }
|
| -}
|
| -
|
| -void SocketTest::UdpReadyToSend(const IPAddress& loopback) {
|
| - SocketAddress empty = EmptySocketAddressWithFamily(loopback.family());
|
| - // RFC 5737 - The blocks 192.0.2.0/24 (TEST-NET-1) ... are provided for use in
|
| - // documentation.
|
| - // RFC 3849 - 2001:DB8::/32 as a documentation-only prefix.
|
| - std::string dest = (loopback.family() == AF_INET6) ?
|
| - "2001:db8::1" : "192.0.2.0";
|
| - SocketAddress test_addr(dest, 2345);
|
| -
|
| - // Test send
|
| - std::unique_ptr<TestClient> client(
|
| - new TestClient(WrapUnique(AsyncUDPSocket::Create(ss_, empty))));
|
| - int test_packet_size = 1200;
|
| - std::unique_ptr<char[]> test_packet(new char[test_packet_size]);
|
| - // Init the test packet just to avoid memcheck warning.
|
| - memset(test_packet.get(), 0, test_packet_size);
|
| - // Set the send buffer size to the same size as the test packet to have a
|
| - // better chance to get EWOULDBLOCK.
|
| - int send_buffer_size = test_packet_size;
|
| -#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
|
| - send_buffer_size /= 2;
|
| -#endif
|
| - client->SetOption(rtc::Socket::OPT_SNDBUF, send_buffer_size);
|
| -
|
| - int error = 0;
|
| - uint32_t start_ms = Time();
|
| - int sent_packet_num = 0;
|
| - int expected_error = EWOULDBLOCK;
|
| - while (start_ms + kTimeout > Time()) {
|
| - int ret = client->SendTo(test_packet.get(), test_packet_size, test_addr);
|
| - ++sent_packet_num;
|
| - if (ret != test_packet_size) {
|
| - error = client->GetError();
|
| - if (error == expected_error) {
|
| - LOG(LS_INFO) << "Got expected error code after sending "
|
| - << sent_packet_num << " packets.";
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - EXPECT_EQ(expected_error, error);
|
| - EXPECT_FALSE(client->ready_to_send());
|
| - EXPECT_TRUE_WAIT(client->ready_to_send(), kTimeout);
|
| - LOG(LS_INFO) << "Got SignalReadyToSend";
|
| -}
|
| -
|
| -void SocketTest::GetSetOptionsInternal(const IPAddress& loopback) {
|
| - std::unique_ptr<AsyncSocket> socket(
|
| - ss_->CreateAsyncSocket(loopback.family(), SOCK_DGRAM));
|
| - socket->Bind(SocketAddress(loopback, 0));
|
| -
|
| - // Check SNDBUF/RCVBUF.
|
| - const int desired_size = 12345;
|
| -#if defined(WEBRTC_LINUX)
|
| - // Yes, really. It's in the kernel source.
|
| - const int expected_size = desired_size * 2;
|
| -#else // !WEBRTC_LINUX
|
| - const int expected_size = desired_size;
|
| -#endif // !WEBRTC_LINUX
|
| - int recv_size = 0;
|
| - int send_size = 0;
|
| - // get the initial sizes
|
| - ASSERT_NE(-1, socket->GetOption(Socket::OPT_RCVBUF, &recv_size));
|
| - ASSERT_NE(-1, socket->GetOption(Socket::OPT_SNDBUF, &send_size));
|
| - // set our desired sizes
|
| - ASSERT_NE(-1, socket->SetOption(Socket::OPT_RCVBUF, desired_size));
|
| - ASSERT_NE(-1, socket->SetOption(Socket::OPT_SNDBUF, desired_size));
|
| - // get the sizes again
|
| - ASSERT_NE(-1, socket->GetOption(Socket::OPT_RCVBUF, &recv_size));
|
| - ASSERT_NE(-1, socket->GetOption(Socket::OPT_SNDBUF, &send_size));
|
| - // make sure they are right
|
| - ASSERT_EQ(expected_size, recv_size);
|
| - ASSERT_EQ(expected_size, send_size);
|
| -
|
| - // Check that we can't set NODELAY on a UDP socket.
|
| - int current_nd, desired_nd = 1;
|
| - ASSERT_EQ(-1, socket->GetOption(Socket::OPT_NODELAY, ¤t_nd));
|
| - ASSERT_EQ(-1, socket->SetOption(Socket::OPT_NODELAY, desired_nd));
|
| -}
|
| -
|
| -void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
|
| - std::unique_ptr<Socket> socket(
|
| - ss_->CreateSocket(loopback.family(), SOCK_DGRAM));
|
| - EXPECT_EQ(0, socket->Bind(SocketAddress(loopback, 0)));
|
| - SocketAddress address = socket->GetLocalAddress();
|
| -
|
| - int64_t send_time_1 = TimeMicros();
|
| - socket->SendTo("foo", 3, address);
|
| - int64_t recv_timestamp_1;
|
| - char buffer[3];
|
| - socket->RecvFrom(buffer, 3, nullptr, &recv_timestamp_1);
|
| - EXPECT_GT(recv_timestamp_1, -1);
|
| -
|
| - const int64_t kTimeBetweenPacketsMs = 100;
|
| - Thread::SleepMs(kTimeBetweenPacketsMs);
|
| -
|
| - int64_t send_time_2 = TimeMicros();
|
| - socket->SendTo("bar", 3, address);
|
| - int64_t recv_timestamp_2;
|
| - socket->RecvFrom(buffer, 3, nullptr, &recv_timestamp_2);
|
| -
|
| - int64_t system_time_diff = send_time_2 - send_time_1;
|
| - int64_t recv_timestamp_diff = recv_timestamp_2 - recv_timestamp_1;
|
| - // Compare against the system time at the point of sending, because
|
| - // SleepMs may not sleep for exactly the requested time.
|
| - EXPECT_NEAR(system_time_diff, recv_timestamp_diff, 10000);
|
| -}
|
| -
|
| -} // namespace rtc
|
|
|