1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/test_client.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <string.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker namespace rtc {
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker // DESIGN: Each packet received is put it into a list of packets.
25*d9f75844SAndroid Build Coastguard Worker // Callers can retrieve received packets from any thread by calling
26*d9f75844SAndroid Build Coastguard Worker // NextPacket.
27*d9f75844SAndroid Build Coastguard Worker
TestClient(std::unique_ptr<AsyncPacketSocket> socket)28*d9f75844SAndroid Build Coastguard Worker TestClient::TestClient(std::unique_ptr<AsyncPacketSocket> socket)
29*d9f75844SAndroid Build Coastguard Worker : TestClient(std::move(socket), nullptr) {}
30*d9f75844SAndroid Build Coastguard Worker
TestClient(std::unique_ptr<AsyncPacketSocket> socket,ThreadProcessingFakeClock * fake_clock)31*d9f75844SAndroid Build Coastguard Worker TestClient::TestClient(std::unique_ptr<AsyncPacketSocket> socket,
32*d9f75844SAndroid Build Coastguard Worker ThreadProcessingFakeClock* fake_clock)
33*d9f75844SAndroid Build Coastguard Worker : fake_clock_(fake_clock),
34*d9f75844SAndroid Build Coastguard Worker socket_(std::move(socket)),
35*d9f75844SAndroid Build Coastguard Worker prev_packet_timestamp_(-1) {
36*d9f75844SAndroid Build Coastguard Worker socket_->SignalReadPacket.connect(this, &TestClient::OnPacket);
37*d9f75844SAndroid Build Coastguard Worker socket_->SignalReadyToSend.connect(this, &TestClient::OnReadyToSend);
38*d9f75844SAndroid Build Coastguard Worker }
39*d9f75844SAndroid Build Coastguard Worker
~TestClient()40*d9f75844SAndroid Build Coastguard Worker TestClient::~TestClient() {}
41*d9f75844SAndroid Build Coastguard Worker
CheckConnState(AsyncPacketSocket::State state)42*d9f75844SAndroid Build Coastguard Worker bool TestClient::CheckConnState(AsyncPacketSocket::State state) {
43*d9f75844SAndroid Build Coastguard Worker // Wait for our timeout value until the socket reaches the desired state.
44*d9f75844SAndroid Build Coastguard Worker int64_t end = TimeAfter(kTimeoutMs);
45*d9f75844SAndroid Build Coastguard Worker while (socket_->GetState() != state && TimeUntil(end) > 0) {
46*d9f75844SAndroid Build Coastguard Worker AdvanceTime(1);
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker return (socket_->GetState() == state);
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker
Send(const char * buf,size_t size)51*d9f75844SAndroid Build Coastguard Worker int TestClient::Send(const char* buf, size_t size) {
52*d9f75844SAndroid Build Coastguard Worker rtc::PacketOptions options;
53*d9f75844SAndroid Build Coastguard Worker return socket_->Send(buf, size, options);
54*d9f75844SAndroid Build Coastguard Worker }
55*d9f75844SAndroid Build Coastguard Worker
SendTo(const char * buf,size_t size,const SocketAddress & dest)56*d9f75844SAndroid Build Coastguard Worker int TestClient::SendTo(const char* buf,
57*d9f75844SAndroid Build Coastguard Worker size_t size,
58*d9f75844SAndroid Build Coastguard Worker const SocketAddress& dest) {
59*d9f75844SAndroid Build Coastguard Worker rtc::PacketOptions options;
60*d9f75844SAndroid Build Coastguard Worker return socket_->SendTo(buf, size, dest, options);
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker
NextPacket(int timeout_ms)63*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TestClient::Packet> TestClient::NextPacket(int timeout_ms) {
64*d9f75844SAndroid Build Coastguard Worker // If no packets are currently available, we go into a get/dispatch loop for
65*d9f75844SAndroid Build Coastguard Worker // at most timeout_ms. If, during the loop, a packet arrives, then we can
66*d9f75844SAndroid Build Coastguard Worker // stop early and return it.
67*d9f75844SAndroid Build Coastguard Worker
68*d9f75844SAndroid Build Coastguard Worker // Note that the case where no packet arrives is important. We often want to
69*d9f75844SAndroid Build Coastguard Worker // test that a packet does not arrive.
70*d9f75844SAndroid Build Coastguard Worker
71*d9f75844SAndroid Build Coastguard Worker // Note also that we only try to pump our current thread's message queue.
72*d9f75844SAndroid Build Coastguard Worker // Pumping another thread's queue could lead to messages being dispatched from
73*d9f75844SAndroid Build Coastguard Worker // the wrong thread to non-thread-safe objects.
74*d9f75844SAndroid Build Coastguard Worker
75*d9f75844SAndroid Build Coastguard Worker int64_t end = TimeAfter(timeout_ms);
76*d9f75844SAndroid Build Coastguard Worker while (TimeUntil(end) > 0) {
77*d9f75844SAndroid Build Coastguard Worker {
78*d9f75844SAndroid Build Coastguard Worker webrtc::MutexLock lock(&mutex_);
79*d9f75844SAndroid Build Coastguard Worker if (packets_.size() != 0) {
80*d9f75844SAndroid Build Coastguard Worker break;
81*d9f75844SAndroid Build Coastguard Worker }
82*d9f75844SAndroid Build Coastguard Worker }
83*d9f75844SAndroid Build Coastguard Worker AdvanceTime(1);
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker // Return the first packet placed in the queue.
87*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Packet> packet;
88*d9f75844SAndroid Build Coastguard Worker webrtc::MutexLock lock(&mutex_);
89*d9f75844SAndroid Build Coastguard Worker if (packets_.size() > 0) {
90*d9f75844SAndroid Build Coastguard Worker packet = std::move(packets_.front());
91*d9f75844SAndroid Build Coastguard Worker packets_.erase(packets_.begin());
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker return packet;
95*d9f75844SAndroid Build Coastguard Worker }
96*d9f75844SAndroid Build Coastguard Worker
CheckNextPacket(const char * buf,size_t size,SocketAddress * addr)97*d9f75844SAndroid Build Coastguard Worker bool TestClient::CheckNextPacket(const char* buf,
98*d9f75844SAndroid Build Coastguard Worker size_t size,
99*d9f75844SAndroid Build Coastguard Worker SocketAddress* addr) {
100*d9f75844SAndroid Build Coastguard Worker bool res = false;
101*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Packet> packet = NextPacket(kTimeoutMs);
102*d9f75844SAndroid Build Coastguard Worker if (packet) {
103*d9f75844SAndroid Build Coastguard Worker res = (packet->size == size && memcmp(packet->buf, buf, size) == 0 &&
104*d9f75844SAndroid Build Coastguard Worker CheckTimestamp(packet->packet_time_us));
105*d9f75844SAndroid Build Coastguard Worker if (addr)
106*d9f75844SAndroid Build Coastguard Worker *addr = packet->addr;
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker return res;
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker
CheckTimestamp(int64_t packet_timestamp)111*d9f75844SAndroid Build Coastguard Worker bool TestClient::CheckTimestamp(int64_t packet_timestamp) {
112*d9f75844SAndroid Build Coastguard Worker bool res = true;
113*d9f75844SAndroid Build Coastguard Worker if (packet_timestamp == -1) {
114*d9f75844SAndroid Build Coastguard Worker res = false;
115*d9f75844SAndroid Build Coastguard Worker }
116*d9f75844SAndroid Build Coastguard Worker if (prev_packet_timestamp_ != -1) {
117*d9f75844SAndroid Build Coastguard Worker if (packet_timestamp < prev_packet_timestamp_) {
118*d9f75844SAndroid Build Coastguard Worker res = false;
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker }
121*d9f75844SAndroid Build Coastguard Worker prev_packet_timestamp_ = packet_timestamp;
122*d9f75844SAndroid Build Coastguard Worker return res;
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker
AdvanceTime(int ms)125*d9f75844SAndroid Build Coastguard Worker void TestClient::AdvanceTime(int ms) {
126*d9f75844SAndroid Build Coastguard Worker // If the test is using a fake clock, we must advance the fake clock to
127*d9f75844SAndroid Build Coastguard Worker // advance time. Otherwise, ProcessMessages will work.
128*d9f75844SAndroid Build Coastguard Worker if (fake_clock_) {
129*d9f75844SAndroid Build Coastguard Worker SIMULATED_WAIT(false, ms, *fake_clock_);
130*d9f75844SAndroid Build Coastguard Worker } else {
131*d9f75844SAndroid Build Coastguard Worker Thread::Current()->ProcessMessages(1);
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker
CheckNoPacket()135*d9f75844SAndroid Build Coastguard Worker bool TestClient::CheckNoPacket() {
136*d9f75844SAndroid Build Coastguard Worker return NextPacket(kNoPacketTimeoutMs) == nullptr;
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker
GetError()139*d9f75844SAndroid Build Coastguard Worker int TestClient::GetError() {
140*d9f75844SAndroid Build Coastguard Worker return socket_->GetError();
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker
SetOption(Socket::Option opt,int value)143*d9f75844SAndroid Build Coastguard Worker int TestClient::SetOption(Socket::Option opt, int value) {
144*d9f75844SAndroid Build Coastguard Worker return socket_->SetOption(opt, value);
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker
OnPacket(AsyncPacketSocket * socket,const char * buf,size_t size,const SocketAddress & remote_addr,const int64_t & packet_time_us)147*d9f75844SAndroid Build Coastguard Worker void TestClient::OnPacket(AsyncPacketSocket* socket,
148*d9f75844SAndroid Build Coastguard Worker const char* buf,
149*d9f75844SAndroid Build Coastguard Worker size_t size,
150*d9f75844SAndroid Build Coastguard Worker const SocketAddress& remote_addr,
151*d9f75844SAndroid Build Coastguard Worker const int64_t& packet_time_us) {
152*d9f75844SAndroid Build Coastguard Worker webrtc::MutexLock lock(&mutex_);
153*d9f75844SAndroid Build Coastguard Worker packets_.push_back(
154*d9f75844SAndroid Build Coastguard Worker std::make_unique<Packet>(remote_addr, buf, size, packet_time_us));
155*d9f75844SAndroid Build Coastguard Worker }
156*d9f75844SAndroid Build Coastguard Worker
OnReadyToSend(AsyncPacketSocket * socket)157*d9f75844SAndroid Build Coastguard Worker void TestClient::OnReadyToSend(AsyncPacketSocket* socket) {
158*d9f75844SAndroid Build Coastguard Worker ++ready_to_send_count_;
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker
Packet(const SocketAddress & a,const char * b,size_t s,int64_t packet_time_us)161*d9f75844SAndroid Build Coastguard Worker TestClient::Packet::Packet(const SocketAddress& a,
162*d9f75844SAndroid Build Coastguard Worker const char* b,
163*d9f75844SAndroid Build Coastguard Worker size_t s,
164*d9f75844SAndroid Build Coastguard Worker int64_t packet_time_us)
165*d9f75844SAndroid Build Coastguard Worker : addr(a), buf(0), size(s), packet_time_us(packet_time_us) {
166*d9f75844SAndroid Build Coastguard Worker buf = new char[size];
167*d9f75844SAndroid Build Coastguard Worker memcpy(buf, b, size);
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker
Packet(const Packet & p)170*d9f75844SAndroid Build Coastguard Worker TestClient::Packet::Packet(const Packet& p)
171*d9f75844SAndroid Build Coastguard Worker : addr(p.addr), buf(0), size(p.size), packet_time_us(p.packet_time_us) {
172*d9f75844SAndroid Build Coastguard Worker buf = new char[size];
173*d9f75844SAndroid Build Coastguard Worker memcpy(buf, p.buf, size);
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker
~Packet()176*d9f75844SAndroid Build Coastguard Worker TestClient::Packet::~Packet() {
177*d9f75844SAndroid Build Coastguard Worker delete[] buf;
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker
180*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
181