mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-08 09:42:06 +03:00
Implement group streams receiver api in transport
Summary: Implement group streams receiver api in transport Reviewed By: mjoras Differential Revision: D36419901 fbshipit-source-id: 98bfefa1a4205fde8764f2e4300f51156667e024
This commit is contained in:
committed by
Facebook GitHub Bot
parent
451b519280
commit
e208ceffdd
@@ -854,12 +854,21 @@ void QuicTransportBase::invokeReadDataAndCallbacks() {
|
|||||||
peekCallbacks_.erase(streamId);
|
peekCallbacks_.erase(streamId);
|
||||||
VLOG(10) << "invoking read error callbacks on stream=" << streamId << " "
|
VLOG(10) << "invoking read error callbacks on stream=" << streamId << " "
|
||||||
<< *this;
|
<< *this;
|
||||||
|
if (!stream->groupId) {
|
||||||
readCb->readError(streamId, QuicError(*stream->streamReadError));
|
readCb->readError(streamId, QuicError(*stream->streamReadError));
|
||||||
|
} else {
|
||||||
|
readCb->readErrorWithGroup(
|
||||||
|
streamId, *stream->groupId, QuicError(*stream->streamReadError));
|
||||||
|
}
|
||||||
} else if (
|
} else if (
|
||||||
readCb && callback->second.resumed && stream->hasReadableData()) {
|
readCb && callback->second.resumed && stream->hasReadableData()) {
|
||||||
VLOG(10) << "invoking read callbacks on stream=" << streamId << " "
|
VLOG(10) << "invoking read callbacks on stream=" << streamId << " "
|
||||||
<< *this;
|
<< *this;
|
||||||
|
if (!stream->groupId) {
|
||||||
readCb->readAvailable(streamId);
|
readCb->readAvailable(streamId);
|
||||||
|
} else {
|
||||||
|
readCb->readAvailableWithGroup(streamId, *stream->groupId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self->datagramCallback_ && !conn_->datagramState.readBuffer.empty()) {
|
if (self->datagramCallback_ && !conn_->datagramState.readBuffer.empty()) {
|
||||||
@@ -1538,11 +1547,24 @@ void QuicTransportBase::handleCancelByteEventCallbacks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuicTransportBase::handleNewStreamCallbacks(
|
void QuicTransportBase::logStreamOpenEvent(StreamId streamId) {
|
||||||
std::vector<StreamId>& streamStorage) {
|
if (getSocketObserverContainer() &&
|
||||||
streamStorage =
|
getSocketObserverContainer()
|
||||||
conn_->streamManager->consumeNewPeerStreams(std::move(streamStorage));
|
->hasObserversForEvent<
|
||||||
|
SocketObserverInterface::Events::streamEvents>()) {
|
||||||
|
getSocketObserverContainer()
|
||||||
|
->invokeInterfaceMethod<SocketObserverInterface::Events::streamEvents>(
|
||||||
|
[event = SocketObserverInterface::StreamOpenEvent(
|
||||||
|
streamId,
|
||||||
|
getStreamInitiator(streamId),
|
||||||
|
getStreamDirectionality(streamId))](
|
||||||
|
auto observer, auto observed) {
|
||||||
|
observer->streamOpened(observed, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuicTransportBase::handleNewStreams(std::vector<StreamId>& streamStorage) {
|
||||||
const auto& newPeerStreamIds = streamStorage;
|
const auto& newPeerStreamIds = streamStorage;
|
||||||
for (const auto& streamId : newPeerStreamIds) {
|
for (const auto& streamId : newPeerStreamIds) {
|
||||||
CHECK_NOTNULL(connCallback_);
|
CHECK_NOTNULL(connCallback_);
|
||||||
@@ -1552,30 +1574,60 @@ void QuicTransportBase::handleNewStreamCallbacks(
|
|||||||
connCallback_->onNewUnidirectionalStream(streamId);
|
connCallback_->onNewUnidirectionalStream(streamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSocketObserverContainer() &&
|
logStreamOpenEvent(streamId);
|
||||||
getSocketObserverContainer()
|
|
||||||
->hasObserversForEvent<
|
|
||||||
SocketObserverInterface::Events::streamEvents>()) {
|
|
||||||
getSocketObserverContainer()
|
|
||||||
->invokeInterfaceMethod<
|
|
||||||
SocketObserverInterface::Events::streamEvents>(
|
|
||||||
[event = SocketObserverInterface::StreamOpenEvent(
|
|
||||||
streamId,
|
|
||||||
getStreamInitiator(streamId),
|
|
||||||
getStreamDirectionality(streamId))](
|
|
||||||
auto observer, auto observed) {
|
|
||||||
observer->streamOpened(observed, event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closeState_ != CloseState::OPEN) {
|
if (closeState_ != CloseState::OPEN) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
streamStorage.clear();
|
streamStorage.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuicTransportBase::handleNewGroupedStreams(
|
||||||
|
std::vector<StreamId>& streamStorage) {
|
||||||
|
const auto& newPeerStreamIds = streamStorage;
|
||||||
|
for (const auto& streamId : newPeerStreamIds) {
|
||||||
|
CHECK_NOTNULL(connCallback_);
|
||||||
|
auto stream = conn_->streamManager->getStream(streamId);
|
||||||
|
CHECK(stream->groupId);
|
||||||
|
if (isBidirectionalStream(streamId)) {
|
||||||
|
connCallback_->onNewBidirectionalStreamInGroup(
|
||||||
|
streamId, *stream->groupId);
|
||||||
|
} else {
|
||||||
|
connCallback_->onNewUnidirectionalStreamInGroup(
|
||||||
|
streamId, *stream->groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
logStreamOpenEvent(streamId);
|
||||||
|
if (closeState_ != CloseState::OPEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
streamStorage.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuicTransportBase::handleNewStreamCallbacks(
|
||||||
|
std::vector<StreamId>& streamStorage) {
|
||||||
|
streamStorage =
|
||||||
|
conn_->streamManager->consumeNewPeerStreams(std::move(streamStorage));
|
||||||
|
handleNewStreams(streamStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuicTransportBase::handleNewGroupedStreamCallbacks(
|
||||||
|
std::vector<StreamId>& streamStorage) {
|
||||||
|
auto newStreamGroups = conn_->streamManager->consumeNewPeerStreamGroups();
|
||||||
|
for (auto newStreamGroupId : newStreamGroups) {
|
||||||
|
if (isBidirectionalStream(newStreamGroupId)) {
|
||||||
|
connCallback_->onNewBidirectionalStreamGroup(newStreamGroupId);
|
||||||
|
} else {
|
||||||
|
connCallback_->onNewUnidirectionalStreamGroup(newStreamGroupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
streamStorage = conn_->streamManager->consumeNewGroupedPeerStreams(
|
||||||
|
std::move(streamStorage));
|
||||||
|
handleNewGroupedStreams(streamStorage);
|
||||||
|
}
|
||||||
|
|
||||||
void QuicTransportBase::handleDeliveryCallbacks() {
|
void QuicTransportBase::handleDeliveryCallbacks() {
|
||||||
auto deliverableStreamId = conn_->streamManager->popDeliverable();
|
auto deliverableStreamId = conn_->streamManager->popDeliverable();
|
||||||
while (deliverableStreamId.has_value()) {
|
while (deliverableStreamId.has_value()) {
|
||||||
@@ -1722,6 +1774,11 @@ void QuicTransportBase::processCallbacksAfterNetworkData() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNewGroupedStreamCallbacks(tempStorage);
|
||||||
|
if (closeState_ != CloseState::OPEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
handlePingCallbacks();
|
handlePingCallbacks();
|
||||||
if (closeState_ != CloseState::OPEN) {
|
if (closeState_ != CloseState::OPEN) {
|
||||||
return;
|
return;
|
||||||
@@ -2845,7 +2902,12 @@ void QuicTransportBase::cancelAllAppCallbacks(const QuicError& err) noexcept {
|
|||||||
for (auto& cb : readCallbacksCopy) {
|
for (auto& cb : readCallbacksCopy) {
|
||||||
readCallbacks_.erase(cb.first);
|
readCallbacks_.erase(cb.first);
|
||||||
if (cb.second.readCb) {
|
if (cb.second.readCb) {
|
||||||
|
auto stream = conn_->streamManager->getStream(cb.first);
|
||||||
|
if (!stream->groupId) {
|
||||||
cb.second.readCb->readError(cb.first, err);
|
cb.second.readCb->readError(cb.first, err);
|
||||||
|
} else {
|
||||||
|
cb.second.readCb->readErrorWithGroup(cb.first, *stream->groupId, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2901,8 +2963,14 @@ void QuicTransportBase::resetNonControlStreams(
|
|||||||
auto readCallbackIt = readCallbacks_.find(id);
|
auto readCallbackIt = readCallbacks_.find(id);
|
||||||
if (readCallbackIt != readCallbacks_.end() &&
|
if (readCallbackIt != readCallbacks_.end() &&
|
||||||
readCallbackIt->second.readCb) {
|
readCallbackIt->second.readCb) {
|
||||||
|
auto stream = conn_->streamManager->getStream(id);
|
||||||
|
if (!stream->groupId) {
|
||||||
readCallbackIt->second.readCb->readError(
|
readCallbackIt->second.readCb->readError(
|
||||||
id, QuicError(error, errorMsg.str()));
|
id, QuicError(error, errorMsg.str()));
|
||||||
|
} else {
|
||||||
|
readCallbackIt->second.readCb->readErrorWithGroup(
|
||||||
|
id, *stream->groupId, QuicError(error, errorMsg.str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
peekCallbacks_.erase(id);
|
peekCallbacks_.erase(id);
|
||||||
stopSending(id, error);
|
stopSending(id, error);
|
||||||
|
@@ -709,6 +709,7 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver {
|
|||||||
void handleAckEventCallbacks();
|
void handleAckEventCallbacks();
|
||||||
void handleCancelByteEventCallbacks();
|
void handleCancelByteEventCallbacks();
|
||||||
void handleNewStreamCallbacks(std::vector<StreamId>& newPeerStreams);
|
void handleNewStreamCallbacks(std::vector<StreamId>& newPeerStreams);
|
||||||
|
void handleNewGroupedStreamCallbacks(std::vector<StreamId>& newPeerStreams);
|
||||||
void handleDeliveryCallbacks();
|
void handleDeliveryCallbacks();
|
||||||
void handleStreamFlowControlUpdatedCallbacks(
|
void handleStreamFlowControlUpdatedCallbacks(
|
||||||
std::vector<StreamId>& streamStorage);
|
std::vector<StreamId>& streamStorage);
|
||||||
@@ -933,6 +934,18 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver {
|
|||||||
// (value >= threshold), the connection is considered to be in backround mode.
|
// (value >= threshold), the connection is considered to be in backround mode.
|
||||||
folly::Optional<PriorityLevel> backgroundPriorityThreshold_;
|
folly::Optional<PriorityLevel> backgroundPriorityThreshold_;
|
||||||
folly::Optional<float> backgroundUtilizationFactor_;
|
folly::Optional<float> backgroundUtilizationFactor_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Helper funtions to handle new streams.
|
||||||
|
*/
|
||||||
|
void handleNewStreams(std::vector<StreamId>& newPeerStreams);
|
||||||
|
void handleNewGroupedStreams(std::vector<StreamId>& newPeerStreams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to log new stream event to observer.
|
||||||
|
*/
|
||||||
|
void logStreamOpenEvent(StreamId streamId);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const QuicTransportBase& qt);
|
std::ostream& operator<<(std::ostream& os, const QuicTransportBase& qt);
|
||||||
|
@@ -46,7 +46,17 @@ class MockReadCallback : public QuicSocket::ReadCallback {
|
|||||||
public:
|
public:
|
||||||
~MockReadCallback() override = default;
|
~MockReadCallback() override = default;
|
||||||
MOCK_METHOD((void), readAvailable, (StreamId), (noexcept));
|
MOCK_METHOD((void), readAvailable, (StreamId), (noexcept));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(void),
|
||||||
|
readAvailableWithGroup,
|
||||||
|
(StreamId, StreamGroupId),
|
||||||
|
(noexcept));
|
||||||
MOCK_METHOD((void), readError, (StreamId, QuicError), (noexcept));
|
MOCK_METHOD((void), readError, (StreamId, QuicError), (noexcept));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(void),
|
||||||
|
readErrorWithGroup,
|
||||||
|
(StreamId, StreamGroupId, QuicError),
|
||||||
|
(noexcept));
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockPeekCallback : public QuicSocket::PeekCallback {
|
class MockPeekCallback : public QuicSocket::PeekCallback {
|
||||||
@@ -91,7 +101,27 @@ class MockConnectionCallback : public QuicSocket::ConnectionCallback {
|
|||||||
|
|
||||||
MOCK_METHOD((void), onFlowControlUpdate, (StreamId), (noexcept));
|
MOCK_METHOD((void), onFlowControlUpdate, (StreamId), (noexcept));
|
||||||
MOCK_METHOD((void), onNewBidirectionalStream, (StreamId), (noexcept));
|
MOCK_METHOD((void), onNewBidirectionalStream, (StreamId), (noexcept));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(void),
|
||||||
|
onNewBidirectionalStreamGroup,
|
||||||
|
(StreamGroupId),
|
||||||
|
(noexcept));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(void),
|
||||||
|
onNewBidirectionalStreamInGroup,
|
||||||
|
(StreamId, StreamGroupId),
|
||||||
|
(noexcept));
|
||||||
MOCK_METHOD((void), onNewUnidirectionalStream, (StreamId), (noexcept));
|
MOCK_METHOD((void), onNewUnidirectionalStream, (StreamId), (noexcept));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(void),
|
||||||
|
onNewUnidirectionalStreamGroup,
|
||||||
|
(StreamGroupId),
|
||||||
|
(noexcept));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(void),
|
||||||
|
onNewUnidirectionalStreamInGroup,
|
||||||
|
(StreamId, StreamGroupId),
|
||||||
|
(noexcept));
|
||||||
MOCK_METHOD(
|
MOCK_METHOD(
|
||||||
(void),
|
(void),
|
||||||
onStopSending,
|
onStopSending,
|
||||||
|
@@ -39,15 +39,26 @@ enum class TestFrameType : uint8_t {
|
|||||||
EXPIRED_DATA,
|
EXPIRED_DATA,
|
||||||
REJECTED_DATA,
|
REJECTED_DATA,
|
||||||
MAX_STREAMS,
|
MAX_STREAMS,
|
||||||
DATAGRAM
|
DATAGRAM,
|
||||||
|
STREAM_GROUP
|
||||||
};
|
};
|
||||||
|
|
||||||
// A made up encoding decoding of a stream.
|
// A made up encoding decoding of a stream.
|
||||||
Buf encodeStreamBuffer(StreamId id, StreamBuffer data) {
|
Buf encodeStreamBuffer(
|
||||||
|
StreamId id,
|
||||||
|
StreamBuffer data,
|
||||||
|
folly::Optional<StreamGroupId> groupId = folly::none) {
|
||||||
auto buf = IOBuf::create(10);
|
auto buf = IOBuf::create(10);
|
||||||
folly::io::Appender appender(buf.get(), 10);
|
folly::io::Appender appender(buf.get(), 10);
|
||||||
|
if (!groupId) {
|
||||||
appender.writeBE(static_cast<uint8_t>(TestFrameType::STREAM));
|
appender.writeBE(static_cast<uint8_t>(TestFrameType::STREAM));
|
||||||
|
} else {
|
||||||
|
appender.writeBE(static_cast<uint8_t>(TestFrameType::STREAM_GROUP));
|
||||||
|
}
|
||||||
appender.writeBE(id);
|
appender.writeBE(id);
|
||||||
|
if (groupId) {
|
||||||
|
appender.writeBE(*groupId);
|
||||||
|
}
|
||||||
auto dataBuf = data.data.move();
|
auto dataBuf = data.data.move();
|
||||||
dataBuf->coalesce();
|
dataBuf->coalesce();
|
||||||
appender.writeBE<uint32_t>(dataBuf->length());
|
appender.writeBE<uint32_t>(dataBuf->length());
|
||||||
@@ -116,6 +127,23 @@ std::pair<StreamId, StreamBuffer> decodeStreamBuffer(
|
|||||||
StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, eof));
|
StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, eof));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StreamGroupIdBuf {
|
||||||
|
StreamId id;
|
||||||
|
StreamGroupId groupId;
|
||||||
|
StreamBuffer buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamGroupIdBuf decodeStreamGroupBuffer(folly::io::Cursor& cursor) {
|
||||||
|
auto streamId = cursor.readBE<StreamId>();
|
||||||
|
auto groupId = cursor.readBE<StreamGroupId>();
|
||||||
|
auto dataBuffer = decodeDataBuffer(cursor);
|
||||||
|
bool eof = (bool)cursor.readBE<uint8_t>();
|
||||||
|
return StreamGroupIdBuf{
|
||||||
|
streamId,
|
||||||
|
groupId,
|
||||||
|
StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, eof)};
|
||||||
|
}
|
||||||
|
|
||||||
StreamBuffer decodeCryptoBuffer(folly::io::Cursor& cursor) {
|
StreamBuffer decodeCryptoBuffer(folly::io::Cursor& cursor) {
|
||||||
auto dataBuffer = decodeDataBuffer(cursor);
|
auto dataBuffer = decodeDataBuffer(cursor);
|
||||||
return StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, false);
|
return StreamBuffer(std::move(dataBuffer.first), dataBuffer.second, false);
|
||||||
@@ -258,6 +286,16 @@ class TestQuicTransport
|
|||||||
auto buffer = decodeDatagramFrame(cursor);
|
auto buffer = decodeDatagramFrame(cursor);
|
||||||
auto frame = DatagramFrame(buffer.second, std::move(buffer.first));
|
auto frame = DatagramFrame(buffer.second, std::move(buffer.first));
|
||||||
handleDatagram(*conn_, frame, data.receiveTimePoint);
|
handleDatagram(*conn_, frame, data.receiveTimePoint);
|
||||||
|
} else if (type == TestFrameType::STREAM_GROUP) {
|
||||||
|
auto res = decodeStreamGroupBuffer(cursor);
|
||||||
|
QuicStreamState* stream =
|
||||||
|
conn_->streamManager->getStream(res.id, res.groupId);
|
||||||
|
if (!stream) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
appendDataToReadBuffer(*stream, std::move(res.buf));
|
||||||
|
conn_->streamManager->updateReadableStreams(*stream);
|
||||||
|
conn_->streamManager->updatePeekableStreams(*stream);
|
||||||
} else {
|
} else {
|
||||||
auto buffer = decodeStreamBuffer(cursor);
|
auto buffer = decodeStreamBuffer(cursor);
|
||||||
QuicStreamState* stream = conn_->streamManager->getStream(buffer.first);
|
QuicStreamState* stream = conn_->streamManager->getStream(buffer.first);
|
||||||
@@ -346,8 +384,11 @@ class TestQuicTransport
|
|||||||
|
|
||||||
void onReadError(const folly::AsyncSocketException&) noexcept {}
|
void onReadError(const folly::AsyncSocketException&) noexcept {}
|
||||||
|
|
||||||
void addDataToStream(StreamId id, StreamBuffer data) {
|
void addDataToStream(
|
||||||
auto buf = encodeStreamBuffer(id, std::move(data));
|
StreamId id,
|
||||||
|
StreamBuffer data,
|
||||||
|
folly::Optional<StreamGroupId> groupId = folly::none) {
|
||||||
|
auto buf = encodeStreamBuffer(id, std::move(data), std::move(groupId));
|
||||||
SocketAddress addr("127.0.0.1", 1000);
|
SocketAddress addr("127.0.0.1", 1000);
|
||||||
onNetworkData(addr, NetworkData(std::move(buf), Clock::now()));
|
onNetworkData(addr, NetworkData(std::move(buf), Clock::now()));
|
||||||
}
|
}
|
||||||
@@ -4038,5 +4079,160 @@ TEST_P(QuicTransportImplTestBase, BackgroundModeChangeWithStreamChanges) {
|
|||||||
manager.removeClosedStream(stream2Id);
|
manager.removeClosedStream(stream2Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QuicTransportImplTestWithGroups : public QuicTransportImplTestBase {};
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
QuicTransportImplTestWithGroups,
|
||||||
|
QuicTransportImplTestWithGroups,
|
||||||
|
::testing::Values(DelayedStreamNotifsTestParam{
|
||||||
|
.notifyOnNewStreamsExplicitly = true}));
|
||||||
|
|
||||||
|
TEST_P(QuicTransportImplTestWithGroups, ReadCallbackWithGroupsDataAvailable) {
|
||||||
|
auto transportSettings = transport->getTransportSettings();
|
||||||
|
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||||
|
transport->setTransportSettings(transportSettings);
|
||||||
|
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||||
|
transportSettings);
|
||||||
|
|
||||||
|
auto groupId = transport->createBidirectionalStreamGroup();
|
||||||
|
EXPECT_TRUE(groupId.hasValue());
|
||||||
|
auto stream1 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||||
|
auto stream2 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||||
|
|
||||||
|
NiceMock<MockReadCallback> readCb1;
|
||||||
|
NiceMock<MockReadCallback> readCb2;
|
||||||
|
|
||||||
|
transport->setReadCallback(stream1, &readCb1);
|
||||||
|
transport->setReadCallback(stream2, &readCb2);
|
||||||
|
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream1,
|
||||||
|
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||||
|
*groupId);
|
||||||
|
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream2,
|
||||||
|
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 10),
|
||||||
|
*groupId);
|
||||||
|
|
||||||
|
EXPECT_CALL(readCb1, readAvailableWithGroup(stream1, *groupId));
|
||||||
|
transport->driveReadCallbacks();
|
||||||
|
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream2,
|
||||||
|
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||||
|
*groupId);
|
||||||
|
|
||||||
|
EXPECT_CALL(readCb1, readAvailableWithGroup(stream1, *groupId));
|
||||||
|
EXPECT_CALL(readCb2, readAvailableWithGroup(stream2, *groupId));
|
||||||
|
transport->driveReadCallbacks();
|
||||||
|
|
||||||
|
EXPECT_CALL(readCb1, readAvailableWithGroup(stream1, *groupId));
|
||||||
|
EXPECT_CALL(readCb2, readAvailableWithGroup(stream2, *groupId));
|
||||||
|
transport->driveReadCallbacks();
|
||||||
|
|
||||||
|
EXPECT_CALL(readCb2, readAvailableWithGroup(stream2, *groupId));
|
||||||
|
transport->setReadCallback(stream1, nullptr);
|
||||||
|
transport->driveReadCallbacks();
|
||||||
|
transport.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(QuicTransportImplTestWithGroups, ReadErrorCallbackWithGroups) {
|
||||||
|
auto transportSettings = transport->getTransportSettings();
|
||||||
|
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||||
|
transport->setTransportSettings(transportSettings);
|
||||||
|
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||||
|
transportSettings);
|
||||||
|
|
||||||
|
auto groupId = transport->createBidirectionalStreamGroup();
|
||||||
|
EXPECT_TRUE(groupId.hasValue());
|
||||||
|
auto stream1 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||||
|
|
||||||
|
NiceMock<MockReadCallback> readCb1;
|
||||||
|
|
||||||
|
transport->setReadCallback(stream1, &readCb1);
|
||||||
|
|
||||||
|
transport->addStreamReadError(stream1, LocalErrorCode::NO_ERROR);
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream1,
|
||||||
|
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||||
|
*groupId);
|
||||||
|
|
||||||
|
EXPECT_CALL(readCb1, readErrorWithGroup(stream1, *groupId, _));
|
||||||
|
transport->driveReadCallbacks();
|
||||||
|
|
||||||
|
transport.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(
|
||||||
|
QuicTransportImplTestWithGroups,
|
||||||
|
ReadCallbackWithGroupsCancellCallbacks) {
|
||||||
|
auto transportSettings = transport->getTransportSettings();
|
||||||
|
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||||
|
transport->setTransportSettings(transportSettings);
|
||||||
|
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||||
|
transportSettings);
|
||||||
|
|
||||||
|
auto groupId = transport->createBidirectionalStreamGroup();
|
||||||
|
EXPECT_TRUE(groupId.hasValue());
|
||||||
|
auto stream1 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||||
|
auto stream2 = transport->createBidirectionalStreamInGroup(*groupId).value();
|
||||||
|
|
||||||
|
NiceMock<MockReadCallback> readCb1;
|
||||||
|
NiceMock<MockReadCallback> readCb2;
|
||||||
|
|
||||||
|
transport->setReadCallback(stream1, &readCb1);
|
||||||
|
transport->setReadCallback(stream2, &readCb2);
|
||||||
|
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream1,
|
||||||
|
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 0),
|
||||||
|
*groupId);
|
||||||
|
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream2,
|
||||||
|
StreamBuffer(folly::IOBuf::copyBuffer("actual stream data"), 10),
|
||||||
|
*groupId);
|
||||||
|
|
||||||
|
EXPECT_CALL(readCb1, readErrorWithGroup(stream1, *groupId, _));
|
||||||
|
EXPECT_CALL(readCb2, readErrorWithGroup(stream2, *groupId, _));
|
||||||
|
QuicError error =
|
||||||
|
QuicError(TransportErrorCode::PROTOCOL_VIOLATION, "test error");
|
||||||
|
transport->cancelAllAppCallbacks(error);
|
||||||
|
transport.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(QuicTransportImplTestWithGroups, onNewStreamsAndGroupsCallbacks) {
|
||||||
|
auto transportSettings = transport->getTransportSettings();
|
||||||
|
transportSettings.maxStreamGroupsAdvertized = 16;
|
||||||
|
transport->setTransportSettings(transportSettings);
|
||||||
|
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||||
|
transportSettings);
|
||||||
|
|
||||||
|
auto readData = folly::IOBuf::copyBuffer("actual stream data");
|
||||||
|
|
||||||
|
StreamGroupId groupId = 0x00;
|
||||||
|
StreamId stream1 = 0x00;
|
||||||
|
EXPECT_CALL(connCallback, onNewBidirectionalStreamGroup(groupId));
|
||||||
|
EXPECT_CALL(connCallback, onNewBidirectionalStreamInGroup(stream1, groupId));
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream1, StreamBuffer(readData->clone(), 0, true), groupId);
|
||||||
|
|
||||||
|
StreamId stream2 = 0x04;
|
||||||
|
EXPECT_CALL(connCallback, onNewBidirectionalStreamInGroup(stream2, groupId));
|
||||||
|
transport->addDataToStream(
|
||||||
|
stream2, StreamBuffer(readData->clone(), 0, true), groupId);
|
||||||
|
|
||||||
|
StreamGroupId groupIdUni = 0x02;
|
||||||
|
StreamId uniStream3 = 0xa;
|
||||||
|
EXPECT_CALL(connCallback, onNewUnidirectionalStreamGroup(groupIdUni));
|
||||||
|
EXPECT_CALL(
|
||||||
|
connCallback, onNewUnidirectionalStreamInGroup(uniStream3, groupIdUni));
|
||||||
|
transport->addDataToStream(
|
||||||
|
uniStream3, StreamBuffer(readData->clone(), 0, true), groupIdUni);
|
||||||
|
|
||||||
|
transport.reset();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
@@ -494,7 +494,8 @@ void QuicClientTransport::processPacketData(
|
|||||||
<< " len=" << frame.data->computeChainDataLength()
|
<< " len=" << frame.data->computeChainDataLength()
|
||||||
<< " fin=" << frame.fin << " packetNum=" << packetNum << " "
|
<< " fin=" << frame.fin << " packetNum=" << packetNum << " "
|
||||||
<< *this;
|
<< *this;
|
||||||
auto stream = conn_->streamManager->getStream(frame.streamId);
|
auto stream = conn_->streamManager->getStream(
|
||||||
|
frame.streamId, frame.streamGroupId);
|
||||||
pktHasRetransmittableData = true;
|
pktHasRetransmittableData = true;
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
VLOG(10) << "Could not find stream=" << frame.streamId << " "
|
VLOG(10) << "Could not find stream=" << frame.streamId << " "
|
||||||
|
@@ -1083,7 +1083,8 @@ void onServerReadDataFromOpen(
|
|||||||
<< " fin=" << frame.fin << " " << conn;
|
<< " fin=" << frame.fin << " " << conn;
|
||||||
pktHasRetransmittableData = true;
|
pktHasRetransmittableData = true;
|
||||||
isNonProbingPacket = true;
|
isNonProbingPacket = true;
|
||||||
auto stream = conn.streamManager->getStream(frame.streamId);
|
auto stream = conn.streamManager->getStream(
|
||||||
|
frame.streamId, frame.streamGroupId);
|
||||||
// Ignore data from closed streams that we don't have the
|
// Ignore data from closed streams that we don't have the
|
||||||
// state for any more.
|
// state for any more.
|
||||||
if (stream) {
|
if (stream) {
|
||||||
|
Reference in New Issue
Block a user