mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-07-30 14:43:05 +03:00
Use iovec instead of IOBuf in QuicAsyncUDPSocket::write and QuicAsyncUDPSocket::writeGSO
Summary: See title Reviewed By: mjoras Differential Revision: D61048705 fbshipit-source-id: 60dc63cc67f63be6f0ac6cbe0e766172a8c79d7c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
924183d2d3
commit
2369ecb69b
@ -69,6 +69,12 @@ constexpr uint16_t kDefaultMsgSizeBackOffSize = 50;
|
||||
// larger than this, unless configured otherwise.
|
||||
constexpr uint16_t kDefaultUDPReadBufferSize = 1500;
|
||||
|
||||
// UDP's typical MTU size is 1500, so a large number of buffers
|
||||
// does not make sense. We can optimize for buffer chains with
|
||||
// fewer than 16 buffers, which is the highest I can think of
|
||||
// for a real use case.
|
||||
constexpr size_t kNumIovecBufferChains = 16;
|
||||
|
||||
// Number of GRO buffers to use
|
||||
// 1 means GRO is not enabled
|
||||
// 64 is the max possible value
|
||||
|
@ -32,7 +32,9 @@ bool SinglePacketBatchWriter::append(
|
||||
ssize_t SinglePacketBatchWriter::write(
|
||||
QuicAsyncUDPSocket& sock,
|
||||
const folly::SocketAddress& address) {
|
||||
return sock.write(address, buf_);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(buf_, vec);
|
||||
return sock.write(address, vec, iovec_len);
|
||||
}
|
||||
|
||||
// SinglePacketInplaceBatchWriter
|
||||
@ -54,7 +56,10 @@ ssize_t SinglePacketInplaceBatchWriter::write(
|
||||
const folly::SocketAddress& address) {
|
||||
auto& buf = conn_.bufAccessor->buf();
|
||||
CHECK(!conn_.bufAccessor->isChained());
|
||||
auto ret = sock.write(address, buf);
|
||||
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(buf, vec);
|
||||
auto ret = sock.write(address, vec, iovec_len);
|
||||
conn_.bufAccessor->clear();
|
||||
return ret;
|
||||
}
|
||||
@ -102,7 +107,9 @@ bool SinglePacketBackpressureBatchWriter::append(
|
||||
ssize_t SinglePacketBackpressureBatchWriter::write(
|
||||
QuicAsyncUDPSocket& sock,
|
||||
const folly::SocketAddress& address) {
|
||||
auto written = sock.write(address, buf_);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(buf_, vec);
|
||||
auto written = sock.write(address, vec, iovec_len);
|
||||
lastWriteSuccessful_ = written > 0;
|
||||
return written;
|
||||
}
|
||||
@ -149,7 +156,9 @@ ssize_t SendmmsgPacketBatchWriter::write(
|
||||
const folly::SocketAddress& address) {
|
||||
CHECK_GT(bufs_.size(), 0);
|
||||
if (bufs_.size() == 1) {
|
||||
return sock.write(address, bufs_[0]);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(bufs_.at(0), vec);
|
||||
return sock.write(address, vec, iovec_len);
|
||||
}
|
||||
|
||||
int ret = sock.writem(
|
||||
|
@ -78,7 +78,9 @@ ssize_t GSOPacketBatchWriter::write(
|
||||
auto options =
|
||||
QuicAsyncUDPSocket::WriteOptions(gsoVal, false /*zerocopyVal*/);
|
||||
options.txTime = txTime_;
|
||||
return sock.writeGSO(address, buf_, options);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(buf_, vec);
|
||||
return sock.writeGSO(address, vec, iovec_len, options);
|
||||
}
|
||||
|
||||
GSOInplacePacketBatchWriter::GSOInplacePacketBatchWriter(
|
||||
@ -159,7 +161,9 @@ ssize_t GSOInplacePacketBatchWriter::write(
|
||||
auto options =
|
||||
QuicAsyncUDPSocket::WriteOptions(gsoVal, false /*zerocopyVal*/);
|
||||
options.txTime = txTime_;
|
||||
auto bytesWritten = sock.writeGSO(address, buf, options);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(buf, vec);
|
||||
auto bytesWritten = sock.writeGSO(address, vec, iovec_len, options);
|
||||
/**
|
||||
* If there is one more bytes after lastPacketEnd_, that means there is a
|
||||
* packet we choose not to write in this batch (e.g., it has a size larger
|
||||
@ -281,8 +285,11 @@ ssize_t SendmmsgGSOPacketBatchWriter::write(
|
||||
const folly::SocketAddress& /*unused*/) {
|
||||
CHECK_GT(bufs_.size(), 0);
|
||||
if (bufs_.size() == 1) {
|
||||
return (currBufs_ > 1) ? sock.writeGSO(addrs_[0], bufs_[0], options_[0])
|
||||
: sock.write(addrs_[0], bufs_[0]);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(bufs_[0], vec);
|
||||
return (currBufs_ > 1)
|
||||
? sock.writeGSO(addrs_[0], vec, iovec_len, options_[0])
|
||||
: sock.write(addrs_[0], vec, iovec_len);
|
||||
}
|
||||
|
||||
int ret = sock.writemGSO(
|
||||
|
@ -1319,7 +1319,9 @@ void writeCloseCommon(
|
||||
// best effort writing to the socket, ignore any errors.
|
||||
|
||||
Buf packetBufPtr = packetBuf.clone();
|
||||
auto ret = sock.write(connection.peerAddress, packetBufPtr);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(packetBufPtr, vec);
|
||||
auto ret = sock.write(connection.peerAddress, vec, iovec_len);
|
||||
connection.lossState.totalBytesSent += packetSize;
|
||||
if (ret < 0) {
|
||||
VLOG(4) << "Error writing connection close " << folly::errnoStr(errno)
|
||||
|
@ -159,6 +159,7 @@ cpp_unittest(
|
||||
deps = [
|
||||
"//quic/api:quic_batch_writer",
|
||||
"//quic/common/events:folly_eventbase",
|
||||
"//quic/common/test:test_utils",
|
||||
"//quic/common/testutil:mock_async_udp_socket",
|
||||
"//quic/common/udpsocket:folly_async_udp_socket",
|
||||
"//quic/fizz/server/handshake:fizz_server_handshake",
|
||||
|
@ -77,6 +77,7 @@ quic_add_test(TARGET QuicBatchWriterTest
|
||||
mvfst_buf_accessor
|
||||
mvfst_server
|
||||
mvfst_transport
|
||||
mvfst_test_utils
|
||||
)
|
||||
|
||||
quic_add_test(TARGET QuicStreamAsyncTransportTest
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <quic/api/QuicBatchWriter.h>
|
||||
#include <quic/api/QuicBatchWriterFactory.h>
|
||||
#include <quic/common/events/FollyQuicEventBase.h>
|
||||
#include <quic/common/test/TestUtils.h>
|
||||
#include <quic/common/udpsocket/FollyQuicAsyncUDPSocket.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@ -464,12 +465,13 @@ TEST_F(QuicBatchWriterTest, InplaceWriterWriteAll) {
|
||||
ASSERT_TRUE(
|
||||
batchWriter->append(nullptr, 700, folly::SocketAddress(), nullptr));
|
||||
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t,
|
||||
QuicAsyncUDPSocket::WriteOptions options) {
|
||||
EXPECT_EQ(1000 * 5 + 700, buf->length());
|
||||
EXPECT_EQ(1000 * 5 + 700, vec[0].iov_len);
|
||||
EXPECT_EQ(1000, options.gso);
|
||||
return 1000 * 5 + 700;
|
||||
}));
|
||||
@ -506,14 +508,13 @@ TEST_F(QuicBatchWriterTest, InplaceWriterWriteOne) {
|
||||
ASSERT_FALSE(
|
||||
batchWriter->append(nullptr, 1000, folly::SocketAddress(), nullptr));
|
||||
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
auto) {
|
||||
EXPECT_EQ(1000, buf->length());
|
||||
return 1000;
|
||||
}));
|
||||
.WillOnce(Invoke(
|
||||
[&](const auto& /* addr */, const struct iovec* vec, size_t, auto) {
|
||||
EXPECT_EQ(1000, vec[0].iov_len);
|
||||
return 1000;
|
||||
}));
|
||||
EXPECT_EQ(1000, batchWriter->write(sock, folly::SocketAddress()));
|
||||
|
||||
EXPECT_TRUE(bufAccessor->ownsBuffer());
|
||||
@ -550,12 +551,13 @@ TEST_F(QuicBatchWriterTest, InplaceWriterLastOneTooBig) {
|
||||
bufAccessor->release(std::move(buf));
|
||||
EXPECT_TRUE(batchWriter->needsFlush(1000));
|
||||
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t,
|
||||
QuicAsyncUDPSocket::WriteOptions options) {
|
||||
EXPECT_EQ(5 * 700, buf->length());
|
||||
EXPECT_EQ(5 * 700, vec[0].iov_len);
|
||||
EXPECT_EQ(700, options.gso);
|
||||
return 700 * 5;
|
||||
}));
|
||||
@ -598,14 +600,13 @@ TEST_F(QuicBatchWriterTest, InplaceWriterBufResidueCheck) {
|
||||
rawBuf->append(packetSizeBig);
|
||||
EXPECT_TRUE(batchWriter->needsFlush(packetSizeBig));
|
||||
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(sock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
auto) {
|
||||
EXPECT_EQ(700, buf->length());
|
||||
return 700;
|
||||
}));
|
||||
.WillOnce(Invoke(
|
||||
[&](const auto& /* addr */, const struct iovec* vec, size_t, auto) {
|
||||
EXPECT_EQ(700, vec[0].iov_len);
|
||||
return 700;
|
||||
}));
|
||||
// No crash:
|
||||
EXPECT_EQ(700, batchWriter->write(sock, folly::SocketAddress()));
|
||||
EXPECT_EQ(1009, rawBuf->length());
|
||||
@ -751,13 +752,13 @@ TEST_F(SinglePacketInplaceBatchWriterTest, TestWrite) {
|
||||
std::shared_ptr<FollyQuicEventBase> qEvb =
|
||||
std::make_shared<FollyQuicEventBase>(&evb);
|
||||
quic::test::MockAsyncUDPSocket sock(qEvb);
|
||||
EXPECT_CALL(sock, write(_, _))
|
||||
EXPECT_CALL(sock, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
EXPECT_EQ(appendSize, buf->length());
|
||||
return appendSize;
|
||||
}));
|
||||
.WillOnce(
|
||||
Invoke([&](const auto& /* addr */, const struct iovec* vec, size_t) {
|
||||
EXPECT_EQ(appendSize, vec[0].iov_len);
|
||||
return appendSize;
|
||||
}));
|
||||
EXPECT_EQ(appendSize, batchWriter->write(sock, folly::SocketAddress()));
|
||||
EXPECT_TRUE(batchWriter->empty());
|
||||
}
|
||||
@ -822,10 +823,11 @@ TEST_F(SinglePacketBackpressureBatchWriterTest, TestFailedWriteCachedOnEAGAIN) {
|
||||
folly::SocketAddress(),
|
||||
&sock_));
|
||||
|
||||
EXPECT_CALL(sock_, write(_, _))
|
||||
EXPECT_CALL(sock_, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& /*buf*/) {
|
||||
const struct iovec* /* vec */,
|
||||
size_t /* iovec_len */) {
|
||||
errno = EAGAIN;
|
||||
return 0;
|
||||
}));
|
||||
@ -846,11 +848,12 @@ TEST_F(SinglePacketBackpressureBatchWriterTest, TestFailedWriteCachedOnEAGAIN) {
|
||||
EXPECT_FALSE(conn_.pendingWriteBatch_.buf);
|
||||
|
||||
// The write succeeds
|
||||
EXPECT_CALL(sock_, write(_, _))
|
||||
EXPECT_CALL(sock_, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
return ::quic::test::getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_EQ(
|
||||
batchWriter->write(sock_, folly::SocketAddress()), testString.size());
|
||||
|
@ -1718,7 +1718,7 @@ TEST_P(QuicTransportImplTestBase, ReadDataAlsoChecksLossAlarm) {
|
||||
TEST_P(QuicTransportImplTestBase, ConnectionErrorOnWrite) {
|
||||
transport->transportConn->oneRttWriteCipher = test::createNoOpAead();
|
||||
auto stream = transport->createBidirectionalStream().value();
|
||||
EXPECT_CALL(*socketPtr, write(_, _))
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(ENETUNREACH, -1));
|
||||
transport->writeChain(stream, folly::IOBuf::copyBuffer("Hey"), true, nullptr);
|
||||
transport->addDataToStream(
|
||||
@ -1743,10 +1743,12 @@ TEST_P(QuicTransportImplTestBase, ReadErrorUnsanitizedErrorMsg) {
|
||||
EXPECT_EQ("You need to calm down.", error.message);
|
||||
}));
|
||||
|
||||
EXPECT_CALL(*socketPtr, write(_, _)).WillOnce(Invoke([](auto&, auto&) {
|
||||
throw std::runtime_error("You need to calm down.");
|
||||
return 0;
|
||||
}));
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillOnce(
|
||||
Invoke([](const folly::SocketAddress&, const struct iovec*, size_t) {
|
||||
throw std::runtime_error("You need to calm down.");
|
||||
return 0;
|
||||
}));
|
||||
transport->writeChain(
|
||||
stream,
|
||||
folly::IOBuf::copyBuffer("You are being too loud."),
|
||||
@ -1765,10 +1767,12 @@ TEST_P(QuicTransportImplTestBase, ConnectionErrorUnhandledException) {
|
||||
onConnectionSetupError(QuicError(
|
||||
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
||||
std::string("Well there's your problem"))));
|
||||
EXPECT_CALL(*socketPtr, write(_, _)).WillOnce(Invoke([](auto&, auto&) {
|
||||
throw std::runtime_error("Well there's your problem");
|
||||
return 0;
|
||||
}));
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillOnce(
|
||||
Invoke([](const folly::SocketAddress&, const struct iovec*, size_t) {
|
||||
throw std::runtime_error("Well there's your problem");
|
||||
return 0;
|
||||
}));
|
||||
transport->writeChain(stream, folly::IOBuf::copyBuffer("Hey"), true, nullptr);
|
||||
transport->addDataToStream(
|
||||
stream, StreamBuffer(folly::IOBuf::copyBuffer("Data"), 0));
|
||||
@ -2939,7 +2943,7 @@ TEST_P(QuicTransportImplTestBase, TestGracefulCloseWithActiveStream) {
|
||||
transport->notifyPendingWriteOnConnection(&wcbConn);
|
||||
transport->notifyPendingWriteOnStream(stream, &wcb);
|
||||
transport->setReadCallback(stream, &rcb);
|
||||
EXPECT_CALL(*socketPtr, write(_, _))
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillRepeatedly(SetErrnoAndReturn(EAGAIN, -1));
|
||||
transport->writeChain(stream, IOBuf::copyBuffer("hello"), true, &deliveryCb);
|
||||
EXPECT_CALL(txCb, onByteEventRegistered(getTxMatcher(stream, 0)));
|
||||
@ -2993,7 +2997,7 @@ TEST_P(QuicTransportImplTestBase, TestGracefulCloseWithNoActiveStream) {
|
||||
EXPECT_CALL(connCallback, onConnectionError(_)).Times(0);
|
||||
|
||||
transport->setReadCallback(stream, &rcb);
|
||||
EXPECT_CALL(*socketPtr, write(_, _))
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillRepeatedly(SetErrnoAndReturn(EAGAIN, -1));
|
||||
transport->writeChain(stream, IOBuf::copyBuffer("hello"), true, &deliveryCb);
|
||||
EXPECT_CALL(txCb, onByteEventRegistered(getTxMatcher(stream, 0)));
|
||||
@ -3055,7 +3059,7 @@ TEST_P(QuicTransportImplTestBase, TestImmediateClose) {
|
||||
transport->notifyPendingWriteOnStream(stream, &wcb);
|
||||
transport->setReadCallback(stream, &rcb);
|
||||
transport->setPeekCallback(stream, &pcb);
|
||||
EXPECT_CALL(*socketPtr, write(_, _))
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillRepeatedly(SetErrnoAndReturn(EAGAIN, -1));
|
||||
transport->writeChain(stream, IOBuf::copyBuffer("hello"), true, &deliveryCb);
|
||||
EXPECT_CALL(txCb, onByteEventRegistered(getTxMatcher(stream, 0)));
|
||||
@ -3195,7 +3199,8 @@ TEST_P(QuicTransportImplTestBase, ExceptionInWriteLooperDoesNotCrash) {
|
||||
transport->writeChain(stream, IOBuf::copyBuffer("hello"), true, nullptr);
|
||||
transport->addDataToStream(
|
||||
stream, StreamBuffer(IOBuf::copyBuffer("hello"), 0, false));
|
||||
EXPECT_CALL(*socketPtr, write(_, _)).WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(connSetupCallback, onConnectionSetupError(_))
|
||||
.WillOnce(Invoke([&](auto) { transport.reset(); }));
|
||||
transport->writeLooper()->runLoopCallback();
|
||||
@ -4913,14 +4918,14 @@ TEST_P(
|
||||
}));
|
||||
|
||||
// Fail the first write loop.
|
||||
EXPECT_CALL(*socketPtr, write(_, _))
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.Times(2) // We attempt to flush the batch twice inside the write loop.
|
||||
// Fail both.
|
||||
.WillRepeatedly(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& /*buf*/) {
|
||||
errno = EAGAIN;
|
||||
return 0;
|
||||
}));
|
||||
.WillRepeatedly(
|
||||
Invoke([&](const folly::SocketAddress&, const struct iovec*, size_t) {
|
||||
errno = EAGAIN;
|
||||
return 0;
|
||||
}));
|
||||
|
||||
transport->writeLooper()->run(true /* thisIteration */);
|
||||
EXPECT_TRUE(transport->writeLooper()->isRunning());
|
||||
@ -4937,12 +4942,13 @@ TEST_P(
|
||||
EXPECT_TRUE(writeCallbackArmed);
|
||||
|
||||
// Reset will make one write attempt. We don't care what happens to it
|
||||
EXPECT_CALL(*socketPtr, write(_, _))
|
||||
EXPECT_CALL(*socketPtr, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillRepeatedly(Invoke([&](const auto& /* addr */,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
.WillRepeatedly(Invoke([&](const folly::SocketAddress&,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
errno = 0;
|
||||
return buf->computeChainDataLength();
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
transport.reset();
|
||||
}
|
||||
|
@ -2620,13 +2620,14 @@ TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketWithCC) {
|
||||
EXPECT_CALL(*rawCongestionController, getWritableBytes())
|
||||
.WillRepeatedly(
|
||||
InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
EXPECT_LE(iobuf->computeChainDataLength(), 30);
|
||||
writableBytes -= iobuf->computeChainDataLength();
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
size_t totalLen = getTotalIovecLen(vec, iovec_len);
|
||||
EXPECT_LE(totalLen, 30);
|
||||
writableBytes -= totalLen;
|
||||
return totalLen;
|
||||
}));
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
|
||||
EXPECT_CALL(*quicStats_, onWrite(_));
|
||||
writeQuicDataToSocket(
|
||||
@ -2697,7 +2698,7 @@ TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketLimitTest) {
|
||||
|
||||
// Limit to zero
|
||||
conn->transportSettings.writeConnectionDataPacketsLimit = 0;
|
||||
EXPECT_CALL(*rawSocket, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
|
||||
EXPECT_CALL(*quicStats_, onWrite(_)).Times(0);
|
||||
auto res = writeQuicDataToSocket(
|
||||
@ -2720,14 +2721,14 @@ TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketLimitTest) {
|
||||
conn->transportSettings.writeConnectionDataPacketsLimit =
|
||||
kDefaultWriteConnectionDataPacketLimit;
|
||||
uint64_t actualWritten = 0;
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
writableBytes -= iobuf->computeChainDataLength();
|
||||
actualWritten += iobuf->computeChainDataLength();
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
writableBytes -= getTotalIovecLen(vec, iovec_len);
|
||||
actualWritten += getTotalIovecLen(vec, iovec_len);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
|
||||
EXPECT_CALL(*quicStats_, onWrite(_)).Times(1);
|
||||
res = writeQuicDataToSocket(
|
||||
@ -2754,13 +2755,13 @@ TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketLimitTest) {
|
||||
EXPECT_CALL(*rawCongestionController, getWritableBytes())
|
||||
.WillRepeatedly(
|
||||
InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.Times(kDefaultWriteConnectionDataPacketLimit * 2)
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
actualWritten += iobuf->computeChainDataLength();
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
actualWritten += getTotalIovecLen(vec, iovec_len);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_))
|
||||
.Times(kDefaultWriteConnectionDataPacketLimit * 2);
|
||||
EXPECT_CALL(*quicStats_, onWrite(_)).Times(1);
|
||||
@ -2807,15 +2808,15 @@ TEST_F(
|
||||
EXPECT_CALL(*rawCongestionController, getWritableBytes())
|
||||
.WillRepeatedly(
|
||||
InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
EXPECT_LE(
|
||||
iobuf->computeChainDataLength(),
|
||||
*conn->writableBytesLimit - conn->lossState.totalBytesSent);
|
||||
writableBytes -= iobuf->computeChainDataLength();
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
EXPECT_LE(
|
||||
getTotalIovecLen(vec, iovec_len),
|
||||
*conn->writableBytesLimit - conn->lossState.totalBytesSent);
|
||||
writableBytes -= getTotalIovecLen(vec, iovec_len);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_NE(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
|
||||
writeQuicDataToSocket(
|
||||
*rawSocket,
|
||||
@ -2962,13 +2963,13 @@ TEST_F(QuicTransportFunctionsTest, WriteBlockedFrameWhenBlocked) {
|
||||
|
||||
auto originalNextSeq = conn->ackStates.appDataAckState.nextPacketNum;
|
||||
uint64_t sentBytes = 0;
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
auto len = iobuf->computeChainDataLength();
|
||||
sentBytes += len;
|
||||
return len;
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
auto len = getTotalIovecLen(vec, iovec_len);
|
||||
sentBytes += len;
|
||||
return len;
|
||||
}));
|
||||
|
||||
// Artificially Block the stream
|
||||
stream1->flowControlState.peerAdvertisedMaxOffset = 10;
|
||||
@ -3033,13 +3034,13 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingNewData) {
|
||||
|
||||
auto currentStreamWriteOffset = stream1->currentWriteOffset;
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
auto len = iobuf->computeChainDataLength();
|
||||
EXPECT_EQ(conn->udpSendPacketLen - aead->getCipherOverhead(), len);
|
||||
return len;
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
auto len = getTotalIovecLen(vec, iovec_len);
|
||||
EXPECT_EQ(conn->udpSendPacketLen - aead->getCipherOverhead(), len);
|
||||
return len;
|
||||
}));
|
||||
writeProbingDataToSocketForTest(
|
||||
*rawSocket, *conn, 1, *aead, *headerCipher, getVersion(*conn));
|
||||
EXPECT_LT(currentPacketSeqNum, conn->ackStates.appDataAckState.nextPacketNum);
|
||||
@ -3061,7 +3062,7 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingOldData) {
|
||||
auto socket =
|
||||
std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = socket.get();
|
||||
EXPECT_CALL(*rawSocket, write(_, _)).WillRepeatedly(Return(100));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _)).WillRepeatedly(Return(100));
|
||||
auto capturingAead = std::make_unique<MockAead>();
|
||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||
auto buf = folly::IOBuf::copyBuffer("Where you wanna go");
|
||||
@ -3111,7 +3112,7 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingOldDataAckFreq) {
|
||||
auto socket =
|
||||
std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = socket.get();
|
||||
EXPECT_CALL(*rawSocket, write(_, _)).WillRepeatedly(Return(100));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _)).WillRepeatedly(Return(100));
|
||||
auto capturingAead = std::make_unique<MockAead>();
|
||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||
auto buf = folly::IOBuf::copyBuffer("Where you wanna go");
|
||||
@ -3186,13 +3187,13 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingCryptoData) {
|
||||
|
||||
auto currentStreamWriteOffset = cryptoStream->currentWriteOffset;
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
auto len = iobuf->computeChainDataLength();
|
||||
EXPECT_EQ(conn.udpSendPacketLen - aead->getCipherOverhead(), len);
|
||||
return len;
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
auto len = getTotalIovecLen(vec, iovec_len);
|
||||
EXPECT_EQ(conn.udpSendPacketLen - aead->getCipherOverhead(), len);
|
||||
return len;
|
||||
}));
|
||||
writeCryptoDataProbesToSocketForTest(
|
||||
*rawSocket, conn, 1, *aead, *headerCipher, getVersion(conn));
|
||||
EXPECT_LT(currentPacketSeqNum, conn.ackStates.initialAckState->nextPacketNum);
|
||||
@ -3234,13 +3235,13 @@ TEST_F(QuicTransportFunctionsTest, WriteableBytesLimitedProbingCryptoData) {
|
||||
|
||||
auto currentStreamWriteOffset = cryptoStream->currentWriteOffset;
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(2);
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
auto len = iobuf->computeChainDataLength();
|
||||
EXPECT_EQ(conn.udpSendPacketLen - aead->getCipherOverhead(), len);
|
||||
return len;
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
auto len = getTotalIovecLen(vec, iovec_len);
|
||||
EXPECT_EQ(conn.udpSendPacketLen - aead->getCipherOverhead(), len);
|
||||
return len;
|
||||
}));
|
||||
writeCryptoDataProbesToSocketForTest(
|
||||
*rawSocket, conn, probesToSend, *aead, *headerCipher, getVersion(conn));
|
||||
|
||||
@ -3265,7 +3266,7 @@ TEST_F(QuicTransportFunctionsTest, ProbingNotFallbackToPingWhenNoQuota) {
|
||||
std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = socket.get();
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
|
||||
EXPECT_CALL(*rawSocket, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _)).Times(0);
|
||||
uint8_t probesToSend = 0;
|
||||
EXPECT_EQ(
|
||||
0,
|
||||
@ -3286,12 +3287,12 @@ TEST_F(QuicTransportFunctionsTest, ProbingFallbackToPing) {
|
||||
auto socket =
|
||||
std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = socket.get();
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
uint8_t probesToSend = 1;
|
||||
EXPECT_EQ(
|
||||
1,
|
||||
@ -3315,12 +3316,12 @@ TEST_F(QuicTransportFunctionsTest, ProbingFallbackToImmediateAck) {
|
||||
auto socket =
|
||||
std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = socket.get();
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
uint8_t probesToSend = 1;
|
||||
EXPECT_EQ(
|
||||
1,
|
||||
@ -3464,13 +3465,13 @@ TEST_F(QuicTransportFunctionsTest, WritePureAckWhenNoWritableBytes) {
|
||||
.WillRepeatedly(Return(0));
|
||||
|
||||
uint64_t actualWritten = 0;
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
EXPECT_LE(iobuf->computeChainDataLength(), 30);
|
||||
actualWritten += iobuf->computeChainDataLength();
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
EXPECT_LE(getTotalIovecLen(vec, iovec_len), 30);
|
||||
actualWritten += getTotalIovecLen(vec, iovec_len);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
|
||||
auto res = writeQuicDataToSocket(
|
||||
*rawSocket,
|
||||
@ -4051,12 +4052,12 @@ TEST_F(QuicTransportFunctionsTest, WriteLimitBytRttFraction) {
|
||||
writeDataToQuicStream(*stream1, buf->clone(), true);
|
||||
|
||||
uint64_t actualWritten = 0;
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
actualWritten += iobuf->computeChainDataLength();
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
actualWritten += getTotalIovecLen(vec, iovec_len);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*rawCongestionController, getWritableBytes())
|
||||
.WillRepeatedly(Return(50));
|
||||
auto writeLoopBeginTime = Clock::now();
|
||||
@ -4111,7 +4112,7 @@ TEST_F(QuicTransportFunctionsTest, WriteLimitBytRttFractionNoLimit) {
|
||||
auto buf = buildRandomInputData(2048 * 2048);
|
||||
writeDataToQuicStream(*stream1, buf->clone(), true);
|
||||
|
||||
EXPECT_CALL(*rawSocket, write(_, _)).WillRepeatedly(Return(1));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _)).WillRepeatedly(Return(1));
|
||||
EXPECT_CALL(*rawCongestionController, getWritableBytes())
|
||||
.WillRepeatedly(Return(50));
|
||||
auto writeLoopBeginTime = Clock::now();
|
||||
@ -4248,11 +4249,11 @@ TEST_F(QuicTransportFunctionsTest, ProbeWriteNewFunctionalFrames) {
|
||||
auto sock = std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = sock.get();
|
||||
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
|
||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||
auto buf = folly::IOBuf::copyBuffer("Drug facts");
|
||||
@ -4299,11 +4300,11 @@ TEST_F(QuicTransportFunctionsTest, ProbeWriteNewFunctionalFramesAckFreq) {
|
||||
auto sock = std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb);
|
||||
auto rawSocket = sock.get();
|
||||
|
||||
EXPECT_CALL(*rawSocket, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*rawSocket, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
|
||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||
auto buf = folly::IOBuf::copyBuffer("Drug facts");
|
||||
@ -4362,17 +4363,18 @@ TEST_F(QuicTransportFunctionsTest, WriteWithInplaceBuilder) {
|
||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||
auto buf = folly::IOBuf::copyBuffer("Andante in C minor");
|
||||
writeDataToQuicStream(*stream, buf->clone(), true);
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& sockBuf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
auto) {
|
||||
EXPECT_GT(bufPtr->length(), 0);
|
||||
EXPECT_GE(sockBuf->length(), buf->length());
|
||||
EXPECT_EQ(sockBuf.get(), bufPtr);
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
|
||||
EXPECT_FALSE(sockBuf->isChained());
|
||||
return sockBuf->computeChainDataLength();
|
||||
EXPECT_GE(vec[0].iov_len, buf->length());
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(
|
||||
*folly::IOBuf::wrapIov(vec, iovec_len), *bufPtr));
|
||||
EXPECT_EQ(iovec_len, 1);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
writeQuicDataToSocket(
|
||||
mockSock,
|
||||
@ -4401,7 +4403,7 @@ TEST_F(QuicTransportFunctionsTest, WriteWithInplaceBuilderRollbackBuf) {
|
||||
std::make_shared<FollyQuicEventBase>(&evb);
|
||||
quic::test::MockAsyncUDPSocket mockSock(qEvb);
|
||||
EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(mockSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(mockSock, write(_, _, _)).Times(0);
|
||||
writeQuicDataToSocket(
|
||||
mockSock,
|
||||
*conn,
|
||||
@ -4432,17 +4434,18 @@ TEST_F(QuicTransportFunctionsTest, WriteWithInplaceBuilderGSOMultiplePackets) {
|
||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(conn->udpSendPacketLen * 10);
|
||||
writeDataToQuicStream(*stream, buf->clone(), true);
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& sockBuf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
QuicAsyncUDPSocket::WriteOptions options) {
|
||||
EXPECT_LE(options.gso, conn->udpSendPacketLen);
|
||||
EXPECT_GT(bufPtr->length(), 0);
|
||||
EXPECT_EQ(sockBuf.get(), bufPtr);
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
|
||||
EXPECT_FALSE(sockBuf->isChained());
|
||||
return sockBuf->length();
|
||||
EXPECT_GT(vec[0].iov_len, 0);
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(
|
||||
*folly::IOBuf::wrapIov(vec, iovec_len), *bufPtr));
|
||||
EXPECT_EQ(iovec_len, 1);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
writeQuicDataToSocket(
|
||||
mockSock,
|
||||
@ -4479,20 +4482,21 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingWithInplaceBuilder) {
|
||||
conn->udpSendPacketLen *
|
||||
conn->transportSettings.writeConnectionDataPacketsLimit);
|
||||
writeDataToQuicStream(*stream, inputBuf->clone(), true);
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& sockBuf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
QuicAsyncUDPSocket::WriteOptions options) {
|
||||
EXPECT_LE(options.gso, conn->udpSendPacketLen);
|
||||
EXPECT_GE(
|
||||
bufPtr->length(),
|
||||
conn->udpSendPacketLen *
|
||||
conn->transportSettings.writeConnectionDataPacketsLimit);
|
||||
EXPECT_EQ(sockBuf.get(), bufPtr);
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
|
||||
EXPECT_FALSE(sockBuf->isChained());
|
||||
return sockBuf->length();
|
||||
EXPECT_TRUE(folly::IOBufEqualTo()(
|
||||
*folly::IOBuf::wrapIov(vec, iovec_len), *bufPtr));
|
||||
EXPECT_EQ(iovec_len, 1);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
writeQuicDataToSocket(
|
||||
mockSock,
|
||||
@ -4515,14 +4519,15 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingWithInplaceBuilder) {
|
||||
conn->outstandings.packets.front().metadata.encodedSize;
|
||||
auto outstandingPacketsCount = conn->outstandings.packets.size();
|
||||
ASSERT_EQ(firstPacketSize, conn->udpSendPacketLen);
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
auto) {
|
||||
EXPECT_FALSE(buf->isChained());
|
||||
EXPECT_EQ(buf->length(), firstPacketSize);
|
||||
return buf->length();
|
||||
EXPECT_EQ(iovec_len, 1);
|
||||
EXPECT_EQ(vec[0].iov_len, firstPacketSize);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
writeProbingDataToSocketForTest(
|
||||
mockSock,
|
||||
@ -4536,15 +4541,16 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingWithInplaceBuilder) {
|
||||
EXPECT_EQ(0, bufPtr->headroom());
|
||||
|
||||
// Clone again, this time 2 pacckets.
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _))
|
||||
EXPECT_CALL(mockSock, writeGSO(_, _, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
QuicAsyncUDPSocket::WriteOptions options) {
|
||||
EXPECT_FALSE(buf->isChained());
|
||||
EXPECT_EQ(iovec_len, 1);
|
||||
EXPECT_EQ(conn->udpSendPacketLen, options.gso);
|
||||
EXPECT_EQ(buf->length(), conn->udpSendPacketLen * 2);
|
||||
return buf->length();
|
||||
EXPECT_EQ(vec[0].iov_len, conn->udpSendPacketLen * 2);
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
writeProbingDataToSocketForTest(
|
||||
mockSock,
|
||||
|
@ -142,12 +142,6 @@ RegularQuicWritePacket stripPaddingFrames(RegularQuicWritePacket packet) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
size_t bufLength(
|
||||
const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
return buf->computeChainDataLength();
|
||||
}
|
||||
|
||||
void dropPackets(QuicServerConnectionState& conn) {
|
||||
for (const auto& packet : conn.outstandings.packets) {
|
||||
for (const auto& frame : packet.packet.frames) {
|
||||
@ -267,12 +261,12 @@ TEST_F(QuicTransportTest, WriteDataWithProbing) {
|
||||
Invoke([&](const auto& /* packet */) { onPacketSentCounter++; }));
|
||||
// Probing will send out one. Then regular write may send out multiple ones:
|
||||
int socketWriteCounter = 0;
|
||||
EXPECT_CALL(*socket_, write(_, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& iobuf) {
|
||||
socketWriteCounter++;
|
||||
return iobuf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWriteCounter++;
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
transport_->writeChain(streamId, buf->clone(), true);
|
||||
loopForWrites();
|
||||
transport_->close(none);
|
||||
@ -1630,7 +1624,8 @@ TEST_F(QuicTransportTest, WriteSmall) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
transport_->setStreamPriority(stream, Priority(0, false));
|
||||
loopForWrites();
|
||||
@ -1639,7 +1634,8 @@ TEST_F(QuicTransportTest, WriteSmall) {
|
||||
|
||||
// Test retransmission
|
||||
dropPackets(conn);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1661,9 +1657,9 @@ TEST_F(QuicTransportTest, WriteLarge) {
|
||||
auto buf =
|
||||
buildRandomInputData(NumFullPackets * kDefaultUDPSendPacketLen + 20);
|
||||
folly::IOBuf passedIn;
|
||||
EXPECT_CALL(*socket_, write(_, _))
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.Times(NumFullPackets + 1)
|
||||
.WillRepeatedly(Invoke(bufLength));
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
auto& conn = transport_->getConnectionState();
|
||||
@ -1672,9 +1668,9 @@ TEST_F(QuicTransportTest, WriteLarge) {
|
||||
|
||||
// Test retransmission
|
||||
dropPackets(conn);
|
||||
EXPECT_CALL(*socket_, write(_, _))
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.Times(NumFullPackets + 1)
|
||||
.WillRepeatedly(Invoke(bufLength));
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1692,7 +1688,8 @@ TEST_F(QuicTransportTest, WriteLarge) {
|
||||
TEST_F(QuicTransportTest, WriteMultipleTimes) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
auto& conn = transport_->getConnectionState();
|
||||
@ -1703,7 +1700,8 @@ TEST_F(QuicTransportTest, WriteMultipleTimes) {
|
||||
conn.outstandings.reset();
|
||||
conn.streamManager->findStream(stream)->retransmissionBuffer.clear();
|
||||
buf = buildRandomInputData(50);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
verifyCorrectness(conn, originalWriteOffset, stream, *buf);
|
||||
@ -1715,14 +1713,16 @@ TEST_F(QuicTransportTest, WriteMultipleStreams) {
|
||||
auto s1 = transport_->createBidirectionalStream().value();
|
||||
auto s2 = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(s1, buf->clone(), false);
|
||||
loopForWrites();
|
||||
auto& conn = transport_->getConnectionState();
|
||||
verifyCorrectness(conn, 0, s1, *buf);
|
||||
|
||||
auto buf2 = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(s2, buf2->clone(), false);
|
||||
loopForWrites();
|
||||
verifyCorrectness(conn, 0, s2, *buf2);
|
||||
@ -1730,7 +1730,8 @@ TEST_F(QuicTransportTest, WriteMultipleStreams) {
|
||||
dropPackets(conn);
|
||||
|
||||
// Should retransmit lost streams in a single packet
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1761,7 +1762,8 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
|
||||
auto buf = buildRandomInputData(150);
|
||||
folly::IOBuf passedIn;
|
||||
// Write stream blocked frame
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(streamId, buf->clone(), false);
|
||||
|
||||
loopForWrites();
|
||||
@ -1793,7 +1795,8 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
|
||||
stream->flowControlState.pendingBlockedFrame = false;
|
||||
EXPECT_CALL(*mockQLogger, addTransportStateUpdate(getFlowControlEvent(200)));
|
||||
conn.streamManager->updateWritableStreams(*stream);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1809,7 +1812,9 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
|
||||
auto num_outstandings = conn.outstandings.packets.size();
|
||||
stream->flowControlState.peerAdvertisedMaxOffset = 300;
|
||||
conn.streamManager->updateWritableStreams(*stream);
|
||||
EXPECT_CALL(*socket_, write(_, _)).Times(2).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1841,7 +1846,7 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
|
||||
|
||||
// Try again, verify that there should not be any Data blocked frame emitted
|
||||
// again.
|
||||
EXPECT_CALL(*socket_, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).Times(0);
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1854,7 +1859,8 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
|
||||
|
||||
// Flow control lifted
|
||||
stream->conn.flowControlState.peerAdvertisedMaxOffset = 300;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1871,7 +1877,7 @@ TEST_F(QuicTransportTest, WriteErrorEagain) {
|
||||
// Test network error
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
}
|
||||
@ -1880,7 +1886,7 @@ TEST_F(QuicTransportTest, WriteErrorBad) {
|
||||
// Test network error
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
EXPECT_TRUE(transport_->closed);
|
||||
@ -1898,7 +1904,8 @@ TEST_F(QuicTransportTest, WriteInvalid) {
|
||||
TEST_F(QuicTransportTest, WriteFin) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), true);
|
||||
loopForWrites();
|
||||
auto& conn = transport_->getConnectionState();
|
||||
@ -1906,7 +1913,8 @@ TEST_F(QuicTransportTest, WriteFin) {
|
||||
|
||||
// Test retransmission
|
||||
dropPackets(conn);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1923,10 +1931,12 @@ TEST_F(QuicTransportTest, WriteFin) {
|
||||
TEST_F(QuicTransportTest, WriteOnlyFin) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, nullptr, true);
|
||||
loopForWrites();
|
||||
auto& conn = transport_->getConnectionState();
|
||||
@ -1934,7 +1944,8 @@ TEST_F(QuicTransportTest, WriteOnlyFin) {
|
||||
|
||||
// Test retransmission
|
||||
dropPackets(conn);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -1951,7 +1962,8 @@ TEST_F(QuicTransportTest, WriteOnlyFin) {
|
||||
TEST_F(QuicTransportTest, WriteDataWithRetransmission) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
auto& conn = transport_->getConnectionState();
|
||||
@ -1959,7 +1971,8 @@ TEST_F(QuicTransportTest, WriteDataWithRetransmission) {
|
||||
|
||||
dropPackets(conn);
|
||||
auto buf2 = buildRandomInputData(50);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf2->clone(), false);
|
||||
loopForWrites();
|
||||
// The first packet was lost. We should expect this packet contains both
|
||||
@ -1975,7 +1988,8 @@ TEST_F(QuicTransportTest, WriteImmediateAcks) {
|
||||
PacketNum end = 15;
|
||||
conn.ackStates.appDataAckState.needsToSendAckImmediately = true;
|
||||
addAckStatesWithCurrentTimestamps(conn.ackStates.appDataAckState, start, end);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -2001,7 +2015,8 @@ TEST_F(QuicTransportTest, WritePendingAckIfHavingData) {
|
||||
addAckStatesWithCurrentTimestamps(conn.ackStates.appDataAckState, start, end);
|
||||
conn.ackStates.appDataAckState.needsToSendAckImmediately = false;
|
||||
conn.ackStates.appDataAckState.numNonRxPacketsRecvd = 3;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
// We should write acks if there is data pending
|
||||
transport_->writeChain(streamId, buf->clone(), true);
|
||||
loopForWrites();
|
||||
@ -2042,7 +2057,8 @@ TEST_F(QuicTransportTest, NoWritePendingAckIfHavingData) {
|
||||
addAckStatesWithCurrentTimestamps(conn.ackStates.appDataAckState, start, end);
|
||||
conn.ackStates.appDataAckState.needsToSendAckImmediately = false;
|
||||
conn.ackStates.appDataAckState.numNonRxPacketsRecvd = 3;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
// We should write acks if there is data pending
|
||||
transport_->writeChain(streamId, buf->clone(), true);
|
||||
loopForWrites();
|
||||
@ -2071,7 +2087,8 @@ TEST_F(QuicTransportTest, NoWritePendingAckIfHavingData) {
|
||||
|
||||
TEST_F(QuicTransportTest, RstStream) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||
loopForWrites();
|
||||
EXPECT_EQ(1, transport_->getConnectionState().outstandings.packets.size());
|
||||
@ -2107,7 +2124,8 @@ TEST_F(QuicTransportTest, RstStream) {
|
||||
|
||||
TEST_F(QuicTransportTest, StopSending) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->stopSending(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||
loopForWrites();
|
||||
EXPECT_EQ(1, transport_->getConnectionState().outstandings.packets.size());
|
||||
@ -2136,7 +2154,8 @@ TEST_F(QuicTransportTest, StopSending) {
|
||||
TEST_F(QuicTransportTest, StopSendingReadCallbackDefault) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
NiceMock<MockReadCallback> readCb;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->setReadCallback(streamId, &readCb);
|
||||
transport_->setReadCallback(streamId, nullptr);
|
||||
loopForWrites();
|
||||
@ -2166,7 +2185,8 @@ TEST_F(QuicTransportTest, StopSendingReadCallbackDefault) {
|
||||
TEST_F(QuicTransportTest, StopSendingReadCallback) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
NiceMock<MockReadCallback> readCb;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->setReadCallback(streamId, &readCb);
|
||||
transport_->setReadCallback(
|
||||
streamId, nullptr, GenericApplicationErrorCode::UNKNOWN);
|
||||
@ -2213,7 +2233,8 @@ TEST_F(QuicTransportTest, NoStopSendingReadCallback) {
|
||||
}
|
||||
|
||||
TEST_F(QuicTransportTest, SendPathChallenge) {
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto& conn = transport_->getConnectionState();
|
||||
PathChallengeFrame pathChallenge(123);
|
||||
conn.pendingEvents.pathChallenge = pathChallenge;
|
||||
@ -2257,7 +2278,8 @@ TEST_F(QuicTransportTest, SendPathChallenge) {
|
||||
}
|
||||
|
||||
TEST_F(QuicTransportTest, PathValidationTimeoutExpired) {
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto& conn = transport_->getConnectionState();
|
||||
PathChallengeFrame pathChallenge(123);
|
||||
conn.pendingEvents.pathChallenge = pathChallenge;
|
||||
@ -2442,7 +2464,8 @@ TEST_F(QuicTransportTest, DoNotResendLostPathChallengeIfNotOutstanding) {
|
||||
}
|
||||
|
||||
TEST_F(QuicTransportTest, SendPathResponse) {
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto& conn = transport_->getConnectionState();
|
||||
EXPECT_EQ(conn.pendingEvents.frames.size(), 0);
|
||||
PathResponseFrame pathResponse(123);
|
||||
@ -2565,7 +2588,8 @@ TEST_F(QuicTransportTest, ResendPathResponseOnLoss) {
|
||||
}
|
||||
|
||||
TEST_F(QuicTransportTest, SendNewConnectionIdFrame) {
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto& conn = transport_->getConnectionState();
|
||||
NewConnectionIdFrame newConnId(
|
||||
1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
|
||||
@ -2656,7 +2680,7 @@ TEST_F(QuicTransportTest, BusyWriteLoopDetection) {
|
||||
EXPECT_TRUE(conn.writeDebugState.needsWriteLoopDetect);
|
||||
EXPECT_EQ(0, conn.writeDebugState.currentEmptyLoopCount);
|
||||
EXPECT_EQ(WriteDataReason::STREAM, conn.writeDebugState.writeDataReason);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Return(1000));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(Return(1000));
|
||||
loopForWrites();
|
||||
EXPECT_EQ(1, conn.outstandings.packets.size());
|
||||
EXPECT_EQ(0, conn.writeDebugState.currentEmptyLoopCount);
|
||||
@ -2667,7 +2691,7 @@ TEST_F(QuicTransportTest, BusyWriteLoopDetection) {
|
||||
EXPECT_TRUE(
|
||||
WriteDataReason::STREAM_WINDOW_UPDATE ==
|
||||
conn.writeDebugState.writeDataReason);
|
||||
EXPECT_CALL(*socket_, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(
|
||||
*rawLoopDetectorCallback,
|
||||
onSuspiciousWriteLoops(1, WriteDataReason::STREAM_WINDOW_UPDATE, _, _))
|
||||
@ -2704,7 +2728,8 @@ TEST_F(QuicTransportTest, ResendNewConnectionIdOnLoss) {
|
||||
}
|
||||
|
||||
TEST_F(QuicTransportTest, SendRetireConnectionIdFrame) {
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto& conn = transport_->getConnectionState();
|
||||
RetireConnectionIdFrame retireConnId(1);
|
||||
sendSimpleFrame(conn, retireConnId);
|
||||
@ -2790,7 +2815,8 @@ TEST_F(QuicTransportTest, ResendRetireConnectionIdOnLoss) {
|
||||
TEST_F(QuicTransportTest, NonWritableStreamAPI) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto& conn = transport_->getConnectionState();
|
||||
auto streamState = conn.streamManager->getStream(streamId);
|
||||
|
||||
@ -2826,7 +2852,8 @@ TEST_F(QuicTransportTest, RstWrittenStream) {
|
||||
ASSERT_TRUE(stream);
|
||||
auto currentWriteOffset = stream->currentWriteOffset;
|
||||
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||
loopForWrites();
|
||||
// 2 packets are outstanding: one for Stream frame one for RstStream frame:
|
||||
@ -2860,7 +2887,7 @@ TEST_F(QuicTransportTest, RstWrittenStream) {
|
||||
|
||||
TEST_F(QuicTransportTest, RstStreamUDPWriteFailNonFatal) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
transport_->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||
loopForWrites();
|
||||
|
||||
@ -2897,7 +2924,7 @@ TEST_F(QuicTransportTest, RstStreamUDPWriteFailNonFatal) {
|
||||
|
||||
TEST_F(QuicTransportTest, RstStreamUDPWriteFailFatal) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
EXPECT_CALL(*socket_, write(_, _))
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(SetErrnoAndReturn(EBADF, -1));
|
||||
transport_->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||
loopForWrites();
|
||||
@ -2916,7 +2943,8 @@ TEST_F(QuicTransportTest, WriteAfterSendRst) {
|
||||
auto stream = conn.streamManager->findStream(streamId);
|
||||
ASSERT_TRUE(stream);
|
||||
auto currentWriteOffset = stream->currentWriteOffset;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||
loopForWrites();
|
||||
|
||||
@ -2960,7 +2988,8 @@ TEST_F(QuicTransportTest, WriteAfterSendRst) {
|
||||
|
||||
TEST_F(QuicTransportTest, DoubleReset) {
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
EXPECT_FALSE(
|
||||
transport_->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN)
|
||||
.hasError());
|
||||
@ -2975,7 +3004,8 @@ TEST_F(QuicTransportTest, DoubleReset) {
|
||||
TEST_F(QuicTransportTest, WriteStreamDataSetLossAlarm) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(1);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
EXPECT_TRUE(transport_->isLossTimeoutScheduled());
|
||||
@ -2986,7 +3016,8 @@ TEST_F(QuicTransportTest, WriteAckNotSetLossAlarm) {
|
||||
addAckStatesWithCurrentTimestamps(
|
||||
conn.ackStates.appDataAckState, 0 /* start */, 100 /* ind */);
|
||||
conn.ackStates.appDataAckState.needsToSendAckImmediately = true;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto res = writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -3005,7 +3036,8 @@ TEST_F(QuicTransportTest, WriteWindowUpdate) {
|
||||
conn.flowControlState.windowSize = 100;
|
||||
conn.flowControlState.advertisedMaxOffset = 0;
|
||||
conn.pendingEvents.connWindowUpdate = true;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
auto res = writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -3041,7 +3073,8 @@ TEST_F(QuicTransportTest, WriteWindowUpdate) {
|
||||
streamState->flowControlState.advertisedMaxOffset = 0;
|
||||
MaxStreamDataFrame frame(stream, 100);
|
||||
conn.streamManager->queueWindowUpdate(stream);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
res = writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -3084,7 +3117,8 @@ TEST_F(QuicTransportTest, DeliveryCallbackClosesClosedTransport) {
|
||||
auto stream1 = transport_->createBidirectionalStream().value();
|
||||
auto buf1 = buildRandomInputData(20);
|
||||
TransportClosingDeliveryCallback dc(transport_.get(), 20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream1, buf1->clone(), true, &dc);
|
||||
loopForWrites();
|
||||
transport_->close(none);
|
||||
@ -3094,7 +3128,8 @@ TEST_F(QuicTransportTest, DeliveryCallbackClosesTransportOnDelivered) {
|
||||
auto stream1 = transport_->createBidirectionalStream().value();
|
||||
auto buf1 = buildRandomInputData(20);
|
||||
TransportClosingDeliveryCallback dc(transport_.get(), 0);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->registerDeliveryCallback(stream1, 0, &dc);
|
||||
transport_->writeChain(stream1, buf1->clone(), true);
|
||||
loopForWrites();
|
||||
@ -3113,7 +3148,8 @@ TEST_F(QuicTransportTest, InvokeDeliveryCallbacksNothingDelivered) {
|
||||
NiceMock<MockDeliveryCallback> mockedDeliveryCallback;
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->registerDeliveryCallback(stream, 1, &mockedDeliveryCallback);
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
@ -3147,7 +3183,8 @@ TEST_F(QuicTransportTest, InvokeDeliveryCallbacksAllDelivered) {
|
||||
NiceMock<MockDeliveryCallback> mockedDeliveryCallback;
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(20);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->registerDeliveryCallback(stream, 1, &mockedDeliveryCallback);
|
||||
transport_->writeChain(stream, buf->clone(), true);
|
||||
loopForWrites();
|
||||
@ -3171,7 +3208,8 @@ TEST_F(QuicTransportTest, InvokeDeliveryCallbacksPartialDelivered) {
|
||||
mockedDeliveryCallback2;
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(100);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->registerDeliveryCallback(stream, 50, &mockedDeliveryCallback1);
|
||||
transport_->registerDeliveryCallback(stream, 150, &mockedDeliveryCallback2);
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
@ -3212,7 +3250,8 @@ TEST_F(QuicTransportTest, InvokeDeliveryCallbacksRetxBuffer) {
|
||||
mockedDeliveryCallback2;
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(100);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->registerDeliveryCallback(stream, 50, &mockedDeliveryCallback1);
|
||||
transport_->registerDeliveryCallback(stream, 150, &mockedDeliveryCallback2);
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
@ -3259,7 +3298,8 @@ TEST_F(QuicTransportTest, InvokeDeliveryCallbacksLossAndRetxBuffer) {
|
||||
mockedDeliveryCallback2, mockedDeliveryCallback3;
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(100);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->registerDeliveryCallback(stream, 30, &mockedDeliveryCallback1);
|
||||
transport_->registerDeliveryCallback(stream, 50, &mockedDeliveryCallback2);
|
||||
transport_->registerDeliveryCallback(stream, 150, &mockedDeliveryCallback3);
|
||||
@ -4219,7 +4259,8 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
|
||||
auto stream2 = conn.streamManager->getStream(s2);
|
||||
writeDataToQuicStream(*stream2, buf2->clone(), false);
|
||||
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -4242,7 +4283,8 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
|
||||
conn.streamManager->writeQueue().setNextScheduledStream(s2);
|
||||
writableBytes = kDefaultUDPSendPacketLen - 100;
|
||||
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -4266,7 +4308,8 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
|
||||
// Test wrap around
|
||||
conn.streamManager->writeQueue().setNextScheduledStream(s2);
|
||||
writableBytes = kDefaultUDPSendPacketLen;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillOnce(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
writeQuicDataToSocket(
|
||||
*socket_,
|
||||
conn,
|
||||
@ -4392,7 +4435,8 @@ TEST_F(QuicTransportTest, CloseTransportCancelsAckTimeout) {
|
||||
auto stream = transport_->createBidirectionalStream().value();
|
||||
auto buf = buildRandomInputData(kDefaultUDPSendPacketLen + 20);
|
||||
folly::IOBuf passedIn;
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillRepeatedly(Invoke(bufLength));
|
||||
EXPECT_CALL(*socket_, write(_, _, _))
|
||||
.WillRepeatedly(testing::WithArgs<1, 2>(Invoke(getTotalIovecLen)));
|
||||
transport_->writeChain(stream, buf->clone(), false);
|
||||
loopForWrites();
|
||||
transport_->scheduleLossTimeout(500ms);
|
||||
@ -4453,7 +4497,7 @@ TEST_F(QuicTransportTest, PacedWriteNoDataToWrite) {
|
||||
ASSERT_EQ(
|
||||
WriteDataReason::NO_WRITE,
|
||||
shouldWriteData(transport_->getConnectionState()));
|
||||
EXPECT_CALL(*socket_, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).Times(0);
|
||||
transport_->pacedWrite();
|
||||
}
|
||||
|
||||
@ -4474,7 +4518,7 @@ TEST_F(QuicTransportTest, PacingWillBurstFirst) {
|
||||
auto buf = buildRandomInputData(200);
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
transport_->writeChain(streamId, buf->clone(), false);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Return(0));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(Return(0));
|
||||
EXPECT_CALL(*rawPacer, updateAndGetWriteBatchSize(_))
|
||||
.WillRepeatedly(Return(1));
|
||||
transport_->pacedWrite();
|
||||
@ -4499,7 +4543,7 @@ TEST_F(QuicTransportTest, AlreadyScheduledPacingNoWrite) {
|
||||
auto buf = buildRandomInputData(200);
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
transport_->writeChain(streamId, buf->clone(), false);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Return(0));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(Return(0));
|
||||
EXPECT_CALL(*rawPacer, updateAndGetWriteBatchSize(_))
|
||||
.WillRepeatedly(Return(1));
|
||||
EXPECT_CALL(*rawPacer, getTimeUntilNextWrite(_))
|
||||
@ -4510,7 +4554,7 @@ TEST_F(QuicTransportTest, AlreadyScheduledPacingNoWrite) {
|
||||
|
||||
ASSERT_NE(WriteDataReason::NO_WRITE, shouldWriteData(conn));
|
||||
EXPECT_TRUE(transport_->isPacingScheduled());
|
||||
EXPECT_CALL(*socket_, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).Times(0);
|
||||
transport_->pacedWrite();
|
||||
}
|
||||
|
||||
@ -4531,7 +4575,7 @@ TEST_F(QuicTransportTest, NoScheduleIfNoNewData) {
|
||||
auto buf = buildRandomInputData(200);
|
||||
auto streamId = transport_->createBidirectionalStream().value();
|
||||
transport_->writeChain(streamId, buf->clone(), false);
|
||||
EXPECT_CALL(*socket_, write(_, _)).WillOnce(Return(0));
|
||||
EXPECT_CALL(*socket_, write(_, _, _)).WillOnce(Return(0));
|
||||
EXPECT_CALL(*rawPacer, updateAndGetWriteBatchSize(_))
|
||||
.WillRepeatedly(Return(1));
|
||||
// This will write out everything. After that because there is no new data,
|
||||
|
@ -1041,9 +1041,11 @@ void QuicClientTransport::startCryptoHandshake() {
|
||||
conn_->transportParametersEncoded = true;
|
||||
if (!conn_->transportSettings.flowPriming.empty() &&
|
||||
conn_->peerAddress.isInitialized()) {
|
||||
socket_->write(
|
||||
conn_->peerAddress,
|
||||
folly::IOBuf::copyBuffer(conn_->transportSettings.flowPriming));
|
||||
auto flowPrimingBuf =
|
||||
folly::IOBuf::copyBuffer(conn_->transportSettings.flowPriming);
|
||||
iovec vec[kNumIovecBufferChains];
|
||||
size_t iovec_len = fillIovec(flowPrimingBuf, vec);
|
||||
socket_->write(conn_->peerAddress, vec, iovec_len);
|
||||
}
|
||||
handshakeLayer->connect(hostname_, std::move(paramsExtension));
|
||||
|
||||
|
@ -9,6 +9,17 @@
|
||||
|
||||
namespace quic {
|
||||
|
||||
size_t fillIovec(std::unique_ptr<folly::IOBuf>& buf, iovec (&vec)[16]) {
|
||||
size_t iovec_len = buf->fillIov(vec, sizeof(vec) / sizeof(vec[0])).numIovecs;
|
||||
if (FOLLY_UNLIKELY(iovec_len == 0)) {
|
||||
buf->coalesce();
|
||||
vec[0].iov_base = const_cast<uint8_t*>(buf->data());
|
||||
vec[0].iov_len = buf->length();
|
||||
iovec_len = 1;
|
||||
}
|
||||
return iovec_len;
|
||||
}
|
||||
|
||||
Buf BufQueue::splitAtMost(size_t len) {
|
||||
folly::IOBuf* current = chain_.get();
|
||||
// empty queue / requested 0 bytes
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
namespace quic {
|
||||
|
||||
size_t fillIovec(std::unique_ptr<folly::IOBuf>& buf, iovec (&vec)[16]);
|
||||
|
||||
class BufQueue {
|
||||
public:
|
||||
BufQueue() = default;
|
||||
|
@ -821,5 +821,26 @@ std::unique_ptr<folly::IOBuf> getProtectionKey() {
|
||||
folly::IOBuf::create(0),
|
||||
pnCipher->keyLength());
|
||||
}
|
||||
|
||||
size_t getTotalIovecLen(const struct iovec* vec, size_t iovec_len) {
|
||||
uint32_t result = 0;
|
||||
for (uint32_t i = 0; i < iovec_len; i++) {
|
||||
result += vec[i].iov_len;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Buf copyChain(Buf&& input) {
|
||||
folly::IOBuf* current = input.get();
|
||||
Buf headCopy = folly::IOBuf::copyBuffer(current->data(), current->length());
|
||||
current = current->next();
|
||||
while (current != input.get()) {
|
||||
Buf currCopy = folly::IOBuf::copyBuffer(current->data(), current->length());
|
||||
headCopy->appendToChain(std::move(currCopy));
|
||||
current = current->next();
|
||||
}
|
||||
return headCopy;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace quic
|
||||
|
@ -580,5 +580,9 @@ class FakeServerHandshake : public FizzServerHandshake {
|
||||
Optional<uint64_t> clientActiveConnectionIdLimit_;
|
||||
};
|
||||
|
||||
size_t getTotalIovecLen(const struct iovec* vec, size_t iovec_len);
|
||||
|
||||
Buf copyChain(Buf&& input);
|
||||
|
||||
} // namespace test
|
||||
} // namespace quic
|
||||
|
@ -26,7 +26,7 @@ struct MockAsyncUDPSocket : public FollyQuicAsyncUDPSocket {
|
||||
MOCK_METHOD(
|
||||
ssize_t,
|
||||
write,
|
||||
(const folly::SocketAddress&, const std::unique_ptr<folly::IOBuf>&));
|
||||
(const folly::SocketAddress&, const struct iovec*, size_t));
|
||||
MOCK_METHOD(
|
||||
int,
|
||||
writem,
|
||||
@ -37,7 +37,8 @@ struct MockAsyncUDPSocket : public FollyQuicAsyncUDPSocket {
|
||||
ssize_t,
|
||||
writeGSO,
|
||||
(const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>&,
|
||||
const struct iovec*,
|
||||
size_t,
|
||||
QuicAsyncUDPSocket::WriteOptions));
|
||||
MOCK_METHOD(
|
||||
ssize_t,
|
||||
|
@ -57,8 +57,11 @@ void FollyQuicAsyncUDPSocket::setErrMessageCallback(
|
||||
|
||||
ssize_t FollyQuicAsyncUDPSocket::write(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
return follySocket_.write(address, buf);
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
folly::AsyncUDPSocket::WriteOptions writeOptions(
|
||||
0 /*gsoVal*/, false /* zerocopyVal*/);
|
||||
return follySocket_.writev(address, vec, iovec_len, writeOptions);
|
||||
}
|
||||
|
||||
int FollyQuicAsyncUDPSocket::writem(
|
||||
@ -70,12 +73,13 @@ int FollyQuicAsyncUDPSocket::writem(
|
||||
|
||||
ssize_t FollyQuicAsyncUDPSocket::writeGSO(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
WriteOptions options) {
|
||||
folly::AsyncUDPSocket::WriteOptions follyOptions(
|
||||
options.gso, options.zerocopy);
|
||||
follyOptions.txTime = options.txTime;
|
||||
return follySocket_.writeGSO(address, buf, follyOptions);
|
||||
return follySocket_.writev(address, vec, iovec_len, follyOptions);
|
||||
}
|
||||
|
||||
int FollyQuicAsyncUDPSocket::writemGSO(
|
||||
|
@ -70,7 +70,8 @@ class FollyQuicAsyncUDPSocket : public QuicAsyncUDPSocketImpl {
|
||||
|
||||
ssize_t write(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) override;
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) override;
|
||||
|
||||
int writem(
|
||||
folly::Range<folly::SocketAddress const*> addrs,
|
||||
@ -79,7 +80,8 @@ class FollyQuicAsyncUDPSocket : public QuicAsyncUDPSocketImpl {
|
||||
|
||||
ssize_t writeGSO(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
WriteOptions options) override;
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,8 @@ void LibevQuicAsyncUDPSocket::pauseWrite() {
|
||||
|
||||
ssize_t LibevQuicAsyncUDPSocket::write(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
if (fd_ == -1) {
|
||||
throw folly::AsyncSocketException(
|
||||
folly::AsyncSocketException::NOT_OPEN, "socket is not initialized");
|
||||
@ -97,15 +98,6 @@ ssize_t LibevQuicAsyncUDPSocket::write(
|
||||
msg.msg_namelen = 0;
|
||||
}
|
||||
|
||||
iovec vec[16];
|
||||
size_t iovec_len = buf->fillIov(vec, sizeof(vec) / sizeof(vec[0])).numIovecs;
|
||||
if (UNLIKELY(iovec_len == 0)) {
|
||||
buf->coalesce();
|
||||
vec[0].iov_base = const_cast<uint8_t*>(buf->data());
|
||||
vec[0].iov_len = buf->length();
|
||||
iovec_len = 1;
|
||||
}
|
||||
|
||||
msg.msg_iov = const_cast<struct iovec*>(vec);
|
||||
msg.msg_iovlen = iovec_len;
|
||||
msg.msg_control = nullptr;
|
||||
|
@ -36,7 +36,8 @@ class LibevQuicAsyncUDPSocket : public QuicAsyncUDPSocketImpl {
|
||||
|
||||
ssize_t write(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) override;
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) override;
|
||||
|
||||
int writem(
|
||||
folly::Range<folly::SocketAddress const*> addrs,
|
||||
@ -45,7 +46,8 @@ class LibevQuicAsyncUDPSocket : public QuicAsyncUDPSocketImpl {
|
||||
|
||||
ssize_t writeGSO(
|
||||
const folly::SocketAddress& /*address*/,
|
||||
const std::unique_ptr<folly::IOBuf>& /*buf*/,
|
||||
const struct iovec* /* vec */,
|
||||
size_t /* iovec_len */,
|
||||
WriteOptions /*options*/) override {
|
||||
LOG(FATAL) << __func__ << " not supported in LibevQuicAsyncUDPSocket";
|
||||
}
|
||||
|
@ -156,7 +156,8 @@ class QuicAsyncUDPSocket {
|
||||
*/
|
||||
virtual ssize_t write(
|
||||
const folly::SocketAddress& /* address */,
|
||||
const std::unique_ptr<folly::IOBuf>& /* buf */) = 0;
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) = 0;
|
||||
|
||||
/**
|
||||
* Send the data in buffers to destination. Returns the return code from
|
||||
@ -189,7 +190,8 @@ class QuicAsyncUDPSocket {
|
||||
*/
|
||||
virtual ssize_t writeGSO(
|
||||
const folly::SocketAddress& address,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
WriteOptions options) = 0;
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ class QuicAsyncUDPSocketMock : public QuicAsyncUDPSocket {
|
||||
MOCK_METHOD(
|
||||
(ssize_t),
|
||||
write,
|
||||
(const folly::SocketAddress&, const std::unique_ptr<folly::IOBuf>&));
|
||||
(const folly::SocketAddress&, const struct iovec* vec, size_t iovec_len));
|
||||
MOCK_METHOD(
|
||||
(int),
|
||||
writem,
|
||||
@ -35,7 +35,8 @@ class QuicAsyncUDPSocketMock : public QuicAsyncUDPSocket {
|
||||
ssize_t,
|
||||
writeGSO,
|
||||
(const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>&,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
WriteOptions));
|
||||
MOCK_METHOD(
|
||||
(int),
|
||||
|
@ -60,7 +60,11 @@ TYPED_TEST_P(QuicAsyncUDPSocketTest, ErrToNonExistentServer) {
|
||||
// If an error is received, the read callback should not be triggered
|
||||
EXPECT_CALL(this->readCb_, onNotifyDataAvailable_(testing::_)).Times(0);
|
||||
#endif // FOLLY_HAVE_MSG_ERRQUEUE
|
||||
this->udpSocket_->write(addr, folly::IOBuf::copyBuffer("hey"));
|
||||
auto sendBuf = folly::IOBuf::copyBuffer("hey");
|
||||
iovec vec[quic::kNumIovecBufferChains];
|
||||
size_t iovec_len =
|
||||
sendBuf->fillIov(vec, sizeof(vec) / sizeof(vec[0])).numIovecs;
|
||||
this->udpSocket_->write(addr, vec, iovec_len);
|
||||
this->udpSocket_->getEventBase()->loopForever();
|
||||
EXPECT_TRUE(errRecvd);
|
||||
}
|
||||
@ -72,7 +76,12 @@ TYPED_TEST_P(QuicAsyncUDPSocketTest, TestUnsetErrCallback) {
|
||||
folly::SocketAddress addr("127.0.0.1", 10000);
|
||||
EXPECT_CALL(this->errCb_, errMessage_(testing::_)).Times(0);
|
||||
EXPECT_CALL(this->readCb_, onNotifyDataAvailable_(testing::_)).Times(0);
|
||||
this->udpSocket_->write(addr, folly::IOBuf::copyBuffer("hey"));
|
||||
|
||||
auto sendBuf = folly::IOBuf::copyBuffer("hey");
|
||||
iovec vec[quic::kNumIovecBufferChains];
|
||||
size_t iovec_len =
|
||||
sendBuf->fillIov(vec, sizeof(vec) / sizeof(vec[0])).numIovecs;
|
||||
this->udpSocket_->write(addr, vec, iovec_len);
|
||||
|
||||
class EvbTerminateTimeout : public quic::QuicTimerCallback {
|
||||
public:
|
||||
@ -113,7 +122,11 @@ TYPED_TEST_P(QuicAsyncUDPSocketTest, CloseInErrorCallback) {
|
||||
// should not be triggered
|
||||
EXPECT_CALL(this->readCb_, onNotifyDataAvailable_(testing::_)).Times(0);
|
||||
#endif // FOLLY_HAVE_MSG_ERRQUEUE
|
||||
this->udpSocket_->write(addr, folly::IOBuf::copyBuffer("hey"));
|
||||
auto sendBuf = folly::IOBuf::copyBuffer("hey");
|
||||
iovec vec[quic::kNumIovecBufferChains];
|
||||
size_t iovec_len =
|
||||
sendBuf->fillIov(vec, sizeof(vec) / sizeof(vec[0])).numIovecs;
|
||||
this->udpSocket_->write(addr, vec, iovec_len);
|
||||
this->udpSocket_->getEventBase()->loopForever();
|
||||
EXPECT_TRUE(errRecvd);
|
||||
}
|
||||
|
@ -171,18 +171,20 @@ TEST_F(DSRMultiWriteTest, TwoRequestsWithLoss) {
|
||||
|
||||
std::vector<Buf> sentData;
|
||||
auto sock = std::make_unique<NiceMock<quic::test::MockAsyncUDPSocket>>(qEvb_);
|
||||
EXPECT_CALL(*sock, writeGSO(conn_.peerAddress, _, _))
|
||||
EXPECT_CALL(*sock, writeGSO(conn_.peerAddress, _, _, _))
|
||||
.WillRepeatedly(Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len,
|
||||
QuicAsyncUDPSocket::WriteOptions) {
|
||||
sentData.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
sentData.push_back(copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*sock, write(conn_.peerAddress, _))
|
||||
EXPECT_CALL(*sock, write(conn_.peerAddress, _, _))
|
||||
.WillRepeatedly(Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
sentData.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
sentData.push_back(copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
auto& instruction = pendingInstructions_.front();
|
||||
CipherBuilder builder;
|
||||
|
@ -1057,7 +1057,7 @@ TEST_F(QuicClientTransportTest, FirstPacketProcessedCallback) {
|
||||
|
||||
TEST_F(QuicClientTransportTest, CloseSocketOnWriteError) {
|
||||
client->addNewPeerAddress(serverAddr);
|
||||
EXPECT_CALL(*sock, write(_, _)).WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(*sock, write(_, _, _)).WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
|
||||
EXPECT_FALSE(client->isClosed());
|
||||
@ -1162,11 +1162,13 @@ TEST_F(QuicClientTransportTest, SocketClosedDuringOnTransportReady) {
|
||||
ConnectionCallbackThatWritesOnTransportReady callback(client);
|
||||
EXPECT_CALL(callback, onTransportReadyMock());
|
||||
EXPECT_CALL(callback, onReplaySafe()).Times(0);
|
||||
ON_CALL(*sock, write(_, _))
|
||||
ON_CALL(*sock, write(_, _, _))
|
||||
.WillByDefault(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
;
|
||||
}));
|
||||
ON_CALL(*sock, address()).WillByDefault(ReturnRef(serverAddr));
|
||||
|
||||
@ -1181,7 +1183,8 @@ TEST_F(QuicClientTransportTest, NetworkUnreachableIsFatalToConn) {
|
||||
client->addNewPeerAddress(serverAddr);
|
||||
setupCryptoLayer();
|
||||
EXPECT_CALL(clientConnSetupCallback, onConnectionSetupError(_));
|
||||
EXPECT_CALL(*sock, write(_, _)).WillOnce(SetErrnoAndReturn(ENETUNREACH, -1));
|
||||
EXPECT_CALL(*sock, write(_, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(ENETUNREACH, -1));
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
loopForWrites();
|
||||
}
|
||||
@ -1380,14 +1383,16 @@ class QuicClientTransportHappyEyeballsTest
|
||||
auto& conn = client->getConn();
|
||||
setupInitialDcidForRetry();
|
||||
auto firstPacketType = GetParam();
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
setConnectionIds();
|
||||
|
||||
@ -1406,7 +1411,7 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_CALL(clientConnSetupCallback, onTransportReady());
|
||||
EXPECT_CALL(clientConnSetupCallback, onReplaySafe());
|
||||
}
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, pauseRead());
|
||||
EXPECT_CALL(*secondSock, close());
|
||||
if (firstPacketType == ServerFirstPacketType::Retry) {
|
||||
@ -1428,13 +1433,15 @@ class QuicClientTransportHappyEyeballsTest
|
||||
auto firstPacketType = GetParam();
|
||||
setupInitialDcidForRetry();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
setConnectionIds();
|
||||
|
||||
@ -1458,13 +1465,15 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
EXPECT_EQ(socketWrites.size(), 1);
|
||||
@ -1477,14 +1486,16 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_CALL(clientConnSetupCallback, onTransportReady());
|
||||
EXPECT_CALL(clientConnSetupCallback, onReplaySafe());
|
||||
}
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, pauseRead());
|
||||
EXPECT_CALL(*secondSock, close());
|
||||
if (firstPacketType == ServerFirstPacketType::Retry) {
|
||||
@ -1506,13 +1517,15 @@ class QuicClientTransportHappyEyeballsTest
|
||||
auto firstPacketType = GetParam();
|
||||
setupInitialDcidForRetry();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
setConnectionIds();
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
@ -1536,12 +1549,14 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.WillOnce(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
@ -1556,15 +1571,17 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_CALL(clientConnSetupCallback, onTransportReady());
|
||||
EXPECT_CALL(clientConnSetupCallback, onReplaySafe());
|
||||
}
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*sock, pauseRead());
|
||||
EXPECT_CALL(*sock, close());
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Invoke([&](const SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
if (firstPacketType == ServerFirstPacketType::Retry) {
|
||||
recvServerRetry(secondAddress);
|
||||
@ -1584,7 +1601,7 @@ class QuicClientTransportHappyEyeballsTest
|
||||
auto& conn = client->getConn();
|
||||
setupInitialDcidForRetry();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, bind(_))
|
||||
.WillOnce(Invoke(
|
||||
[](const folly::SocketAddress&) { throw std::exception(); }));
|
||||
@ -1603,9 +1620,9 @@ class QuicClientTransportHappyEyeballsTest
|
||||
auto& conn = client->getConn();
|
||||
TransportSettings settings;
|
||||
client->setTransportSettings(settings);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
EXPECT_CALL(*secondSock, write(_, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _));
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1615,8 +1632,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout()
|
||||
.isTimerCallbackScheduled());
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _));
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1625,13 +1642,13 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& firstAddress,
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
// Socket is paused read once during happy eyeballs
|
||||
// Socket is paused read for the second time when QuicClientTransport dies
|
||||
EXPECT_CALL(*sock, pauseRead()).Times(2);
|
||||
EXPECT_CALL(*sock, close()).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(_, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _));
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1641,8 +1658,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout()
|
||||
.isTimerCallbackScheduled());
|
||||
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _));
|
||||
EXPECT_CALL(*sock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1652,7 +1669,7 @@ class QuicClientTransportHappyEyeballsTest
|
||||
[[maybe_unused]] const SocketAddress& secondAddress) {
|
||||
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
|
||||
auto& conn = client->getConn();
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
// Socket is paused read once during happy eyeballs
|
||||
// Socket is paused read for the second time when QuicClientTransport dies
|
||||
EXPECT_CALL(*sock, pauseRead()).Times(2);
|
||||
@ -1677,8 +1694,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout()
|
||||
.isTimerCallbackScheduled());
|
||||
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _));
|
||||
EXPECT_CALL(*sock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
#endif
|
||||
@ -1689,8 +1706,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1707,17 +1724,17 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _)).Times(1);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1727,8 +1744,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1745,21 +1762,21 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
// Socket is paused read once during happy eyeballs
|
||||
// Socket is paused read for the second time when QuicClientTransport dies
|
||||
EXPECT_CALL(*sock, pauseRead()).Times(2);
|
||||
EXPECT_CALL(*sock, close()).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
|
||||
EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
|
||||
EXPECT_CALL(*sock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _)).Times(1);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1770,8 +1787,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1804,8 +1821,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
|
||||
EXPECT_CALL(*sock, write(_, _, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _)).Times(1);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
#endif
|
||||
@ -1816,8 +1833,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1834,8 +1851,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
@ -1843,8 +1860,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _)).Times(1);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1854,8 +1871,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1872,8 +1889,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
// Socket is paused read once during happy eyeballs
|
||||
// Socket is paused read for the second time when QuicClientTransport dies
|
||||
@ -1885,8 +1902,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1897,8 +1914,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1915,7 +1932,7 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
union {
|
||||
struct cmsghdr hdr;
|
||||
unsigned char buf[CMSG_SPACE(sizeof(sock_extended_err))];
|
||||
@ -1936,8 +1953,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
#endif
|
||||
@ -1948,8 +1965,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -1966,9 +1983,9 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EAGAIN, -1));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
@ -1976,8 +1993,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
|
||||
EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _)).Times(1);
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _)).Times(1);
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
}
|
||||
@ -1987,8 +2004,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
const SocketAddress& secondAddress) {
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -2005,9 +2022,9 @@ class QuicClientTransportHappyEyeballsTest
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.WillOnce(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(clientConnSetupCallback, onConnectionSetupError(_));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
@ -2023,8 +2040,8 @@ class QuicClientTransportHappyEyeballsTest
|
||||
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
|
||||
auto& conn = client->getConn();
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _));
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
client->start(&clientConnSetupCallback, &clientConnCallback);
|
||||
EXPECT_EQ(conn.peerAddress, firstAddress);
|
||||
EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
|
||||
@ -3996,11 +4013,12 @@ TEST_F(QuicClientTransportVersionAndRetryTest, RetryPacket) {
|
||||
|
||||
std::unique_ptr<IOBuf> bytesWrittenToNetwork = nullptr;
|
||||
|
||||
EXPECT_CALL(*sock, write(_, _))
|
||||
EXPECT_CALL(*sock, write(_, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
bytesWrittenToNetwork = buf->clone();
|
||||
return buf->computeChainDataLength();
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
bytesWrittenToNetwork =
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
|
||||
auto serverCid = recvServerRetry(serverAddr);
|
||||
@ -4637,7 +4655,8 @@ TEST_F(QuicClientTransportAfterStartTest, WriteThrowsExceptionWhileDraining) {
|
||||
auto err = QuicError(
|
||||
QuicErrorCode(LocalErrorCode::INTERNAL_ERROR),
|
||||
toString(LocalErrorCode::INTERNAL_ERROR).str());
|
||||
EXPECT_CALL(*sock, write(_, _)).WillRepeatedly(SetErrnoAndReturn(EBADF, -1));
|
||||
EXPECT_CALL(*sock, write(_, _, _))
|
||||
.WillRepeatedly(SetErrnoAndReturn(EBADF, -1));
|
||||
client->close(err);
|
||||
EXPECT_FALSE(client->idleTimeout().isTimerCallbackScheduled());
|
||||
}
|
||||
@ -4860,13 +4879,15 @@ TEST_F(QuicClientTransportAfterStartTest, OneCloseFramePerRtt) {
|
||||
auto streamId = client->createBidirectionalStream().value();
|
||||
auto& conn = client->getNonConstConn();
|
||||
conn.lossState.srtt = 10s;
|
||||
EXPECT_CALL(*sock, write(_, _)).WillRepeatedly(Return(100));
|
||||
EXPECT_CALL(*sock, write(_, _, _)).WillRepeatedly(Return(100));
|
||||
loopForWrites();
|
||||
Mock::VerifyAndClearExpectations(sock);
|
||||
|
||||
// Close the client transport. There could be multiple writes given how many
|
||||
// ciphers we have.
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(AtLeast(1)).WillRepeatedly(Return(10));
|
||||
EXPECT_CALL(*sock, write(_, _, _))
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Return(10));
|
||||
client->close(QuicError(
|
||||
QuicErrorCode(LocalErrorCode::INTERNAL_ERROR),
|
||||
toString(LocalErrorCode::INTERNAL_ERROR).str()));
|
||||
@ -4874,7 +4895,7 @@ TEST_F(QuicClientTransportAfterStartTest, OneCloseFramePerRtt) {
|
||||
Mock::VerifyAndClearExpectations(sock);
|
||||
|
||||
// Then received some server packet, which won't trigger another close
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*sock, write(_, _, _)).Times(0);
|
||||
auto firstData = folly::IOBuf::copyBuffer(
|
||||
"I got a room full of your posters and your pictures, man");
|
||||
deliverDataWithoutErrorCheck(packetToBuf(createStreamPacket(
|
||||
@ -4892,7 +4913,9 @@ TEST_F(QuicClientTransportAfterStartTest, OneCloseFramePerRtt) {
|
||||
conn.lastCloseSentTime = Clock::now() - 10s;
|
||||
conn.lossState.srtt = 1us;
|
||||
// Receive another server packet
|
||||
EXPECT_CALL(*sock, write(_, _)).Times(AtLeast(1)).WillRepeatedly(Return(10));
|
||||
EXPECT_CALL(*sock, write(_, _, _))
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Return(10));
|
||||
auto secondData = folly::IOBuf::copyBuffer(
|
||||
"Dear Slim, I wrote to you but you still ain't callin'");
|
||||
deliverDataWithoutErrorCheck(packetToBuf(createStreamPacket(
|
||||
@ -5424,13 +5447,14 @@ TEST_F(
|
||||
[&](const Optional<std::string>&, const Buf&) { return true; },
|
||||
[]() -> Buf { return nullptr; });
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(_, _)).Times(0);
|
||||
EXPECT_CALL(*secondSock, write(_, _, _)).Times(0);
|
||||
startClient();
|
||||
socketWrites.clear();
|
||||
auto& conn = client->getConn();
|
||||
@ -5460,20 +5484,21 @@ TEST_F(
|
||||
|
||||
// Manually expire loss timeout to trigger write to both first and second
|
||||
// socket
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
folly::IOBuf::copyBuffer(buf->data(), buf->length(), 0, 0));
|
||||
return buf->length();
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
@ -5515,11 +5540,12 @@ TEST_F(
|
||||
[&](const Optional<std::string>&, const Buf&) { return true; },
|
||||
[]() -> Buf { return nullptr; });
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
startClient();
|
||||
socketWrites.clear();
|
||||
@ -5529,12 +5555,11 @@ TEST_F(
|
||||
ASSERT_TRUE(client->happyEyeballsConnAttemptDelayTimeout()
|
||||
.isTimerCallbackScheduled());
|
||||
|
||||
EXPECT_CALL(*sock, write(firstAddress, _))
|
||||
.WillOnce(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>&) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}));
|
||||
EXPECT_CALL(*sock, write(firstAddress, _, _))
|
||||
.WillOnce(Invoke([&](const SocketAddress&, const struct iovec*, size_t) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}));
|
||||
auto streamId = client->createBidirectionalStream().value();
|
||||
client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
|
||||
loopForWrites();
|
||||
@ -5546,12 +5571,13 @@ TEST_F(
|
||||
EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout()
|
||||
.isTimerCallbackScheduled());
|
||||
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _))
|
||||
EXPECT_CALL(*secondSock, write(secondAddress, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Invoke(
|
||||
[&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
[&](const SocketAddress&, const struct iovec* vec, size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
client->lossTimeout().cancelTimerCallback();
|
||||
client->lossTimeout().timeoutExpired();
|
||||
|
@ -489,13 +489,14 @@ class QuicClientTransportTestBase : public virtual testing::Test {
|
||||
void startTransport() {
|
||||
client->addNewPeerAddress(serverAddr);
|
||||
client->setHostname(hostname_);
|
||||
ON_CALL(*sock, write(testing::_, testing::_))
|
||||
.WillByDefault(
|
||||
testing::Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
socketWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
}));
|
||||
ON_CALL(*sock, write(testing::_, testing::_, testing::_))
|
||||
.WillByDefault(testing::Invoke([&](const folly::SocketAddress&,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
socketWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
ON_CALL(*sock, address()).WillByDefault(testing::ReturnRef(serverAddr));
|
||||
|
||||
setupCryptoLayer();
|
||||
@ -575,7 +576,7 @@ class QuicClientTransportTestBase : public virtual testing::Test {
|
||||
EXPECT_CALL(*sock, setErrMessageCallback(client.get()));
|
||||
EXPECT_CALL(*sock, resumeRead(client.get()));
|
||||
EXPECT_CALL(*sock, setErrMessageCallback(nullptr));
|
||||
EXPECT_CALL(*sock, write(testing::_, testing::_))
|
||||
EXPECT_CALL(*sock, write(testing::_, testing::_, testing::_))
|
||||
.Times(testing::AtLeast(1));
|
||||
}
|
||||
|
||||
|
@ -144,13 +144,14 @@ class QuicServerTransportTestBase : public virtual testing::Test {
|
||||
std::make_unique<testing::NiceMock<quic::test::MockAsyncUDPSocket>>(
|
||||
qEvb_);
|
||||
socket = sock.get();
|
||||
EXPECT_CALL(*sock, write(testing::_, testing::_))
|
||||
.WillRepeatedly(
|
||||
testing::Invoke([&](const folly::SocketAddress&,
|
||||
const std::unique_ptr<folly::IOBuf>& buf) {
|
||||
serverWrites.push_back(buf->clone());
|
||||
return buf->computeChainDataLength();
|
||||
}));
|
||||
EXPECT_CALL(*sock, write(testing::_, testing::_, testing::_))
|
||||
.WillRepeatedly(testing::Invoke([&](const folly::SocketAddress&,
|
||||
const struct iovec* vec,
|
||||
size_t iovec_len) {
|
||||
serverWrites.push_back(
|
||||
copyChain(folly::IOBuf::wrapIov(vec, iovec_len)));
|
||||
return getTotalIovecLen(vec, iovec_len);
|
||||
}));
|
||||
EXPECT_CALL(*sock, address())
|
||||
.WillRepeatedly(testing::ReturnRef(serverAddr));
|
||||
supportedVersions = {QuicVersion::MVFST};
|
||||
|
Reference in New Issue
Block a user