Files
platform-external-webrtc/webrtc/p2p/base/udptransport_unittest.cc
deadbeef d1c0998730 Adding OrtcFactory, and changing UdpTransport to match current plan.
The factory follows the same principles as PeerConnectionFactory;
various modules can be passed into its constructor but default
implementations are provided. Currently the only object the factory can
create is a UdpTransport (need to start somewhere).

UdpTransportChannel (renamed to UdpTransport)
will now accept a socket passed into its constructor,
relying on the factory to create the socket. This allows some
simplifications to be made, such as getting rid of "State" since the
only states are now "has destination set or doesn't".

BUG=webrtc:7013

Review-Url: https://codereview.webrtc.org/2632613002
Cr-Commit-Position: refs/heads/master@{#16154}
2017-01-18 23:16:37 +00:00

196 lines
7.3 KiB
C++

/*
* Copyright 2016 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 <algorithm>
#include <list>
#include <memory>
#include <utility>
#include <vector>
#include "webrtc/base/gunit.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/asyncpacketsocket.h"
#include "webrtc/base/ipaddress.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/socketaddress.h"
#include "webrtc/base/socketserver.h"
#include "webrtc/base/virtualsocketserver.h"
#include "webrtc/p2p/base/basicpacketsocketfactory.h"
#include "webrtc/p2p/base/packettransportinterface.h"
#include "webrtc/p2p/base/udptransport.h"
namespace cricket {
constexpr int kTimeoutMs = 10000;
static const rtc::IPAddress kIPv4LocalHostAddress =
rtc::IPAddress(0x7F000001); // 127.0.0.1
class UdpTransportTest : public testing::Test, public sigslot::has_slots<> {
public:
UdpTransportTest()
: network_thread_(rtc::Thread::Current()),
physical_socket_server_(new rtc::PhysicalSocketServer),
virtual_socket_server_(
new rtc::VirtualSocketServer(physical_socket_server_.get())),
ss_scope_(virtual_socket_server_.get()),
ep1_("Name1",
std::unique_ptr<rtc::AsyncPacketSocket>(
socket_factory_.CreateUdpSocket(
rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0),
0,
0))),
ep2_("Name2",
std::unique_ptr<rtc::AsyncPacketSocket>(
socket_factory_.CreateUdpSocket(
rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0),
0,
0))) {
// Setup IP Address for outgoing packets from sockets bound to IPV4
// INADDR_ANY ("0.0.0.0."), as used above when creating the virtual
// sockets. The virtual socket server sends these packets only if the
// default address is explicit set. With a physical socket, the actual
// network stack / operating system would set the IP address for outgoing
// packets.
virtual_socket_server_->SetDefaultRoute(kIPv4LocalHostAddress);
}
struct Endpoint : public sigslot::has_slots<> {
explicit Endpoint(std::string tch_name,
std::unique_ptr<rtc::AsyncPacketSocket> socket) {
ch_.reset(new UdpTransport(std::move(tch_name), std::move(socket)));
ch_->SignalReadPacket.connect(this, &Endpoint::OnReadPacket);
ch_->SignalSentPacket.connect(this, &Endpoint::OnSentPacket);
ch_->SignalReadyToSend.connect(this, &Endpoint::OnReadyToSend);
ch_->SignalWritableState.connect(this, &Endpoint::OnWritableState);
}
bool CheckData(const char* data, int len) {
bool ret = false;
if (!ch_packets_.empty()) {
std::string packet = ch_packets_.front();
ret = (packet == std::string(data, len));
ch_packets_.pop_front();
}
return ret;
}
void OnWritableState(rtc::PacketTransportInterface* transport) {
num_sig_writable_++;
}
void OnReadyToSend(rtc::PacketTransportInterface* transport) {
num_sig_ready_to_send_++;
}
void OnReadPacket(rtc::PacketTransportInterface* transport,
const char* data,
size_t len,
const rtc::PacketTime& packet_time,
int flags) {
num_received_packets_++;
LOG(LS_VERBOSE) << "OnReadPacket (unittest)";
ch_packets_.push_front(std::string(data, len));
}
void OnSentPacket(rtc::PacketTransportInterface* transport,
const rtc::SentPacket&) {
num_sig_sent_packets_++;
}
int SendData(const char* data, size_t len) {
rtc::PacketOptions options;
return ch_->SendPacket(data, len, options, 0);
}
void GetLocalPort(uint16_t* local_port) {
*local_port = ch_->GetLocalAddress().port();
}
std::list<std::string> ch_packets_;
std::unique_ptr<UdpTransport> ch_;
uint32_t num_received_packets_ = 0; // Increases on SignalReadPacket.
uint32_t num_sig_sent_packets_ = 0; // Increases on SignalSentPacket.
uint32_t num_sig_writable_ = 0; // Increases on SignalWritable.
uint32_t num_sig_ready_to_send_ = 0; // Increases on SignalReadyToSend.
};
rtc::Thread* network_thread_ = nullptr;
std::unique_ptr<rtc::PhysicalSocketServer> physical_socket_server_;
std::unique_ptr<rtc::VirtualSocketServer> virtual_socket_server_;
rtc::SocketServerScope ss_scope_;
// Uses current thread's socket server, which will be set by ss_scope_.
rtc::BasicPacketSocketFactory socket_factory_;
Endpoint ep1_;
Endpoint ep2_;
void TestSendRecv() {
for (uint32_t i = 0; i < 5; ++i) {
static const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
int len = static_cast<int>(strlen(data));
// local_channel <==> remote_channel
EXPECT_EQ_WAIT(len, ep1_.SendData(data, len), kTimeoutMs);
EXPECT_TRUE_WAIT(ep2_.CheckData(data, len), kTimeoutMs);
EXPECT_EQ_WAIT(i + 1u, ep2_.num_received_packets_, kTimeoutMs);
EXPECT_EQ_WAIT(len, ep2_.SendData(data, len), kTimeoutMs);
EXPECT_TRUE_WAIT(ep1_.CheckData(data, len), kTimeoutMs);
EXPECT_EQ_WAIT(i + 1u, ep1_.num_received_packets_, kTimeoutMs);
}
}
};
TEST_F(UdpTransportTest, AddressGetters) {
// Initially, remote address should be nil but local address shouldn't be.
EXPECT_FALSE(ep1_.ch_->GetLocalAddress().IsNil());
EXPECT_TRUE(ep1_.ch_->GetRemoteAddress().IsNil());
rtc::SocketAddress destination("127.0.0.1", 1337);
ASSERT_TRUE(ep1_.ch_->SetRemoteAddress(destination));
EXPECT_EQ(destination, ep1_.ch_->GetRemoteAddress());
}
// Setting an invalid address should fail and have no effect.
TEST_F(UdpTransportTest, SettingIncompleteRemoteAddressFails) {
EXPECT_FALSE(ep1_.ch_->SetRemoteAddress(rtc::SocketAddress("127.0.0.1", 0)));
EXPECT_TRUE(ep1_.ch_->GetRemoteAddress().IsNil());
}
TEST_F(UdpTransportTest, SendRecvBasic) {
uint16_t port;
ep2_.GetLocalPort(&port);
rtc::SocketAddress addr2 = rtc::SocketAddress("127.0.0.1", port);
EXPECT_TRUE(ep1_.ch_->SetRemoteAddress(addr2));
ep1_.GetLocalPort(&port);
rtc::SocketAddress addr1 = rtc::SocketAddress("127.0.0.1", port);
EXPECT_TRUE(ep2_.ch_->SetRemoteAddress(addr1));
TestSendRecv();
}
// Test the signals and state methods used internally by causing a UdpTransport
// to send a packet to itself.
TEST_F(UdpTransportTest, StatusAndSignals) {
EXPECT_EQ(0u, ep1_.num_sig_writable_);
EXPECT_EQ(0u, ep1_.num_sig_ready_to_send_);
// Loopback
EXPECT_TRUE(!ep1_.ch_->writable());
rtc::SocketAddress addr = ep1_.ch_->GetLocalAddress();
// Keep port, but explicitly set IP.
addr.SetIP("127.0.0.1");
ep1_.ch_->SetRemoteAddress(addr);
EXPECT_TRUE(ep1_.ch_->writable());
EXPECT_EQ(1u, ep1_.num_sig_writable_);
EXPECT_EQ(1u, ep1_.num_sig_ready_to_send_);
const char data[] = "abc";
ep1_.SendData(data, sizeof(data));
EXPECT_EQ_WAIT(1u, ep1_.ch_packets_.size(), kTimeoutMs);
EXPECT_EQ_WAIT(1u, ep1_.num_sig_sent_packets_, kTimeoutMs);
}
} // namespace cricket