1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2011 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 "p2p/base/pseudo_tcp.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 <algorithm>
16*d9f75844SAndroid Build Coastguard Worker #include <cstddef>
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker #include <utility>
19*d9f75844SAndroid Build Coastguard Worker #include <vector>
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/pending_task_safety_flag.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/memory_stream.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
29*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker using ::cricket::PseudoTcp;
32*d9f75844SAndroid Build Coastguard Worker using ::webrtc::ScopedTaskSafety;
33*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TaskQueueBase;
34*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TimeDelta;
35*d9f75844SAndroid Build Coastguard Worker
36*d9f75844SAndroid Build Coastguard Worker static const int kConnectTimeoutMs = 10000; // ~3 * default RTO of 3000ms
37*d9f75844SAndroid Build Coastguard Worker static const int kTransferTimeoutMs = 15000;
38*d9f75844SAndroid Build Coastguard Worker static const int kBlockSize = 4096;
39*d9f75844SAndroid Build Coastguard Worker
40*d9f75844SAndroid Build Coastguard Worker class PseudoTcpForTest : public cricket::PseudoTcp {
41*d9f75844SAndroid Build Coastguard Worker public:
PseudoTcpForTest(cricket::IPseudoTcpNotify * notify,uint32_t conv)42*d9f75844SAndroid Build Coastguard Worker PseudoTcpForTest(cricket::IPseudoTcpNotify* notify, uint32_t conv)
43*d9f75844SAndroid Build Coastguard Worker : PseudoTcp(notify, conv) {}
44*d9f75844SAndroid Build Coastguard Worker
isReceiveBufferFull() const45*d9f75844SAndroid Build Coastguard Worker bool isReceiveBufferFull() const { return PseudoTcp::isReceiveBufferFull(); }
46*d9f75844SAndroid Build Coastguard Worker
disableWindowScale()47*d9f75844SAndroid Build Coastguard Worker void disableWindowScale() { PseudoTcp::disableWindowScale(); }
48*d9f75844SAndroid Build Coastguard Worker };
49*d9f75844SAndroid Build Coastguard Worker
50*d9f75844SAndroid Build Coastguard Worker class PseudoTcpTestBase : public ::testing::Test,
51*d9f75844SAndroid Build Coastguard Worker public cricket::IPseudoTcpNotify {
52*d9f75844SAndroid Build Coastguard Worker public:
PseudoTcpTestBase()53*d9f75844SAndroid Build Coastguard Worker PseudoTcpTestBase()
54*d9f75844SAndroid Build Coastguard Worker : local_(this, 1),
55*d9f75844SAndroid Build Coastguard Worker remote_(this, 1),
56*d9f75844SAndroid Build Coastguard Worker have_connected_(false),
57*d9f75844SAndroid Build Coastguard Worker have_disconnected_(false),
58*d9f75844SAndroid Build Coastguard Worker local_mtu_(65535),
59*d9f75844SAndroid Build Coastguard Worker remote_mtu_(65535),
60*d9f75844SAndroid Build Coastguard Worker delay_(0),
61*d9f75844SAndroid Build Coastguard Worker loss_(0) {
62*d9f75844SAndroid Build Coastguard Worker // Set use of the test RNG to get predictable loss patterns. Otherwise,
63*d9f75844SAndroid Build Coastguard Worker // this test would occasionally get really unlucky loss and time out.
64*d9f75844SAndroid Build Coastguard Worker rtc::SetRandomTestMode(true);
65*d9f75844SAndroid Build Coastguard Worker }
~PseudoTcpTestBase()66*d9f75844SAndroid Build Coastguard Worker ~PseudoTcpTestBase() {
67*d9f75844SAndroid Build Coastguard Worker // Put it back for the next test.
68*d9f75844SAndroid Build Coastguard Worker rtc::SetRandomTestMode(false);
69*d9f75844SAndroid Build Coastguard Worker }
70*d9f75844SAndroid Build Coastguard Worker // If true, both endpoints will send the "connect" segment simultaneously,
71*d9f75844SAndroid Build Coastguard Worker // rather than `local_` sending it followed by a response from `remote_`.
72*d9f75844SAndroid Build Coastguard Worker // Note that this is what chromoting ends up doing.
SetSimultaneousOpen(bool enabled)73*d9f75844SAndroid Build Coastguard Worker void SetSimultaneousOpen(bool enabled) { simultaneous_open_ = enabled; }
SetLocalMtu(int mtu)74*d9f75844SAndroid Build Coastguard Worker void SetLocalMtu(int mtu) {
75*d9f75844SAndroid Build Coastguard Worker local_.NotifyMTU(mtu);
76*d9f75844SAndroid Build Coastguard Worker local_mtu_ = mtu;
77*d9f75844SAndroid Build Coastguard Worker }
SetRemoteMtu(int mtu)78*d9f75844SAndroid Build Coastguard Worker void SetRemoteMtu(int mtu) {
79*d9f75844SAndroid Build Coastguard Worker remote_.NotifyMTU(mtu);
80*d9f75844SAndroid Build Coastguard Worker remote_mtu_ = mtu;
81*d9f75844SAndroid Build Coastguard Worker }
SetDelay(int delay)82*d9f75844SAndroid Build Coastguard Worker void SetDelay(int delay) { delay_ = delay; }
SetLoss(int percent)83*d9f75844SAndroid Build Coastguard Worker void SetLoss(int percent) { loss_ = percent; }
84*d9f75844SAndroid Build Coastguard Worker // Used to cause the initial "connect" segment to be lost, needed for a
85*d9f75844SAndroid Build Coastguard Worker // regression test.
DropNextPacket()86*d9f75844SAndroid Build Coastguard Worker void DropNextPacket() { drop_next_packet_ = true; }
SetOptNagling(bool enable_nagles)87*d9f75844SAndroid Build Coastguard Worker void SetOptNagling(bool enable_nagles) {
88*d9f75844SAndroid Build Coastguard Worker local_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles);
89*d9f75844SAndroid Build Coastguard Worker remote_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles);
90*d9f75844SAndroid Build Coastguard Worker }
SetOptAckDelay(int ack_delay)91*d9f75844SAndroid Build Coastguard Worker void SetOptAckDelay(int ack_delay) {
92*d9f75844SAndroid Build Coastguard Worker local_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay);
93*d9f75844SAndroid Build Coastguard Worker remote_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay);
94*d9f75844SAndroid Build Coastguard Worker }
SetOptSndBuf(int size)95*d9f75844SAndroid Build Coastguard Worker void SetOptSndBuf(int size) {
96*d9f75844SAndroid Build Coastguard Worker local_.SetOption(PseudoTcp::OPT_SNDBUF, size);
97*d9f75844SAndroid Build Coastguard Worker remote_.SetOption(PseudoTcp::OPT_SNDBUF, size);
98*d9f75844SAndroid Build Coastguard Worker }
SetRemoteOptRcvBuf(int size)99*d9f75844SAndroid Build Coastguard Worker void SetRemoteOptRcvBuf(int size) {
100*d9f75844SAndroid Build Coastguard Worker remote_.SetOption(PseudoTcp::OPT_RCVBUF, size);
101*d9f75844SAndroid Build Coastguard Worker }
SetLocalOptRcvBuf(int size)102*d9f75844SAndroid Build Coastguard Worker void SetLocalOptRcvBuf(int size) {
103*d9f75844SAndroid Build Coastguard Worker local_.SetOption(PseudoTcp::OPT_RCVBUF, size);
104*d9f75844SAndroid Build Coastguard Worker }
DisableRemoteWindowScale()105*d9f75844SAndroid Build Coastguard Worker void DisableRemoteWindowScale() { remote_.disableWindowScale(); }
DisableLocalWindowScale()106*d9f75844SAndroid Build Coastguard Worker void DisableLocalWindowScale() { local_.disableWindowScale(); }
107*d9f75844SAndroid Build Coastguard Worker
108*d9f75844SAndroid Build Coastguard Worker protected:
Connect()109*d9f75844SAndroid Build Coastguard Worker int Connect() {
110*d9f75844SAndroid Build Coastguard Worker int ret = local_.Connect();
111*d9f75844SAndroid Build Coastguard Worker if (ret == 0) {
112*d9f75844SAndroid Build Coastguard Worker UpdateLocalClock();
113*d9f75844SAndroid Build Coastguard Worker }
114*d9f75844SAndroid Build Coastguard Worker if (simultaneous_open_) {
115*d9f75844SAndroid Build Coastguard Worker ret = remote_.Connect();
116*d9f75844SAndroid Build Coastguard Worker if (ret == 0) {
117*d9f75844SAndroid Build Coastguard Worker UpdateRemoteClock();
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker return ret;
121*d9f75844SAndroid Build Coastguard Worker }
Close()122*d9f75844SAndroid Build Coastguard Worker void Close() {
123*d9f75844SAndroid Build Coastguard Worker local_.Close(false);
124*d9f75844SAndroid Build Coastguard Worker UpdateLocalClock();
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker
OnTcpOpen(PseudoTcp * tcp)127*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpOpen(PseudoTcp* tcp) {
128*d9f75844SAndroid Build Coastguard Worker // Consider ourselves connected when the local side gets OnTcpOpen.
129*d9f75844SAndroid Build Coastguard Worker // OnTcpWriteable isn't fired at open, so we trigger it now.
130*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Opened";
131*d9f75844SAndroid Build Coastguard Worker if (tcp == &local_) {
132*d9f75844SAndroid Build Coastguard Worker have_connected_ = true;
133*d9f75844SAndroid Build Coastguard Worker OnTcpWriteable(tcp);
134*d9f75844SAndroid Build Coastguard Worker }
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker // Test derived from the base should override
137*d9f75844SAndroid Build Coastguard Worker // virtual void OnTcpReadable(PseudoTcp* tcp)
138*d9f75844SAndroid Build Coastguard Worker // and
139*d9f75844SAndroid Build Coastguard Worker // virtual void OnTcpWritable(PseudoTcp* tcp)
OnTcpClosed(PseudoTcp * tcp,uint32_t error)140*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) {
141*d9f75844SAndroid Build Coastguard Worker // Consider ourselves closed when the remote side gets OnTcpClosed.
142*d9f75844SAndroid Build Coastguard Worker // TODO(?): OnTcpClosed is only ever notified in case of error in
143*d9f75844SAndroid Build Coastguard Worker // the current implementation. Solicited close is not (yet) supported.
144*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Closed";
145*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0U, error);
146*d9f75844SAndroid Build Coastguard Worker if (tcp == &remote_) {
147*d9f75844SAndroid Build Coastguard Worker have_disconnected_ = true;
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker }
TcpWritePacket(PseudoTcp * tcp,const char * buffer,size_t len)150*d9f75844SAndroid Build Coastguard Worker virtual WriteResult TcpWritePacket(PseudoTcp* tcp,
151*d9f75844SAndroid Build Coastguard Worker const char* buffer,
152*d9f75844SAndroid Build Coastguard Worker size_t len) {
153*d9f75844SAndroid Build Coastguard Worker // Drop a packet if the test called DropNextPacket.
154*d9f75844SAndroid Build Coastguard Worker if (drop_next_packet_) {
155*d9f75844SAndroid Build Coastguard Worker drop_next_packet_ = false;
156*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Dropping packet due to DropNextPacket, size="
157*d9f75844SAndroid Build Coastguard Worker << len;
158*d9f75844SAndroid Build Coastguard Worker return WR_SUCCESS;
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker // Randomly drop the desired percentage of packets.
161*d9f75844SAndroid Build Coastguard Worker if (rtc::CreateRandomId() % 100 < static_cast<uint32_t>(loss_)) {
162*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Randomly dropping packet, size=" << len;
163*d9f75844SAndroid Build Coastguard Worker return WR_SUCCESS;
164*d9f75844SAndroid Build Coastguard Worker }
165*d9f75844SAndroid Build Coastguard Worker // Also drop packets that are larger than the configured MTU.
166*d9f75844SAndroid Build Coastguard Worker if (len > static_cast<size_t>(std::min(local_mtu_, remote_mtu_))) {
167*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Dropping packet that exceeds path MTU, size="
168*d9f75844SAndroid Build Coastguard Worker << len;
169*d9f75844SAndroid Build Coastguard Worker return WR_SUCCESS;
170*d9f75844SAndroid Build Coastguard Worker }
171*d9f75844SAndroid Build Coastguard Worker PseudoTcp* other;
172*d9f75844SAndroid Build Coastguard Worker ScopedTaskSafety* timer;
173*d9f75844SAndroid Build Coastguard Worker if (tcp == &local_) {
174*d9f75844SAndroid Build Coastguard Worker other = &remote_;
175*d9f75844SAndroid Build Coastguard Worker timer = &remote_timer_;
176*d9f75844SAndroid Build Coastguard Worker } else {
177*d9f75844SAndroid Build Coastguard Worker other = &local_;
178*d9f75844SAndroid Build Coastguard Worker timer = &local_timer_;
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker std::string packet(buffer, len);
181*d9f75844SAndroid Build Coastguard Worker ++packets_in_flight_;
182*d9f75844SAndroid Build Coastguard Worker TaskQueueBase::Current()->PostDelayedTask(
183*d9f75844SAndroid Build Coastguard Worker [other, timer, packet = std::move(packet), this] {
184*d9f75844SAndroid Build Coastguard Worker --packets_in_flight_;
185*d9f75844SAndroid Build Coastguard Worker other->NotifyPacket(packet.c_str(), packet.size());
186*d9f75844SAndroid Build Coastguard Worker UpdateClock(*other, *timer);
187*d9f75844SAndroid Build Coastguard Worker },
188*d9f75844SAndroid Build Coastguard Worker TimeDelta::Millis(delay_));
189*d9f75844SAndroid Build Coastguard Worker return WR_SUCCESS;
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker
UpdateLocalClock()192*d9f75844SAndroid Build Coastguard Worker void UpdateLocalClock() { UpdateClock(local_, local_timer_); }
UpdateRemoteClock()193*d9f75844SAndroid Build Coastguard Worker void UpdateRemoteClock() { UpdateClock(remote_, remote_timer_); }
UpdateClock(PseudoTcp & tcp,ScopedTaskSafety & timer)194*d9f75844SAndroid Build Coastguard Worker static void UpdateClock(PseudoTcp& tcp, ScopedTaskSafety& timer) {
195*d9f75844SAndroid Build Coastguard Worker long interval = 0; // NOLINT
196*d9f75844SAndroid Build Coastguard Worker tcp.GetNextClock(PseudoTcp::Now(), interval);
197*d9f75844SAndroid Build Coastguard Worker interval = std::max<int>(interval, 0L); // sometimes interval is < 0
198*d9f75844SAndroid Build Coastguard Worker timer.reset();
199*d9f75844SAndroid Build Coastguard Worker TaskQueueBase::Current()->PostDelayedTask(
200*d9f75844SAndroid Build Coastguard Worker SafeTask(timer.flag(),
201*d9f75844SAndroid Build Coastguard Worker [&tcp, &timer] {
202*d9f75844SAndroid Build Coastguard Worker tcp.NotifyClock(PseudoTcp::Now());
203*d9f75844SAndroid Build Coastguard Worker UpdateClock(tcp, timer);
204*d9f75844SAndroid Build Coastguard Worker }),
205*d9f75844SAndroid Build Coastguard Worker TimeDelta::Millis(interval));
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker
208*d9f75844SAndroid Build Coastguard Worker rtc::AutoThread main_thread_;
209*d9f75844SAndroid Build Coastguard Worker PseudoTcpForTest local_;
210*d9f75844SAndroid Build Coastguard Worker PseudoTcpForTest remote_;
211*d9f75844SAndroid Build Coastguard Worker ScopedTaskSafety local_timer_;
212*d9f75844SAndroid Build Coastguard Worker ScopedTaskSafety remote_timer_;
213*d9f75844SAndroid Build Coastguard Worker rtc::MemoryStream send_stream_;
214*d9f75844SAndroid Build Coastguard Worker rtc::MemoryStream recv_stream_;
215*d9f75844SAndroid Build Coastguard Worker bool have_connected_;
216*d9f75844SAndroid Build Coastguard Worker bool have_disconnected_;
217*d9f75844SAndroid Build Coastguard Worker int local_mtu_;
218*d9f75844SAndroid Build Coastguard Worker int remote_mtu_;
219*d9f75844SAndroid Build Coastguard Worker int delay_;
220*d9f75844SAndroid Build Coastguard Worker int loss_;
221*d9f75844SAndroid Build Coastguard Worker bool drop_next_packet_ = false;
222*d9f75844SAndroid Build Coastguard Worker bool simultaneous_open_ = false;
223*d9f75844SAndroid Build Coastguard Worker int packets_in_flight_ = 0;
224*d9f75844SAndroid Build Coastguard Worker };
225*d9f75844SAndroid Build Coastguard Worker
226*d9f75844SAndroid Build Coastguard Worker class PseudoTcpTest : public PseudoTcpTestBase {
227*d9f75844SAndroid Build Coastguard Worker public:
TestTransfer(int size)228*d9f75844SAndroid Build Coastguard Worker void TestTransfer(int size) {
229*d9f75844SAndroid Build Coastguard Worker uint32_t start;
230*d9f75844SAndroid Build Coastguard Worker int32_t elapsed;
231*d9f75844SAndroid Build Coastguard Worker size_t received;
232*d9f75844SAndroid Build Coastguard Worker // Create some dummy data to send.
233*d9f75844SAndroid Build Coastguard Worker send_stream_.ReserveSize(size);
234*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < size; ++i) {
235*d9f75844SAndroid Build Coastguard Worker uint8_t ch = static_cast<uint8_t>(i);
236*d9f75844SAndroid Build Coastguard Worker size_t written;
237*d9f75844SAndroid Build Coastguard Worker int error;
238*d9f75844SAndroid Build Coastguard Worker send_stream_.Write(rtc::MakeArrayView(&ch, 1), written, error);
239*d9f75844SAndroid Build Coastguard Worker }
240*d9f75844SAndroid Build Coastguard Worker send_stream_.Rewind();
241*d9f75844SAndroid Build Coastguard Worker // Prepare the receive stream.
242*d9f75844SAndroid Build Coastguard Worker recv_stream_.ReserveSize(size);
243*d9f75844SAndroid Build Coastguard Worker // Connect and wait until connected.
244*d9f75844SAndroid Build Coastguard Worker start = rtc::Time32();
245*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, Connect());
246*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs);
247*d9f75844SAndroid Build Coastguard Worker // Sending will start from OnTcpWriteable and complete when all data has
248*d9f75844SAndroid Build Coastguard Worker // been received.
249*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs);
250*d9f75844SAndroid Build Coastguard Worker elapsed = rtc::Time32() - start;
251*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetSize(&received);
252*d9f75844SAndroid Build Coastguard Worker // Ensure we closed down OK and we got the right data.
253*d9f75844SAndroid Build Coastguard Worker // TODO(?): Ensure the errors are cleared properly.
254*d9f75844SAndroid Build Coastguard Worker // EXPECT_EQ(0, local_.GetError());
255*d9f75844SAndroid Build Coastguard Worker // EXPECT_EQ(0, remote_.GetError());
256*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<size_t>(size), received);
257*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0,
258*d9f75844SAndroid Build Coastguard Worker memcmp(send_stream_.GetBuffer(), recv_stream_.GetBuffer(), size));
259*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Transferred " << received << " bytes in " << elapsed
260*d9f75844SAndroid Build Coastguard Worker << " ms (" << size * 8 / elapsed << " Kbps)";
261*d9f75844SAndroid Build Coastguard Worker }
262*d9f75844SAndroid Build Coastguard Worker
263*d9f75844SAndroid Build Coastguard Worker private:
264*d9f75844SAndroid Build Coastguard Worker // IPseudoTcpNotify interface
265*d9f75844SAndroid Build Coastguard Worker
OnTcpReadable(PseudoTcp * tcp)266*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpReadable(PseudoTcp* tcp) {
267*d9f75844SAndroid Build Coastguard Worker // Stream bytes to the recv stream as they arrive.
268*d9f75844SAndroid Build Coastguard Worker if (tcp == &remote_) {
269*d9f75844SAndroid Build Coastguard Worker ReadData();
270*d9f75844SAndroid Build Coastguard Worker
271*d9f75844SAndroid Build Coastguard Worker // TODO(?): OnTcpClosed() is currently only notified on error -
272*d9f75844SAndroid Build Coastguard Worker // there is no on-the-wire equivalent of TCP FIN.
273*d9f75844SAndroid Build Coastguard Worker // So we fake the notification when all the data has been read.
274*d9f75844SAndroid Build Coastguard Worker size_t received, required;
275*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetPosition(&received);
276*d9f75844SAndroid Build Coastguard Worker send_stream_.GetSize(&required);
277*d9f75844SAndroid Build Coastguard Worker if (received == required)
278*d9f75844SAndroid Build Coastguard Worker OnTcpClosed(&remote_, 0);
279*d9f75844SAndroid Build Coastguard Worker }
280*d9f75844SAndroid Build Coastguard Worker }
OnTcpWriteable(PseudoTcp * tcp)281*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpWriteable(PseudoTcp* tcp) {
282*d9f75844SAndroid Build Coastguard Worker // Write bytes from the send stream when we can.
283*d9f75844SAndroid Build Coastguard Worker // Shut down when we've sent everything.
284*d9f75844SAndroid Build Coastguard Worker if (tcp == &local_) {
285*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Flow Control Lifted";
286*d9f75844SAndroid Build Coastguard Worker bool done;
287*d9f75844SAndroid Build Coastguard Worker WriteData(&done);
288*d9f75844SAndroid Build Coastguard Worker if (done) {
289*d9f75844SAndroid Build Coastguard Worker Close();
290*d9f75844SAndroid Build Coastguard Worker }
291*d9f75844SAndroid Build Coastguard Worker }
292*d9f75844SAndroid Build Coastguard Worker }
293*d9f75844SAndroid Build Coastguard Worker
ReadData()294*d9f75844SAndroid Build Coastguard Worker void ReadData() {
295*d9f75844SAndroid Build Coastguard Worker char block[kBlockSize];
296*d9f75844SAndroid Build Coastguard Worker size_t position;
297*d9f75844SAndroid Build Coastguard Worker int rcvd;
298*d9f75844SAndroid Build Coastguard Worker do {
299*d9f75844SAndroid Build Coastguard Worker rcvd = remote_.Recv(block, sizeof(block));
300*d9f75844SAndroid Build Coastguard Worker if (rcvd != -1) {
301*d9f75844SAndroid Build Coastguard Worker size_t written;
302*d9f75844SAndroid Build Coastguard Worker int error;
303*d9f75844SAndroid Build Coastguard Worker recv_stream_.Write(
304*d9f75844SAndroid Build Coastguard Worker rtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), rcvd),
305*d9f75844SAndroid Build Coastguard Worker written, error);
306*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetPosition(&position);
307*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Received: " << position;
308*d9f75844SAndroid Build Coastguard Worker }
309*d9f75844SAndroid Build Coastguard Worker } while (rcvd > 0);
310*d9f75844SAndroid Build Coastguard Worker }
WriteData(bool * done)311*d9f75844SAndroid Build Coastguard Worker void WriteData(bool* done) {
312*d9f75844SAndroid Build Coastguard Worker size_t position, tosend;
313*d9f75844SAndroid Build Coastguard Worker int sent;
314*d9f75844SAndroid Build Coastguard Worker char block[kBlockSize];
315*d9f75844SAndroid Build Coastguard Worker do {
316*d9f75844SAndroid Build Coastguard Worker send_stream_.GetPosition(&position);
317*d9f75844SAndroid Build Coastguard Worker int error;
318*d9f75844SAndroid Build Coastguard Worker if (send_stream_.Read(
319*d9f75844SAndroid Build Coastguard Worker rtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), kBlockSize),
320*d9f75844SAndroid Build Coastguard Worker tosend, error) != rtc::SR_EOS) {
321*d9f75844SAndroid Build Coastguard Worker sent = local_.Send(block, tosend);
322*d9f75844SAndroid Build Coastguard Worker UpdateLocalClock();
323*d9f75844SAndroid Build Coastguard Worker if (sent != -1) {
324*d9f75844SAndroid Build Coastguard Worker send_stream_.SetPosition(position + sent);
325*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Sent: " << position + sent;
326*d9f75844SAndroid Build Coastguard Worker } else {
327*d9f75844SAndroid Build Coastguard Worker send_stream_.SetPosition(position);
328*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Flow Controlled";
329*d9f75844SAndroid Build Coastguard Worker }
330*d9f75844SAndroid Build Coastguard Worker } else {
331*d9f75844SAndroid Build Coastguard Worker sent = static_cast<int>(tosend = 0);
332*d9f75844SAndroid Build Coastguard Worker }
333*d9f75844SAndroid Build Coastguard Worker } while (sent > 0);
334*d9f75844SAndroid Build Coastguard Worker *done = (tosend == 0);
335*d9f75844SAndroid Build Coastguard Worker }
336*d9f75844SAndroid Build Coastguard Worker
337*d9f75844SAndroid Build Coastguard Worker private:
338*d9f75844SAndroid Build Coastguard Worker rtc::MemoryStream send_stream_;
339*d9f75844SAndroid Build Coastguard Worker rtc::MemoryStream recv_stream_;
340*d9f75844SAndroid Build Coastguard Worker };
341*d9f75844SAndroid Build Coastguard Worker
342*d9f75844SAndroid Build Coastguard Worker class PseudoTcpTestPingPong : public PseudoTcpTestBase {
343*d9f75844SAndroid Build Coastguard Worker public:
PseudoTcpTestPingPong()344*d9f75844SAndroid Build Coastguard Worker PseudoTcpTestPingPong()
345*d9f75844SAndroid Build Coastguard Worker : iterations_remaining_(0),
346*d9f75844SAndroid Build Coastguard Worker sender_(NULL),
347*d9f75844SAndroid Build Coastguard Worker receiver_(NULL),
348*d9f75844SAndroid Build Coastguard Worker bytes_per_send_(0) {}
SetBytesPerSend(int bytes)349*d9f75844SAndroid Build Coastguard Worker void SetBytesPerSend(int bytes) { bytes_per_send_ = bytes; }
TestPingPong(int size,int iterations)350*d9f75844SAndroid Build Coastguard Worker void TestPingPong(int size, int iterations) {
351*d9f75844SAndroid Build Coastguard Worker uint32_t start, elapsed;
352*d9f75844SAndroid Build Coastguard Worker iterations_remaining_ = iterations;
353*d9f75844SAndroid Build Coastguard Worker receiver_ = &remote_;
354*d9f75844SAndroid Build Coastguard Worker sender_ = &local_;
355*d9f75844SAndroid Build Coastguard Worker // Create some dummy data to send.
356*d9f75844SAndroid Build Coastguard Worker send_stream_.ReserveSize(size);
357*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < size; ++i) {
358*d9f75844SAndroid Build Coastguard Worker uint8_t ch = static_cast<uint8_t>(i);
359*d9f75844SAndroid Build Coastguard Worker size_t written;
360*d9f75844SAndroid Build Coastguard Worker int error;
361*d9f75844SAndroid Build Coastguard Worker send_stream_.Write(rtc::MakeArrayView(&ch, 1), written, error);
362*d9f75844SAndroid Build Coastguard Worker }
363*d9f75844SAndroid Build Coastguard Worker send_stream_.Rewind();
364*d9f75844SAndroid Build Coastguard Worker // Prepare the receive stream.
365*d9f75844SAndroid Build Coastguard Worker recv_stream_.ReserveSize(size);
366*d9f75844SAndroid Build Coastguard Worker // Connect and wait until connected.
367*d9f75844SAndroid Build Coastguard Worker start = rtc::Time32();
368*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, Connect());
369*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs);
370*d9f75844SAndroid Build Coastguard Worker // Sending will start from OnTcpWriteable and stop when the required
371*d9f75844SAndroid Build Coastguard Worker // number of iterations have completed.
372*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs);
373*d9f75844SAndroid Build Coastguard Worker elapsed = rtc::TimeSince(start);
374*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Performed " << iterations << " pings in " << elapsed
375*d9f75844SAndroid Build Coastguard Worker << " ms";
376*d9f75844SAndroid Build Coastguard Worker }
377*d9f75844SAndroid Build Coastguard Worker
378*d9f75844SAndroid Build Coastguard Worker private:
379*d9f75844SAndroid Build Coastguard Worker // IPseudoTcpNotify interface
380*d9f75844SAndroid Build Coastguard Worker
OnTcpReadable(PseudoTcp * tcp)381*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpReadable(PseudoTcp* tcp) {
382*d9f75844SAndroid Build Coastguard Worker if (tcp != receiver_) {
383*d9f75844SAndroid Build Coastguard Worker RTC_LOG_F(LS_ERROR) << "unexpected OnTcpReadable";
384*d9f75844SAndroid Build Coastguard Worker return;
385*d9f75844SAndroid Build Coastguard Worker }
386*d9f75844SAndroid Build Coastguard Worker // Stream bytes to the recv stream as they arrive.
387*d9f75844SAndroid Build Coastguard Worker ReadData();
388*d9f75844SAndroid Build Coastguard Worker // If we've received the desired amount of data, rewind things
389*d9f75844SAndroid Build Coastguard Worker // and send it back the other way!
390*d9f75844SAndroid Build Coastguard Worker size_t position, desired;
391*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetPosition(&position);
392*d9f75844SAndroid Build Coastguard Worker send_stream_.GetSize(&desired);
393*d9f75844SAndroid Build Coastguard Worker if (position == desired) {
394*d9f75844SAndroid Build Coastguard Worker if (receiver_ == &local_ && --iterations_remaining_ == 0) {
395*d9f75844SAndroid Build Coastguard Worker Close();
396*d9f75844SAndroid Build Coastguard Worker // TODO(?): Fake OnTcpClosed() on the receiver for now.
397*d9f75844SAndroid Build Coastguard Worker OnTcpClosed(&remote_, 0);
398*d9f75844SAndroid Build Coastguard Worker return;
399*d9f75844SAndroid Build Coastguard Worker }
400*d9f75844SAndroid Build Coastguard Worker PseudoTcp* tmp = receiver_;
401*d9f75844SAndroid Build Coastguard Worker receiver_ = sender_;
402*d9f75844SAndroid Build Coastguard Worker sender_ = tmp;
403*d9f75844SAndroid Build Coastguard Worker recv_stream_.Rewind();
404*d9f75844SAndroid Build Coastguard Worker send_stream_.Rewind();
405*d9f75844SAndroid Build Coastguard Worker OnTcpWriteable(sender_);
406*d9f75844SAndroid Build Coastguard Worker }
407*d9f75844SAndroid Build Coastguard Worker }
OnTcpWriteable(PseudoTcp * tcp)408*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpWriteable(PseudoTcp* tcp) {
409*d9f75844SAndroid Build Coastguard Worker if (tcp != sender_)
410*d9f75844SAndroid Build Coastguard Worker return;
411*d9f75844SAndroid Build Coastguard Worker // Write bytes from the send stream when we can.
412*d9f75844SAndroid Build Coastguard Worker // Shut down when we've sent everything.
413*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Flow Control Lifted";
414*d9f75844SAndroid Build Coastguard Worker WriteData();
415*d9f75844SAndroid Build Coastguard Worker }
416*d9f75844SAndroid Build Coastguard Worker
ReadData()417*d9f75844SAndroid Build Coastguard Worker void ReadData() {
418*d9f75844SAndroid Build Coastguard Worker char block[kBlockSize];
419*d9f75844SAndroid Build Coastguard Worker size_t position;
420*d9f75844SAndroid Build Coastguard Worker int rcvd;
421*d9f75844SAndroid Build Coastguard Worker do {
422*d9f75844SAndroid Build Coastguard Worker rcvd = receiver_->Recv(block, sizeof(block));
423*d9f75844SAndroid Build Coastguard Worker if (rcvd != -1) {
424*d9f75844SAndroid Build Coastguard Worker size_t written;
425*d9f75844SAndroid Build Coastguard Worker int error;
426*d9f75844SAndroid Build Coastguard Worker recv_stream_.Write(
427*d9f75844SAndroid Build Coastguard Worker rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(block), rcvd),
428*d9f75844SAndroid Build Coastguard Worker written, error);
429*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetPosition(&position);
430*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Received: " << position;
431*d9f75844SAndroid Build Coastguard Worker }
432*d9f75844SAndroid Build Coastguard Worker } while (rcvd > 0);
433*d9f75844SAndroid Build Coastguard Worker }
WriteData()434*d9f75844SAndroid Build Coastguard Worker void WriteData() {
435*d9f75844SAndroid Build Coastguard Worker size_t position, tosend;
436*d9f75844SAndroid Build Coastguard Worker int sent;
437*d9f75844SAndroid Build Coastguard Worker char block[kBlockSize];
438*d9f75844SAndroid Build Coastguard Worker do {
439*d9f75844SAndroid Build Coastguard Worker send_stream_.GetPosition(&position);
440*d9f75844SAndroid Build Coastguard Worker tosend = bytes_per_send_ ? bytes_per_send_ : sizeof(block);
441*d9f75844SAndroid Build Coastguard Worker int error;
442*d9f75844SAndroid Build Coastguard Worker if (send_stream_.Read(
443*d9f75844SAndroid Build Coastguard Worker rtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), tosend),
444*d9f75844SAndroid Build Coastguard Worker tosend, error) != rtc::SR_EOS) {
445*d9f75844SAndroid Build Coastguard Worker sent = sender_->Send(block, tosend);
446*d9f75844SAndroid Build Coastguard Worker UpdateLocalClock();
447*d9f75844SAndroid Build Coastguard Worker if (sent != -1) {
448*d9f75844SAndroid Build Coastguard Worker send_stream_.SetPosition(position + sent);
449*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Sent: " << position + sent;
450*d9f75844SAndroid Build Coastguard Worker } else {
451*d9f75844SAndroid Build Coastguard Worker send_stream_.SetPosition(position);
452*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Flow Controlled";
453*d9f75844SAndroid Build Coastguard Worker }
454*d9f75844SAndroid Build Coastguard Worker } else {
455*d9f75844SAndroid Build Coastguard Worker sent = static_cast<int>(tosend = 0);
456*d9f75844SAndroid Build Coastguard Worker }
457*d9f75844SAndroid Build Coastguard Worker } while (sent > 0);
458*d9f75844SAndroid Build Coastguard Worker }
459*d9f75844SAndroid Build Coastguard Worker
460*d9f75844SAndroid Build Coastguard Worker private:
461*d9f75844SAndroid Build Coastguard Worker int iterations_remaining_;
462*d9f75844SAndroid Build Coastguard Worker PseudoTcp* sender_;
463*d9f75844SAndroid Build Coastguard Worker PseudoTcp* receiver_;
464*d9f75844SAndroid Build Coastguard Worker int bytes_per_send_;
465*d9f75844SAndroid Build Coastguard Worker };
466*d9f75844SAndroid Build Coastguard Worker
467*d9f75844SAndroid Build Coastguard Worker // Fill the receiver window until it is full, drain it and then
468*d9f75844SAndroid Build Coastguard Worker // fill it with the same amount. This is to test that receiver window
469*d9f75844SAndroid Build Coastguard Worker // contracts and enlarges correctly.
470*d9f75844SAndroid Build Coastguard Worker class PseudoTcpTestReceiveWindow : public PseudoTcpTestBase {
471*d9f75844SAndroid Build Coastguard Worker public:
472*d9f75844SAndroid Build Coastguard Worker // Not all the data are transfered, `size` just need to be big enough
473*d9f75844SAndroid Build Coastguard Worker // to fill up the receiver window twice.
TestTransfer(int size)474*d9f75844SAndroid Build Coastguard Worker void TestTransfer(int size) {
475*d9f75844SAndroid Build Coastguard Worker // Create some dummy data to send.
476*d9f75844SAndroid Build Coastguard Worker send_stream_.ReserveSize(size);
477*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < size; ++i) {
478*d9f75844SAndroid Build Coastguard Worker uint8_t ch = static_cast<uint8_t>(i);
479*d9f75844SAndroid Build Coastguard Worker size_t written;
480*d9f75844SAndroid Build Coastguard Worker int error;
481*d9f75844SAndroid Build Coastguard Worker send_stream_.Write(rtc::MakeArrayView(&ch, 1), written, error);
482*d9f75844SAndroid Build Coastguard Worker }
483*d9f75844SAndroid Build Coastguard Worker send_stream_.Rewind();
484*d9f75844SAndroid Build Coastguard Worker
485*d9f75844SAndroid Build Coastguard Worker // Prepare the receive stream.
486*d9f75844SAndroid Build Coastguard Worker recv_stream_.ReserveSize(size);
487*d9f75844SAndroid Build Coastguard Worker
488*d9f75844SAndroid Build Coastguard Worker // Connect and wait until connected.
489*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, Connect());
490*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs);
491*d9f75844SAndroid Build Coastguard Worker
492*d9f75844SAndroid Build Coastguard Worker TaskQueueBase::Current()->PostTask([this] { WriteData(); });
493*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs);
494*d9f75844SAndroid Build Coastguard Worker
495*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(2u, send_position_.size());
496*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(2u, recv_position_.size());
497*d9f75844SAndroid Build Coastguard Worker
498*d9f75844SAndroid Build Coastguard Worker const size_t estimated_recv_window = EstimateReceiveWindowSize();
499*d9f75844SAndroid Build Coastguard Worker
500*d9f75844SAndroid Build Coastguard Worker // The difference in consecutive send positions should equal the
501*d9f75844SAndroid Build Coastguard Worker // receive window size or match very closely. This verifies that receive
502*d9f75844SAndroid Build Coastguard Worker // window is open after receiver drained all the data.
503*d9f75844SAndroid Build Coastguard Worker const size_t send_position_diff = send_position_[1] - send_position_[0];
504*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(1024u, estimated_recv_window - send_position_diff);
505*d9f75844SAndroid Build Coastguard Worker
506*d9f75844SAndroid Build Coastguard Worker // Receiver drained the receive window twice.
507*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2 * estimated_recv_window, recv_position_[1]);
508*d9f75844SAndroid Build Coastguard Worker }
509*d9f75844SAndroid Build Coastguard Worker
EstimateReceiveWindowSize() const510*d9f75844SAndroid Build Coastguard Worker uint32_t EstimateReceiveWindowSize() const {
511*d9f75844SAndroid Build Coastguard Worker return static_cast<uint32_t>(recv_position_[0]);
512*d9f75844SAndroid Build Coastguard Worker }
513*d9f75844SAndroid Build Coastguard Worker
EstimateSendWindowSize() const514*d9f75844SAndroid Build Coastguard Worker uint32_t EstimateSendWindowSize() const {
515*d9f75844SAndroid Build Coastguard Worker return static_cast<uint32_t>(send_position_[0] - recv_position_[0]);
516*d9f75844SAndroid Build Coastguard Worker }
517*d9f75844SAndroid Build Coastguard Worker
518*d9f75844SAndroid Build Coastguard Worker private:
519*d9f75844SAndroid Build Coastguard Worker // IPseudoTcpNotify interface
OnTcpReadable(PseudoTcp * tcp)520*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpReadable(PseudoTcp* tcp) {}
521*d9f75844SAndroid Build Coastguard Worker
OnTcpWriteable(PseudoTcp * tcp)522*d9f75844SAndroid Build Coastguard Worker virtual void OnTcpWriteable(PseudoTcp* tcp) {}
523*d9f75844SAndroid Build Coastguard Worker
ReadUntilIOPending()524*d9f75844SAndroid Build Coastguard Worker void ReadUntilIOPending() {
525*d9f75844SAndroid Build Coastguard Worker char block[kBlockSize];
526*d9f75844SAndroid Build Coastguard Worker size_t position;
527*d9f75844SAndroid Build Coastguard Worker int rcvd;
528*d9f75844SAndroid Build Coastguard Worker
529*d9f75844SAndroid Build Coastguard Worker do {
530*d9f75844SAndroid Build Coastguard Worker rcvd = remote_.Recv(block, sizeof(block));
531*d9f75844SAndroid Build Coastguard Worker if (rcvd != -1) {
532*d9f75844SAndroid Build Coastguard Worker size_t written;
533*d9f75844SAndroid Build Coastguard Worker int error;
534*d9f75844SAndroid Build Coastguard Worker recv_stream_.Write(
535*d9f75844SAndroid Build Coastguard Worker rtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), rcvd),
536*d9f75844SAndroid Build Coastguard Worker written, error);
537*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetPosition(&position);
538*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Received: " << position;
539*d9f75844SAndroid Build Coastguard Worker }
540*d9f75844SAndroid Build Coastguard Worker } while (rcvd > 0);
541*d9f75844SAndroid Build Coastguard Worker
542*d9f75844SAndroid Build Coastguard Worker recv_stream_.GetPosition(&position);
543*d9f75844SAndroid Build Coastguard Worker recv_position_.push_back(position);
544*d9f75844SAndroid Build Coastguard Worker
545*d9f75844SAndroid Build Coastguard Worker // Disconnect if we have done two transfers.
546*d9f75844SAndroid Build Coastguard Worker if (recv_position_.size() == 2u) {
547*d9f75844SAndroid Build Coastguard Worker Close();
548*d9f75844SAndroid Build Coastguard Worker OnTcpClosed(&remote_, 0);
549*d9f75844SAndroid Build Coastguard Worker } else {
550*d9f75844SAndroid Build Coastguard Worker WriteData();
551*d9f75844SAndroid Build Coastguard Worker }
552*d9f75844SAndroid Build Coastguard Worker }
553*d9f75844SAndroid Build Coastguard Worker
WriteData()554*d9f75844SAndroid Build Coastguard Worker void WriteData() {
555*d9f75844SAndroid Build Coastguard Worker size_t position, tosend;
556*d9f75844SAndroid Build Coastguard Worker int sent;
557*d9f75844SAndroid Build Coastguard Worker char block[kBlockSize];
558*d9f75844SAndroid Build Coastguard Worker do {
559*d9f75844SAndroid Build Coastguard Worker send_stream_.GetPosition(&position);
560*d9f75844SAndroid Build Coastguard Worker int error;
561*d9f75844SAndroid Build Coastguard Worker if (send_stream_.Read(
562*d9f75844SAndroid Build Coastguard Worker rtc::MakeArrayView(reinterpret_cast<uint8_t*>(block),
563*d9f75844SAndroid Build Coastguard Worker sizeof(block)),
564*d9f75844SAndroid Build Coastguard Worker tosend, error) != rtc::SR_EOS) {
565*d9f75844SAndroid Build Coastguard Worker sent = local_.Send(block, tosend);
566*d9f75844SAndroid Build Coastguard Worker UpdateLocalClock();
567*d9f75844SAndroid Build Coastguard Worker if (sent != -1) {
568*d9f75844SAndroid Build Coastguard Worker send_stream_.SetPosition(position + sent);
569*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Sent: " << position + sent;
570*d9f75844SAndroid Build Coastguard Worker } else {
571*d9f75844SAndroid Build Coastguard Worker send_stream_.SetPosition(position);
572*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_VERBOSE) << "Flow Controlled";
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker } else {
575*d9f75844SAndroid Build Coastguard Worker sent = static_cast<int>(tosend = 0);
576*d9f75844SAndroid Build Coastguard Worker }
577*d9f75844SAndroid Build Coastguard Worker } while (sent > 0);
578*d9f75844SAndroid Build Coastguard Worker // At this point, we've filled up the available space in the send queue.
579*d9f75844SAndroid Build Coastguard Worker
580*d9f75844SAndroid Build Coastguard Worker if (packets_in_flight_ > 0) {
581*d9f75844SAndroid Build Coastguard Worker // If there are packet tasks, attempt to continue sending after giving
582*d9f75844SAndroid Build Coastguard Worker // those packets time to process, which should free up the send buffer.
583*d9f75844SAndroid Build Coastguard Worker rtc::Thread::Current()->PostDelayedTask([this] { WriteData(); },
584*d9f75844SAndroid Build Coastguard Worker TimeDelta::Millis(10));
585*d9f75844SAndroid Build Coastguard Worker } else {
586*d9f75844SAndroid Build Coastguard Worker if (!remote_.isReceiveBufferFull()) {
587*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "This shouldn't happen - the send buffer is full, "
588*d9f75844SAndroid Build Coastguard Worker "the receive buffer is not, and there are no "
589*d9f75844SAndroid Build Coastguard Worker "remaining messages to process.";
590*d9f75844SAndroid Build Coastguard Worker }
591*d9f75844SAndroid Build Coastguard Worker send_stream_.GetPosition(&position);
592*d9f75844SAndroid Build Coastguard Worker send_position_.push_back(position);
593*d9f75844SAndroid Build Coastguard Worker
594*d9f75844SAndroid Build Coastguard Worker // Drain the receiver buffer.
595*d9f75844SAndroid Build Coastguard Worker ReadUntilIOPending();
596*d9f75844SAndroid Build Coastguard Worker }
597*d9f75844SAndroid Build Coastguard Worker }
598*d9f75844SAndroid Build Coastguard Worker
599*d9f75844SAndroid Build Coastguard Worker private:
600*d9f75844SAndroid Build Coastguard Worker rtc::MemoryStream send_stream_;
601*d9f75844SAndroid Build Coastguard Worker rtc::MemoryStream recv_stream_;
602*d9f75844SAndroid Build Coastguard Worker
603*d9f75844SAndroid Build Coastguard Worker std::vector<size_t> send_position_;
604*d9f75844SAndroid Build Coastguard Worker std::vector<size_t> recv_position_;
605*d9f75844SAndroid Build Coastguard Worker };
606*d9f75844SAndroid Build Coastguard Worker
607*d9f75844SAndroid Build Coastguard Worker // Basic end-to-end data transfer tests
608*d9f75844SAndroid Build Coastguard Worker
609*d9f75844SAndroid Build Coastguard Worker // Test the normal case of sending data from one side to the other.
TEST_F(PseudoTcpTest,TestSend)610*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSend) {
611*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
612*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
613*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
614*d9f75844SAndroid Build Coastguard Worker }
615*d9f75844SAndroid Build Coastguard Worker
616*d9f75844SAndroid Build Coastguard Worker // Test sending data with a 50 ms RTT. Transmission should take longer due
617*d9f75844SAndroid Build Coastguard Worker // to a slower ramp-up in send rate.
TEST_F(PseudoTcpTest,TestSendWithDelay)618*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithDelay) {
619*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
620*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
621*d9f75844SAndroid Build Coastguard Worker SetDelay(50);
622*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
623*d9f75844SAndroid Build Coastguard Worker }
624*d9f75844SAndroid Build Coastguard Worker
625*d9f75844SAndroid Build Coastguard Worker // Test sending data with packet loss. Transmission should take much longer due
626*d9f75844SAndroid Build Coastguard Worker // to send back-off when loss occurs.
TEST_F(PseudoTcpTest,TestSendWithLoss)627*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithLoss) {
628*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
629*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
630*d9f75844SAndroid Build Coastguard Worker SetLoss(10);
631*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000); // less data so test runs faster
632*d9f75844SAndroid Build Coastguard Worker }
633*d9f75844SAndroid Build Coastguard Worker
634*d9f75844SAndroid Build Coastguard Worker // Test sending data with a 50 ms RTT and 10% packet loss. Transmission should
635*d9f75844SAndroid Build Coastguard Worker // take much longer due to send back-off and slower detection of loss.
TEST_F(PseudoTcpTest,TestSendWithDelayAndLoss)636*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithDelayAndLoss) {
637*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
638*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
639*d9f75844SAndroid Build Coastguard Worker SetDelay(50);
640*d9f75844SAndroid Build Coastguard Worker SetLoss(10);
641*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000); // less data so test runs faster
642*d9f75844SAndroid Build Coastguard Worker }
643*d9f75844SAndroid Build Coastguard Worker
644*d9f75844SAndroid Build Coastguard Worker // Test sending data with 10% packet loss and Nagling disabled. Transmission
645*d9f75844SAndroid Build Coastguard Worker // should take about the same time as with Nagling enabled.
TEST_F(PseudoTcpTest,TestSendWithLossAndOptNaglingOff)646*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithLossAndOptNaglingOff) {
647*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
648*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
649*d9f75844SAndroid Build Coastguard Worker SetLoss(10);
650*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
651*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000); // less data so test runs faster
652*d9f75844SAndroid Build Coastguard Worker }
653*d9f75844SAndroid Build Coastguard Worker
654*d9f75844SAndroid Build Coastguard Worker // Regression test for bugs.webrtc.org/9208.
655*d9f75844SAndroid Build Coastguard Worker //
656*d9f75844SAndroid Build Coastguard Worker // This bug resulted in corrupted data if a "connect" segment was received after
657*d9f75844SAndroid Build Coastguard Worker // a data segment. This is only possible if:
658*d9f75844SAndroid Build Coastguard Worker //
659*d9f75844SAndroid Build Coastguard Worker // * The initial "connect" segment is lost, and retransmitted later.
660*d9f75844SAndroid Build Coastguard Worker // * Both sides send "connect"s simultaneously, such that the local side thinks
661*d9f75844SAndroid Build Coastguard Worker // a connection is established even before its "connect" has been
662*d9f75844SAndroid Build Coastguard Worker // acknowledged.
663*d9f75844SAndroid Build Coastguard Worker // * Nagle algorithm disabled, allowing a data segment to be sent before the
664*d9f75844SAndroid Build Coastguard Worker // "connect" has been acknowledged.
TEST_F(PseudoTcpTest,TestSendWhenFirstPacketLostWithOptNaglingOffAndSimultaneousOpen)665*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest,
666*d9f75844SAndroid Build Coastguard Worker TestSendWhenFirstPacketLostWithOptNaglingOffAndSimultaneousOpen) {
667*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
668*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
669*d9f75844SAndroid Build Coastguard Worker DropNextPacket();
670*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
671*d9f75844SAndroid Build Coastguard Worker SetSimultaneousOpen(true);
672*d9f75844SAndroid Build Coastguard Worker TestTransfer(10000);
673*d9f75844SAndroid Build Coastguard Worker }
674*d9f75844SAndroid Build Coastguard Worker
675*d9f75844SAndroid Build Coastguard Worker // Test sending data with 10% packet loss and Delayed ACK disabled.
676*d9f75844SAndroid Build Coastguard Worker // Transmission should be slightly faster than with it enabled.
TEST_F(PseudoTcpTest,TestSendWithLossAndOptAckDelayOff)677*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithLossAndOptAckDelayOff) {
678*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
679*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
680*d9f75844SAndroid Build Coastguard Worker SetLoss(10);
681*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
682*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000);
683*d9f75844SAndroid Build Coastguard Worker }
684*d9f75844SAndroid Build Coastguard Worker
685*d9f75844SAndroid Build Coastguard Worker // Test sending data with 50ms delay and Nagling disabled.
TEST_F(PseudoTcpTest,TestSendWithDelayAndOptNaglingOff)686*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithDelayAndOptNaglingOff) {
687*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
688*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
689*d9f75844SAndroid Build Coastguard Worker SetDelay(50);
690*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
691*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000); // less data so test runs faster
692*d9f75844SAndroid Build Coastguard Worker }
693*d9f75844SAndroid Build Coastguard Worker
694*d9f75844SAndroid Build Coastguard Worker // Test sending data with 50ms delay and Delayed ACK disabled.
TEST_F(PseudoTcpTest,TestSendWithDelayAndOptAckDelayOff)695*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithDelayAndOptAckDelayOff) {
696*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
697*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
698*d9f75844SAndroid Build Coastguard Worker SetDelay(50);
699*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
700*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000); // less data so test runs faster
701*d9f75844SAndroid Build Coastguard Worker }
702*d9f75844SAndroid Build Coastguard Worker
703*d9f75844SAndroid Build Coastguard Worker // Test a large receive buffer with a sender that doesn't support scaling.
TEST_F(PseudoTcpTest,TestSendRemoteNoWindowScale)704*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendRemoteNoWindowScale) {
705*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
706*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
707*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(100000);
708*d9f75844SAndroid Build Coastguard Worker DisableRemoteWindowScale();
709*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
710*d9f75844SAndroid Build Coastguard Worker }
711*d9f75844SAndroid Build Coastguard Worker
712*d9f75844SAndroid Build Coastguard Worker // Test a large sender-side receive buffer with a receiver that doesn't support
713*d9f75844SAndroid Build Coastguard Worker // scaling.
TEST_F(PseudoTcpTest,TestSendLocalNoWindowScale)714*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendLocalNoWindowScale) {
715*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
716*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
717*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(100000);
718*d9f75844SAndroid Build Coastguard Worker DisableLocalWindowScale();
719*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
720*d9f75844SAndroid Build Coastguard Worker }
721*d9f75844SAndroid Build Coastguard Worker
722*d9f75844SAndroid Build Coastguard Worker // Test when both sides use window scaling.
TEST_F(PseudoTcpTest,TestSendBothUseWindowScale)723*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendBothUseWindowScale) {
724*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
725*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
726*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(100000);
727*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(100000);
728*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
729*d9f75844SAndroid Build Coastguard Worker }
730*d9f75844SAndroid Build Coastguard Worker
731*d9f75844SAndroid Build Coastguard Worker // Test using a large window scale value.
TEST_F(PseudoTcpTest,TestSendLargeInFlight)732*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendLargeInFlight) {
733*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
734*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
735*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(100000);
736*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(100000);
737*d9f75844SAndroid Build Coastguard Worker SetOptSndBuf(150000);
738*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
739*d9f75844SAndroid Build Coastguard Worker }
740*d9f75844SAndroid Build Coastguard Worker
TEST_F(PseudoTcpTest,TestSendBothUseLargeWindowScale)741*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendBothUseLargeWindowScale) {
742*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
743*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
744*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(1000000);
745*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(1000000);
746*d9f75844SAndroid Build Coastguard Worker TestTransfer(10000000);
747*d9f75844SAndroid Build Coastguard Worker }
748*d9f75844SAndroid Build Coastguard Worker
749*d9f75844SAndroid Build Coastguard Worker // Test using a small receive buffer.
TEST_F(PseudoTcpTest,TestSendSmallReceiveBuffer)750*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendSmallReceiveBuffer) {
751*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
752*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
753*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(10000);
754*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(10000);
755*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
756*d9f75844SAndroid Build Coastguard Worker }
757*d9f75844SAndroid Build Coastguard Worker
758*d9f75844SAndroid Build Coastguard Worker // Test using a very small receive buffer.
TEST_F(PseudoTcpTest,TestSendVerySmallReceiveBuffer)759*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendVerySmallReceiveBuffer) {
760*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
761*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
762*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(100);
763*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(100);
764*d9f75844SAndroid Build Coastguard Worker TestTransfer(100000);
765*d9f75844SAndroid Build Coastguard Worker }
766*d9f75844SAndroid Build Coastguard Worker
767*d9f75844SAndroid Build Coastguard Worker // Ping-pong (request/response) tests
768*d9f75844SAndroid Build Coastguard Worker
769*d9f75844SAndroid Build Coastguard Worker // Test sending <= 1x MTU of data in each ping/pong. Should take <10ms.
TEST_F(PseudoTcpTestPingPong,TestPingPong1xMtu)770*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPong1xMtu) {
771*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
772*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
773*d9f75844SAndroid Build Coastguard Worker TestPingPong(100, 100);
774*d9f75844SAndroid Build Coastguard Worker }
775*d9f75844SAndroid Build Coastguard Worker
776*d9f75844SAndroid Build Coastguard Worker // Test sending 2x-3x MTU of data in each ping/pong. Should take <10ms.
TEST_F(PseudoTcpTestPingPong,TestPingPong3xMtu)777*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPong3xMtu) {
778*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
779*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
780*d9f75844SAndroid Build Coastguard Worker TestPingPong(400, 100);
781*d9f75844SAndroid Build Coastguard Worker }
782*d9f75844SAndroid Build Coastguard Worker
783*d9f75844SAndroid Build Coastguard Worker // Test sending 1x-2x MTU of data in each ping/pong.
784*d9f75844SAndroid Build Coastguard Worker // Should take ~1s, due to interaction between Nagling and Delayed ACK.
TEST_F(PseudoTcpTestPingPong,TestPingPong2xMtu)785*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtu) {
786*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
787*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
788*d9f75844SAndroid Build Coastguard Worker TestPingPong(2000, 5);
789*d9f75844SAndroid Build Coastguard Worker }
790*d9f75844SAndroid Build Coastguard Worker
791*d9f75844SAndroid Build Coastguard Worker // Test sending 1x-2x MTU of data in each ping/pong with Delayed ACK off.
792*d9f75844SAndroid Build Coastguard Worker // Should take <10ms.
TEST_F(PseudoTcpTestPingPong,TestPingPong2xMtuWithAckDelayOff)793*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithAckDelayOff) {
794*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
795*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
796*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
797*d9f75844SAndroid Build Coastguard Worker TestPingPong(2000, 100);
798*d9f75844SAndroid Build Coastguard Worker }
799*d9f75844SAndroid Build Coastguard Worker
800*d9f75844SAndroid Build Coastguard Worker // Test sending 1x-2x MTU of data in each ping/pong with Nagling off.
801*d9f75844SAndroid Build Coastguard Worker // Should take <10ms.
TEST_F(PseudoTcpTestPingPong,TestPingPong2xMtuWithNaglingOff)802*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithNaglingOff) {
803*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
804*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
805*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
806*d9f75844SAndroid Build Coastguard Worker TestPingPong(2000, 5);
807*d9f75844SAndroid Build Coastguard Worker }
808*d9f75844SAndroid Build Coastguard Worker
809*d9f75844SAndroid Build Coastguard Worker // Test sending a ping as pair of short (non-full) segments.
810*d9f75844SAndroid Build Coastguard Worker // Should take ~1s, due to Delayed ACK interaction with Nagling.
TEST_F(PseudoTcpTestPingPong,TestPingPongShortSegments)811*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegments) {
812*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
813*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
814*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(5000);
815*d9f75844SAndroid Build Coastguard Worker SetBytesPerSend(50); // i.e. two Send calls per payload
816*d9f75844SAndroid Build Coastguard Worker TestPingPong(100, 5);
817*d9f75844SAndroid Build Coastguard Worker }
818*d9f75844SAndroid Build Coastguard Worker
819*d9f75844SAndroid Build Coastguard Worker // Test sending ping as a pair of short (non-full) segments, with Nagling off.
820*d9f75844SAndroid Build Coastguard Worker // Should take <10ms.
TEST_F(PseudoTcpTestPingPong,TestPingPongShortSegmentsWithNaglingOff)821*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithNaglingOff) {
822*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
823*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
824*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
825*d9f75844SAndroid Build Coastguard Worker SetBytesPerSend(50); // i.e. two Send calls per payload
826*d9f75844SAndroid Build Coastguard Worker TestPingPong(100, 5);
827*d9f75844SAndroid Build Coastguard Worker }
828*d9f75844SAndroid Build Coastguard Worker
829*d9f75844SAndroid Build Coastguard Worker // Test sending <= 1x MTU of data ping/pong, in two segments, no Delayed ACK.
830*d9f75844SAndroid Build Coastguard Worker // Should take ~1s.
TEST_F(PseudoTcpTestPingPong,TestPingPongShortSegmentsWithAckDelayOff)831*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithAckDelayOff) {
832*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
833*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
834*d9f75844SAndroid Build Coastguard Worker SetBytesPerSend(50); // i.e. two Send calls per payload
835*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
836*d9f75844SAndroid Build Coastguard Worker TestPingPong(100, 5);
837*d9f75844SAndroid Build Coastguard Worker }
838*d9f75844SAndroid Build Coastguard Worker
839*d9f75844SAndroid Build Coastguard Worker // Test that receive window expands and contract correctly.
TEST_F(PseudoTcpTestReceiveWindow,TestReceiveWindow)840*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestReceiveWindow, TestReceiveWindow) {
841*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
842*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
843*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
844*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
845*d9f75844SAndroid Build Coastguard Worker TestTransfer(1024 * 1000);
846*d9f75844SAndroid Build Coastguard Worker }
847*d9f75844SAndroid Build Coastguard Worker
848*d9f75844SAndroid Build Coastguard Worker // Test setting send window size to a very small value.
TEST_F(PseudoTcpTestReceiveWindow,TestSetVerySmallSendWindowSize)849*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestReceiveWindow, TestSetVerySmallSendWindowSize) {
850*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
851*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
852*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
853*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
854*d9f75844SAndroid Build Coastguard Worker SetOptSndBuf(900);
855*d9f75844SAndroid Build Coastguard Worker TestTransfer(1024 * 1000);
856*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(900u, EstimateSendWindowSize());
857*d9f75844SAndroid Build Coastguard Worker }
858*d9f75844SAndroid Build Coastguard Worker
859*d9f75844SAndroid Build Coastguard Worker // Test setting receive window size to a value other than default.
TEST_F(PseudoTcpTestReceiveWindow,TestSetReceiveWindowSize)860*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTestReceiveWindow, TestSetReceiveWindowSize) {
861*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
862*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1500);
863*d9f75844SAndroid Build Coastguard Worker SetOptNagling(false);
864*d9f75844SAndroid Build Coastguard Worker SetOptAckDelay(0);
865*d9f75844SAndroid Build Coastguard Worker SetRemoteOptRcvBuf(100000);
866*d9f75844SAndroid Build Coastguard Worker SetLocalOptRcvBuf(100000);
867*d9f75844SAndroid Build Coastguard Worker TestTransfer(1024 * 1000);
868*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(100000u, EstimateReceiveWindowSize());
869*d9f75844SAndroid Build Coastguard Worker }
870*d9f75844SAndroid Build Coastguard Worker
871*d9f75844SAndroid Build Coastguard Worker /* Test sending data with mismatched MTUs. We should detect this and reduce
872*d9f75844SAndroid Build Coastguard Worker // our packet size accordingly.
873*d9f75844SAndroid Build Coastguard Worker // TODO(?): This doesn't actually work right now. The current code
874*d9f75844SAndroid Build Coastguard Worker // doesn't detect if the MTU is set too high on either side.
875*d9f75844SAndroid Build Coastguard Worker TEST_F(PseudoTcpTest, TestSendWithMismatchedMtus) {
876*d9f75844SAndroid Build Coastguard Worker SetLocalMtu(1500);
877*d9f75844SAndroid Build Coastguard Worker SetRemoteMtu(1280);
878*d9f75844SAndroid Build Coastguard Worker TestTransfer(1000000);
879*d9f75844SAndroid Build Coastguard Worker }
880*d9f75844SAndroid Build Coastguard Worker */
881