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