/*
 *  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 "rtc_base/socket.h"

#include <errno.h>
#include <stdint.h>
#include <string.h>

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/test/rtc_error_matchers.h"
#include "api/transport/ecn_marking.h"
#include "rtc_base/async_udp_socket.h"
#include "rtc_base/buffer.h"
#include "rtc_base/gunit.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h"
#include "rtc_base/net_helpers.h"
#include "rtc_base/net_test_helpers.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/socket_server.h"
#include "rtc_base/socket_unittest.h"
#include "rtc_base/test_client.h"
#include "rtc_base/test_utils.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/wait_until.h"

#define MAYBE_SKIP_IPV6                        \
  if (!::webrtc::HasIPv6Enabled()) {           \
    RTC_LOG(LS_INFO) << "No IPv6... skipping"; \
    return;                                    \
  }

namespace webrtc {

using testing::SSE_CLOSE;
using testing::SSE_ERROR;
using testing::SSE_OPEN;
using testing::SSE_READ;
using testing::SSE_WRITE;
using testing::StreamSink;

// 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.
  RTC_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::TestDeleteInReadCallbackIPv4() {
  DeleteInReadCallbackInternal(kIPv4Loopback);
}

void SocketTest::TestDeleteInReadCallbackIPv6() {
  MAYBE_SKIP_IPV6;
  DeleteInReadCallbackInternal(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);
}

void SocketTest::TestUdpSocketRecvTimestampUseRtcEpochIPv4() {
  UdpSocketRecvTimestampUseRtcEpoch(kIPv4Loopback);
}

void SocketTest::TestUdpSocketRecvTimestampUseRtcEpochIPv6() {
  MAYBE_SKIP_IPV6;
  UdpSocketRecvTimestampUseRtcEpoch(kIPv6Loopback);
}

void SocketTest::TestSocketSendRecvWithEcnIPV4() {
  SocketSendRecvWithEcn(kIPv4Loopback);
}

void SocketTest::TestSocketSendRecvWithEcnIPV6() {
  MAYBE_SKIP_IPV6;
  SocketSendRecvWithEcn(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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());
  EXPECT_EQ(Socket::CS_CLOSED, client->GetState());
  EXPECT_TRUE(IsUnspecOrEmptyIP(client->GetLocalAddress().ipaddr()));

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(server.get());
  EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
  EXPECT_EQ(0, server->Listen(5));
  EXPECT_EQ(Socket::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(Socket::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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> 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(Socket::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_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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,
                                              absl::string_view host) {
  StreamSink sink;
  SocketAddress accept_addr;

  // Create client.
  std::unique_ptr<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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(Socket::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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> 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(Socket::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_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server, but don't listen yet.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server, but don't listen yet.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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() == Socket::CS_CLOSED, 5000, dns_lookup_finished);
  if (!dns_lookup_finished) {
    RTC_LOG(LS_WARNING) << "Skipping test; DNS resolution took longer than 5 "
                           "seconds.";
    return;
  }

  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  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<Socket> server(
      socket_factory_->CreateSocket(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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  EXPECT_EQ(0, client->Close());
  EXPECT_EQ(Socket::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(Socket::CS_CONNECTING, client->GetState());
}

void SocketTest::ConnectWhileNotClosedInternal(const IPAddress& loopback) {
  // Create server and listen.
  StreamSink sink;
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  EXPECT_EQ(0, client->Connect(SocketAddress(server->GetLocalAddress())));
  EXPECT_EQ(Socket::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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> accepted(server->Accept(&accept_addr));
  ASSERT_TRUE(accepted);
  EXPECT_FALSE(accept_addr.IsNil());

  // Check the states and addresses.
  EXPECT_EQ(Socket::CS_CONNECTED, accepted->GetState());
  EXPECT_EQ(server->GetLocalAddress(), accepted->GetLocalAddress());
  EXPECT_EQ(client->GetLocalAddress(), accepted->GetRemoteAddress());
  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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(Socket::CS_CONNECTED, accepted->GetState());
  EXPECT_EQ(Socket::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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return sink.Check(server.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  server->Close();

  // This should fail the connection for the client. Clean up.
  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return sink.Check(server.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  client->Close();

  // The connection should still be able to be accepted.
  std::unique_ptr<Socket> accepted(server->Accept(&accept_addr));
  ASSERT_TRUE(accepted);
  sink.Monitor(accepted.get());
  EXPECT_EQ(Socket::CS_CONNECTED, accepted->GetState());

  // The accepted socket should then close (possibly with err, timing-related)
  EXPECT_THAT(WaitUntil([&] { return accepted->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> accepted(server->Accept(&accept_addr));
  ASSERT_TRUE(accepted);
  sink.Monitor(accepted.get());

  // Both sides are now connected.
  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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(Socket::CS_CLOSED, accepted->GetState());

  // Expect that the client is notified, and has not yet closed.
  EXPECT_THAT(WaitUntil([&] { return sink.Check(client.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
  EXPECT_EQ(Socket::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_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  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(Socket* 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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());
  client->SignalCloseEvent.connect(&closer, &SocketCloser::OnClose);

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> accepted(server->Accept(&accept_addr));
  ASSERT_TRUE(accepted);
  sink.Monitor(accepted.get());

  // Both sides are now connected.
  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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(Socket::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(Socket::CS_CONNECTED, client->GetState());

  // Now we should be closed and invalidated
  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  EXPECT_TRUE(sink.Check(client.get(), SSE_CLOSE));
  EXPECT_TRUE(Socket::CS_CLOSED == client->GetState());
}

// Helper class specifically for the test below.
class SocketDeleter : public sigslot::has_slots<> {
 public:
  explicit SocketDeleter(std::unique_ptr<Socket> socket)
      : socket_(std::move(socket)) {}

  void Delete(Socket* other) { socket_.reset(); }

  bool deleted() const { return socket_ == nullptr; }

 private:
  std::unique_ptr<Socket> socket_;
};

// Tested deleting a socket within another socket's read callback. A previous
// iteration of the select loop failed in this situation, if both sockets
// became readable at the same time.
void SocketTest::DeleteInReadCallbackInternal(const IPAddress& loopback) {
  std::unique_ptr<Socket> socket1(
      socket_factory_->CreateSocket(loopback.family(), SOCK_DGRAM));
  std::unique_ptr<Socket> socket2(
      socket_factory_->CreateSocket(loopback.family(), SOCK_DGRAM));
  EXPECT_EQ(0, socket1->Bind(SocketAddress(loopback, 0)));
  EXPECT_EQ(0, socket2->Bind(SocketAddress(loopback, 0)));
  EXPECT_EQ(3, socket1->SendTo("foo", 3, socket1->GetLocalAddress()));
  EXPECT_EQ(3, socket2->SendTo("bar", 3, socket1->GetLocalAddress()));
  // Sleep a while to ensure sends are both completed at the same time.
  Thread::SleepMs(1000);

  // Configure the helper class to delete socket 2 when socket 1 has a read
  // event.
  SocketDeleter deleter(std::move(socket2));
  socket1->SignalReadEvent.connect(&deleter, &SocketDeleter::Delete);
  EXPECT_THAT(WaitUntil([&] { return deleter.deleted(); }, ::testing::IsTrue()),
              IsRtcOk());
}

void SocketTest::SocketServerWaitInternal(const IPAddress& loopback) {
  StreamSink sink;
  SocketAddress accept_addr;

  // Create & connect server and client sockets.
  std::unique_ptr<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());

  std::unique_ptr<Socket> accepted(server->Accept(&accept_addr));
  ASSERT_TRUE(accepted);
  sink.Monitor(accepted.get());
  EXPECT_EQ(Socket::CS_CONNECTED, accepted->GetState());
  EXPECT_EQ(server->GetLocalAddress(), accepted->GetLocalAddress());
  EXPECT_EQ(client->GetLocalAddress(), accepted->GetRemoteAddress());

  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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(Thread::CreateWithSocketServer());
  thread->Start();
  thread->BlockingCall([] { Thread::SleepMs(500); });
  EXPECT_FALSE(sink.Check(accepted.get(), SSE_READ));

  // But should signal when process_io is true.
  EXPECT_THAT(WaitUntil([&] { return (sink.Check(accepted.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  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<Socket> receiver(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(receiver.get());

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> sender(server->Accept(&accept_addr));
  ASSERT_TRUE(sender);
  sink.Monitor(sender.get());

  // Both sides are now connected.
  EXPECT_THAT(WaitUntil([&] { return receiver->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  EXPECT_TRUE(sink.Check(receiver.get(), SSE_OPEN));
  EXPECT_EQ(receiver->GetRemoteAddress(), sender->GetLocalAddress());
  EXPECT_EQ(sender->GetRemoteAddress(), receiver->GetLocalAddress());

  // Create test data.
  Buffer send_buffer(0, data_size);
  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));
  }
  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_THAT(
            WaitUntil([&] { return sink.Check(receiver.get(), SSE_READ); },
                      ::testing::IsTrue()),
            IsRtcOk());
        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_THAT(WaitUntil([&] { return sink.Check(sender.get(), SSE_WRITE); },
                            ::testing::IsTrue()),
                  IsRtcOk());
      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_THAT(WaitUntil([&] { return receiver->GetState(); },
                        ::testing::Eq(Socket::CS_CLOSED)),
              IsRtcOk());
  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<Socket> client(
      socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  sink.Monitor(client.get());

  // Create server and listen.
  std::unique_ptr<Socket> server(
      socket_factory_->CreateSocket(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_THAT(WaitUntil([&] { return (sink.Check(server.get(), SSE_READ)); },
                        ::testing::IsTrue()),
              IsRtcOk());
  std::unique_ptr<Socket> accepted(server->Accept(&accept_addr));
  ASSERT_TRUE(accepted);
  sink.Monitor(accepted.get());

  // Both sides are now connected.
  EXPECT_THAT(WaitUntil([&] { return client->GetState(); },
                        ::testing::Eq(Socket::CS_CONNECTED)),
              IsRtcOk());
  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_THAT(WaitUntil([&] { return sink.Check(accepted.get(), SSE_WRITE); },
                        ::testing::IsTrue()),
              IsRtcOk());

  // Fill the socket buffer.
  char buf[1024 * 16] = {0};
  int sends = 0;
  while (++sends && accepted->Send(&buf, std::size(buf)) != -1) {
  }
  EXPECT_TRUE(accepted->IsBlocking());

  // Wait until data is available.
  EXPECT_THAT(WaitUntil([&] { return sink.Check(client.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());

  // Pull data.
  for (int i = 0; i < sends; ++i) {
    client->Recv(buf, std::size(buf), nullptr);
  }

  // Expect at least one additional writable callback.
  EXPECT_THAT(WaitUntil([&] { return sink.Check(accepted.get(), SSE_WRITE); },
                        ::testing::IsTrue()),
              IsRtcOk());

  // 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, std::size(buf));
    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.
  Socket* socket = socket_factory_->CreateSocket(loopback.family(), SOCK_DGRAM);
  EXPECT_EQ(Socket::CS_CLOSED, socket->GetState());
  EXPECT_EQ(0, socket->Bind(SocketAddress(loopback, 0)));
  SocketAddress addr1 = socket->GetLocalAddress();
  EXPECT_EQ(0, socket->Connect(addr1));
  EXPECT_EQ(Socket::CS_CONNECTED, socket->GetState());
  socket->Close();
  EXPECT_EQ(Socket::CS_CLOSED, socket->GetState());
  delete socket;

  // Test send/receive behavior.
  auto client1 = std::make_unique<TestClient>(
      absl::WrapUnique(AsyncUDPSocket::Create(socket_factory_, addr1)));
  auto client2 = std::make_unique<TestClient>(
      absl::WrapUnique(AsyncUDPSocket::Create(socket_factory_, 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 = std::make_unique<TestClient>(
        absl::WrapUnique(AsyncUDPSocket::Create(socket_factory_, 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
  auto client = std::make_unique<TestClient>(
      absl::WrapUnique(AsyncUDPSocket::Create(socket_factory_, 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(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 + 5000 > 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) {
        RTC_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_THAT(
      WaitUntil([&] { return client->ready_to_send(); }, ::testing::IsTrue()),
      IsRtcOk());
  RTC_LOG(LS_INFO) << "Got SignalReadyToSend";
}

void SocketTest::GetSetOptionsInternal(const IPAddress& loopback) {
  std::unique_ptr<Socket> socket(
      socket_factory_->CreateSocket(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, &current_nd));
  ASSERT_EQ(-1, socket->SetOption(Socket::OPT_NODELAY, desired_nd));

#if defined(WEBRTC_POSIX)
  // Check DSCP.
  int current_dscp, desired_dscp = 1;
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_DSCP, &current_dscp));
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_DSCP, desired_dscp));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_DSCP, &current_dscp));
  ASSERT_EQ(desired_dscp, current_dscp);

  int current_send_esn, desired_send_esn = 1;
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_SEND_ECN, &current_send_esn));
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_SEND_ECN, desired_send_esn));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_SEND_ECN, &current_send_esn));
  ASSERT_EQ(current_send_esn, desired_send_esn);

  int current_recv_esn, desired_recv_esn = 1;
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_RECV_ECN, &current_recv_esn));
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_RECV_ECN, desired_recv_esn));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_RECV_ECN, &current_recv_esn));
  ASSERT_EQ(current_recv_esn, desired_recv_esn);
#endif

  // Prepare on TCP specific options.
  socket.reset(socket_factory_->CreateSocket(loopback.family(), SOCK_STREAM));
  socket->Bind(SocketAddress(loopback, 0));

  // Check that we can set NODELAY on a TCP socket.
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_NODELAY, desired_nd));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_NODELAY, &current_nd));
  ASSERT_NE(0, current_nd);

  // Check TCP Keep Alive settings.
  int current_kl, desired_kl = 1;
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_KEEPALIVE, desired_kl));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_KEEPALIVE, &current_kl));
  ASSERT_NE(0, current_kl);

  int current_kl_cnt, desired_kl_cnt = 3;
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_KEEPCNT, desired_kl_cnt));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_TCP_KEEPCNT, &current_kl_cnt));
  ASSERT_EQ(desired_kl_cnt, current_kl_cnt);

  int current_kl_idle, desired_kl_idle = 2;
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_KEEPIDLE, desired_kl_idle));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_TCP_KEEPIDLE, &current_kl_idle));
  ASSERT_EQ(desired_kl_idle, current_kl_idle);

  int current_kl_intvl, desired_kl_intvl = 2;
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_KEEPINTVL, desired_kl_intvl));
  ASSERT_NE(-1,
            socket->GetOption(Socket::OPT_TCP_KEEPINTVL, &current_kl_intvl));
  ASSERT_EQ(desired_kl_intvl, current_kl_intvl);

#if defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
  int current_ut, desired_ut = 10;
  ASSERT_NE(-1, socket->SetOption(Socket::OPT_TCP_USER_TIMEOUT, desired_ut));
  ASSERT_NE(-1, socket->GetOption(Socket::OPT_TCP_USER_TIMEOUT, &current_ut));
  ASSERT_EQ(desired_ut, current_ut);
#endif
}

void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
  StreamSink sink;
  std::unique_ptr<Socket> socket(
      socket_factory_->CreateSocket(loopback.family(), SOCK_DGRAM));
  EXPECT_EQ(0, socket->Bind(SocketAddress(loopback, 0)));
  SocketAddress address = socket->GetLocalAddress();
  sink.Monitor(socket.get());

  int64_t send_time_1 = TimeMicros();
  socket->SendTo("foo", 3, address);

  // Wait until data is available.
  EXPECT_THAT(WaitUntil([&] { return sink.Check(socket.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  Buffer buffer;
  Socket::ReceiveBuffer receive_buffer_1(buffer);
  ASSERT_GT(socket->RecvFrom(receive_buffer_1), 0);

  const int64_t kTimeBetweenPacketsMs = 100;
  Thread::SleepMs(kTimeBetweenPacketsMs);

  int64_t send_time_2 = TimeMicros();
  socket->SendTo("bar", 3, address);
  // Wait until data is available.
  EXPECT_THAT(WaitUntil([&] { return sink.Check(socket.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  Socket::ReceiveBuffer receive_buffer_2(buffer);
  ASSERT_GT(socket->RecvFrom(receive_buffer_2), 0);

  int64_t system_time_diff = send_time_2 - send_time_1;
  int64_t recv_timestamp_diff =
      receive_buffer_2.arrival_time->us() - receive_buffer_1.arrival_time->us();
  // 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);
}

void SocketTest::UdpSocketRecvTimestampUseRtcEpoch(const IPAddress& loopback) {
  SocketAddress empty = EmptySocketAddressWithFamily(loopback.family());
  std::unique_ptr<Socket> socket(
      socket_factory_->CreateSocket(loopback.family(), SOCK_DGRAM));
  ASSERT_EQ(socket->Bind(SocketAddress(loopback, 0)), 0);
  SocketAddress address = socket->GetLocalAddress();
  socket = nullptr;

  auto client1 = std::make_unique<TestClient>(
      absl::WrapUnique(AsyncUDPSocket::Create(socket_factory_, address)));
  auto client2 = std::make_unique<TestClient>(
      absl::WrapUnique(AsyncUDPSocket::Create(socket_factory_, empty)));

  SocketAddress addr2;
  client2->SendTo("foo", 3, address);
  std::unique_ptr<TestClient::Packet> packet_1 = client1->NextPacket(10000);
  ASSERT_TRUE(packet_1 != nullptr);
  EXPECT_NEAR(packet_1->packet_time->us(), TimeMicros(), 1000'000);

  Thread::SleepMs(100);
  client2->SendTo("bar", 3, address);
  std::unique_ptr<TestClient::Packet> packet_2 = client1->NextPacket(10000);
  ASSERT_TRUE(packet_2 != nullptr);
  EXPECT_GT(packet_2->packet_time->us(), packet_1->packet_time->us());
  EXPECT_NEAR(packet_2->packet_time->us(), TimeMicros(), 1000'000);
}

void SocketTest::SocketSendRecvWithEcn(const IPAddress& loopback) {
  StreamSink sink;
  std::unique_ptr<Socket> socket(
      socket_factory_->CreateSocket(loopback.family(), SOCK_DGRAM));
  EXPECT_EQ(0, socket->Bind(SocketAddress(loopback, 0)));
  SocketAddress address = socket->GetLocalAddress();
  sink.Monitor(socket.get());
  Buffer buffer;
  Socket::ReceiveBuffer receive_buffer(buffer);

  socket->SendTo("foo", 3, address);
  EXPECT_THAT(WaitUntil([&] { return sink.Check(socket.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  ASSERT_GT(socket->RecvFrom(receive_buffer), 0);
  EXPECT_EQ(receive_buffer.ecn, EcnMarking::kNotEct);

  socket->SetOption(Socket::OPT_SEND_ECN, 1);  // Ect(1)
  socket->SetOption(Socket::OPT_RECV_ECN, 1);

  socket->SendTo("bar", 3, address);
  EXPECT_THAT(WaitUntil([&] { return sink.Check(socket.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  ASSERT_GT(socket->RecvFrom(receive_buffer), 0);
  EXPECT_EQ(receive_buffer.ecn, EcnMarking::kEct1);

  socket->SetOption(Socket::OPT_SEND_ECN, 2);  // Ect(0)
  socket->SendTo("bar", 3, address);
  EXPECT_THAT(WaitUntil([&] { return sink.Check(socket.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  ASSERT_GT(socket->RecvFrom(receive_buffer), 0);
  EXPECT_EQ(receive_buffer.ecn, EcnMarking::kEct0);

  socket->SetOption(Socket::OPT_SEND_ECN, 3);  // Ce
  socket->SendTo("bar", 3, address);
  EXPECT_THAT(WaitUntil([&] { return sink.Check(socket.get(), SSE_READ); },
                        ::testing::IsTrue()),
              IsRtcOk());
  ASSERT_GT(socket->RecvFrom(receive_buffer), 0);
  EXPECT_EQ(receive_buffer.ecn, EcnMarking::kCe);
}

}  // namespace webrtc
