Add SendMany method to dcsctp socket
Bug: webrtc:15724 Change-Id: Ib1689cd46395e2315803714ef50c009580fd71bb Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/331021 Reviewed-by: Victor Boivie <boivie@webrtc.org> Commit-Queue: Victor Boivie <boivie@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41397}
This commit is contained in:
parent
0f86cd126b
commit
c9d44b3fb9
@ -13,6 +13,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
@ -577,6 +578,16 @@ class DcSctpSocketInterface {
|
|||||||
virtual SendStatus Send(DcSctpMessage message,
|
virtual SendStatus Send(DcSctpMessage message,
|
||||||
const SendOptions& send_options) = 0;
|
const SendOptions& send_options) = 0;
|
||||||
|
|
||||||
|
// Sends the messages `messages` using the provided send options.
|
||||||
|
// Sending a message is an asynchronous operation, and the `OnError` callback
|
||||||
|
// may be invoked to indicate any errors in sending the message.
|
||||||
|
//
|
||||||
|
// This has identical semantics to Send, except that it may coalesce many
|
||||||
|
// messages into a single SCTP packet if they would fit.
|
||||||
|
virtual std::vector<SendStatus> SendMany(
|
||||||
|
rtc::ArrayView<DcSctpMessage> messages,
|
||||||
|
const SendOptions& send_options) = 0;
|
||||||
|
|
||||||
// Resetting streams is an asynchronous operation and the results will
|
// Resetting streams is an asynchronous operation and the results will
|
||||||
// be notified using `DcSctpSocketCallbacks::OnStreamsResetDone()` on success
|
// be notified using `DcSctpSocketCallbacks::OnStreamsResetDone()` on success
|
||||||
// and `DcSctpSocketCallbacks::OnStreamsResetFailed()` on failure. Note that
|
// and `DcSctpSocketCallbacks::OnStreamsResetFailed()` on failure. Note that
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
#ifndef NET_DCSCTP_PUBLIC_MOCK_DCSCTP_SOCKET_H_
|
#ifndef NET_DCSCTP_PUBLIC_MOCK_DCSCTP_SOCKET_H_
|
||||||
#define NET_DCSCTP_PUBLIC_MOCK_DCSCTP_SOCKET_H_
|
#define NET_DCSCTP_PUBLIC_MOCK_DCSCTP_SOCKET_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "net/dcsctp/public/dcsctp_socket.h"
|
#include "net/dcsctp/public/dcsctp_socket.h"
|
||||||
#include "test/gmock.h"
|
#include "test/gmock.h"
|
||||||
|
|
||||||
@ -56,6 +58,12 @@ class MockDcSctpSocket : public DcSctpSocketInterface {
|
|||||||
(DcSctpMessage message, const SendOptions& send_options),
|
(DcSctpMessage message, const SendOptions& send_options),
|
||||||
(override));
|
(override));
|
||||||
|
|
||||||
|
MOCK_METHOD(std::vector<SendStatus>,
|
||||||
|
SendMany,
|
||||||
|
(rtc::ArrayView<DcSctpMessage> messages,
|
||||||
|
const SendOptions& send_options),
|
||||||
|
(override));
|
||||||
|
|
||||||
MOCK_METHOD(ResetStreamsStatus,
|
MOCK_METHOD(ResetStreamsStatus,
|
||||||
ResetStreams,
|
ResetStreams,
|
||||||
(rtc::ArrayView<const StreamID> outgoing_streams),
|
(rtc::ArrayView<const StreamID> outgoing_streams),
|
||||||
|
|||||||
@ -475,8 +475,43 @@ SendStatus DcSctpSocket::Send(DcSctpMessage message,
|
|||||||
const SendOptions& send_options) {
|
const SendOptions& send_options) {
|
||||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||||
CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
|
CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
|
||||||
LifecycleId lifecycle_id = send_options.lifecycle_id;
|
SendStatus send_status = InternalSend(message, send_options);
|
||||||
|
if (send_status != SendStatus::kSuccess)
|
||||||
|
return send_status;
|
||||||
|
Timestamp now = callbacks_.Now();
|
||||||
|
++metrics_.tx_messages_count;
|
||||||
|
send_queue_.Add(now, std::move(message), send_options);
|
||||||
|
if (tcb_ != nullptr)
|
||||||
|
tcb_->SendBufferedPackets(now);
|
||||||
|
RTC_DCHECK(IsConsistent());
|
||||||
|
return SendStatus::kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SendStatus> DcSctpSocket::SendMany(
|
||||||
|
rtc::ArrayView<DcSctpMessage> messages,
|
||||||
|
const SendOptions& send_options) {
|
||||||
|
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||||
|
CallbackDeferrer::ScopedDeferrer deferrer(callbacks_);
|
||||||
|
Timestamp now = callbacks_.Now();
|
||||||
|
std::vector<SendStatus> send_statuses;
|
||||||
|
send_statuses.reserve(messages.size());
|
||||||
|
for (DcSctpMessage& message : messages) {
|
||||||
|
SendStatus send_status = InternalSend(message, send_options);
|
||||||
|
send_statuses.push_back(send_status);
|
||||||
|
if (send_status != SendStatus::kSuccess)
|
||||||
|
continue;
|
||||||
|
++metrics_.tx_messages_count;
|
||||||
|
send_queue_.Add(now, std::move(message), send_options);
|
||||||
|
}
|
||||||
|
if (tcb_ != nullptr)
|
||||||
|
tcb_->SendBufferedPackets(now);
|
||||||
|
RTC_DCHECK(IsConsistent());
|
||||||
|
return send_statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendStatus DcSctpSocket::InternalSend(const DcSctpMessage& message,
|
||||||
|
const SendOptions& send_options) {
|
||||||
|
LifecycleId lifecycle_id = send_options.lifecycle_id;
|
||||||
if (message.payload().empty()) {
|
if (message.payload().empty()) {
|
||||||
if (lifecycle_id.IsSet()) {
|
if (lifecycle_id.IsSet()) {
|
||||||
callbacks_.OnLifecycleEnd(lifecycle_id);
|
callbacks_.OnLifecycleEnd(lifecycle_id);
|
||||||
@ -514,15 +549,6 @@ SendStatus DcSctpSocket::Send(DcSctpMessage message,
|
|||||||
"Unable to send message as the send queue is full");
|
"Unable to send message as the send queue is full");
|
||||||
return SendStatus::kErrorResourceExhaustion;
|
return SendStatus::kErrorResourceExhaustion;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestamp now = callbacks_.Now();
|
|
||||||
++metrics_.tx_messages_count;
|
|
||||||
send_queue_.Add(now, std::move(message), send_options);
|
|
||||||
if (tcb_ != nullptr) {
|
|
||||||
tcb_->SendBufferedPackets(now);
|
|
||||||
}
|
|
||||||
|
|
||||||
RTC_DCHECK(IsConsistent());
|
|
||||||
return SendStatus::kSuccess;
|
return SendStatus::kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
#include "api/array_view.h"
|
#include "api/array_view.h"
|
||||||
@ -91,6 +92,8 @@ class DcSctpSocket : public DcSctpSocketInterface {
|
|||||||
void Close() override;
|
void Close() override;
|
||||||
SendStatus Send(DcSctpMessage message,
|
SendStatus Send(DcSctpMessage message,
|
||||||
const SendOptions& send_options) override;
|
const SendOptions& send_options) override;
|
||||||
|
std::vector<SendStatus> SendMany(rtc::ArrayView<DcSctpMessage> messages,
|
||||||
|
const SendOptions& send_options) override;
|
||||||
ResetStreamsStatus ResetStreams(
|
ResetStreamsStatus ResetStreams(
|
||||||
rtc::ArrayView<const StreamID> outgoing_streams) override;
|
rtc::ArrayView<const StreamID> outgoing_streams) override;
|
||||||
SocketState state() const override;
|
SocketState state() const override;
|
||||||
@ -165,6 +168,9 @@ class DcSctpSocket : public DcSctpSocketInterface {
|
|||||||
void MaybeSendShutdownOnPacketReceived(const SctpPacket& packet);
|
void MaybeSendShutdownOnPacketReceived(const SctpPacket& packet);
|
||||||
// If there are streams pending to be reset, send a request to reset them.
|
// If there are streams pending to be reset, send a request to reset them.
|
||||||
void MaybeSendResetStreamsRequest();
|
void MaybeSendResetStreamsRequest();
|
||||||
|
// Performs internal processing shared between Send and SendMany.
|
||||||
|
SendStatus InternalSend(const DcSctpMessage& message,
|
||||||
|
const SendOptions& send_options);
|
||||||
// Sends a INIT chunk.
|
// Sends a INIT chunk.
|
||||||
void SendInit();
|
void SendInit();
|
||||||
// Sends a SHUTDOWN chunk.
|
// Sends a SHUTDOWN chunk.
|
||||||
|
|||||||
@ -66,6 +66,7 @@ namespace {
|
|||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
using ::testing::AllOf;
|
using ::testing::AllOf;
|
||||||
using ::testing::ElementsAre;
|
using ::testing::ElementsAre;
|
||||||
|
using ::testing::ElementsAreArray;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::IsEmpty;
|
using ::testing::IsEmpty;
|
||||||
@ -1561,6 +1562,33 @@ TEST(DcSctpSocketTest, SetMaxMessageSize) {
|
|||||||
EXPECT_EQ(a.socket.options().max_message_size, 42u);
|
EXPECT_EQ(a.socket.options().max_message_size, 42u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(DcSctpSocketParametrizedTest, SendManyMessages) {
|
||||||
|
SocketUnderTest a("A");
|
||||||
|
auto z = std::make_unique<SocketUnderTest>("Z");
|
||||||
|
|
||||||
|
ConnectSockets(a, *z);
|
||||||
|
z = MaybeHandoverSocket(std::move(z));
|
||||||
|
|
||||||
|
static constexpr int kIterations = 100;
|
||||||
|
std::vector<DcSctpMessage> messages;
|
||||||
|
std::vector<SendStatus> statuses;
|
||||||
|
for (int i = 0; i < kIterations; ++i) {
|
||||||
|
messages.push_back(DcSctpMessage(StreamID(1), PPID(53), {1, 2}));
|
||||||
|
statuses.push_back(SendStatus::kSuccess);
|
||||||
|
}
|
||||||
|
EXPECT_THAT(a.socket.SendMany(messages, {}), ElementsAreArray(statuses));
|
||||||
|
|
||||||
|
ExchangeMessages(a, *z);
|
||||||
|
|
||||||
|
for (int i = 0; i < kIterations; ++i) {
|
||||||
|
EXPECT_TRUE(z->cb.ConsumeReceivedMessage().has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_FALSE(z->cb.ConsumeReceivedMessage().has_value());
|
||||||
|
|
||||||
|
MaybeHandoverSocketAndSendMessage(a, std::move(z));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(DcSctpSocketParametrizedTest, SendsMessagesWithLowLifetime) {
|
TEST_P(DcSctpSocketParametrizedTest, SendsMessagesWithLowLifetime) {
|
||||||
SocketUnderTest a("A");
|
SocketUnderTest a("A");
|
||||||
auto z = std::make_unique<SocketUnderTest>("Z");
|
auto z = std::make_unique<SocketUnderTest>("Z");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user