#include "common.hpp"
#include "MediaSoupErrors.hpp"
#include "RTC/SCTP/packet/Chunk.hpp"
#include "RTC/SCTP/packet/Packet.hpp"
#include "RTC/SCTP/packet/Parameter.hpp"
#include "RTC/SCTP/packet/chunks/DataChunk.hpp"
#include "RTC/SCTP/packet/chunks/HeartbeatAckChunk.hpp"
#include "RTC/SCTP/packet/chunks/HeartbeatRequestChunk.hpp"
#include "RTC/SCTP/packet/chunks/InitChunk.hpp"
#include "RTC/SCTP/packet/chunks/ShutdownCompleteChunk.hpp"
#include "RTC/SCTP/packet/chunks/UnknownChunk.hpp"
#include "RTC/SCTP/packet/parameters/CookiePreservativeParameter.hpp"
#include "RTC/SCTP/packet/parameters/HeartbeatInfoParameter.hpp"
#include "RTC/SCTP/packet/parameters/IPv4AddressParameter.hpp"
#include "RTC/SCTP/sctpCommon.hpp"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
SCENARIO("SCTP Packet", "[serializable][sctp][packet]")
{
sctpCommon::ResetBuffers();
SECTION("alignof() SCTP structs")
{
REQUIRE(alignof(RTC::SCTP::Packet::CommonHeader) == 4);
}
SECTION("Parse() without Chunks succeeds")
{
alignas(4) uint8_t buffer[] =
{
0x27, 0x10, 0x3E, 0x7F,
0xFF, 0xFF, 0xFF, 0xF5,
0x00, 0x00, 0x00, 0x05
};
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Parse(buffer, sizeof(buffer)) };
CHECK_SCTP_PACKET(
packet.get(),
buffer,
sizeof(buffer),
12,
10000,
15999,
4294967285,
5,
false,
0);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == nullptr);
packet->Serialize(sctpCommon::SerializeBuffer, sizeof(sctpCommon::SerializeBuffer));
std::memset(buffer, 0x00, sizeof(buffer));
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::SerializeBuffer,
sizeof(sctpCommon::SerializeBuffer),
12,
10000,
15999,
4294967285,
5,
false,
0);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == nullptr);
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::SerializeBuffer,
sizeof(sctpCommon::SerializeBuffer),
12,
10000,
15999,
4294967285,
5,
false,
0);
packet.reset(packet->Clone(sctpCommon::CloneBuffer, sizeof(sctpCommon::CloneBuffer)));
std::memset(sctpCommon::SerializeBuffer, 0x00, sizeof(sctpCommon::SerializeBuffer));
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::CloneBuffer,
sizeof(sctpCommon::CloneBuffer),
12,
10000,
15999,
4294967285,
5,
false,
0);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == nullptr);
}
SECTION("Parse() with Chunks succeeds")
{
alignas(4) uint8_t buffer[] =
{
0x27, 0x10, 0x3E, 0x7F,
0xFF, 0xFF, 0xFF, 0xF5,
0x00, 0x00, 0x00, 0x05,
0x00, 0b00001011, 0x00, 0x12,
0x11, 0x22, 0x33, 0x44,
0xFF, 0x00, 0x66, 0x77,
0x12, 0x34, 0x12, 0x34,
0xAB, 0xCD, 0x00, 0x00,
0xEE, 0b00001100, 0x00, 0x07,
0xAA, 0xBB, 0xCC, 0x00,
0x05, 0b00000000, 0x00, 0x0A,
0x00, 0x01, 0x00, 0x06,
0x11, 0x22, 0x00, 0x00,
};
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Parse(buffer, sizeof(buffer)) };
CHECK_SCTP_PACKET(
packet.get(),
buffer,
sizeof(buffer),
52,
10000,
15999,
4294967285,
5,
false,
3);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::UnknownChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatAckChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatRequestChunk>() == nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::ShutdownCompleteChunk>() == nullptr);
const auto* chunk1 = reinterpret_cast<const RTC::SCTP::DataChunk*>(packet->GetChunkAt(0));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == chunk1);
CHECK_SCTP_CHUNK(
chunk1,
nullptr,
20,
20,
RTC::SCTP::Chunk::ChunkType::DATA,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00001011,
false,
0,
false,
0);
REQUIRE(chunk1->GetI() == true);
REQUIRE(chunk1->GetU() == false);
REQUIRE(chunk1->GetB() == true);
REQUIRE(chunk1->GetE() == true);
REQUIRE(chunk1->GetTsn() == 0x11223344);
REQUIRE(chunk1->GetStreamId() == 0xFF00);
REQUIRE(chunk1->GetStreamSequenceNumber() == 0x6677);
REQUIRE(chunk1->GetPayloadProtocolId() == 0x12341234);
REQUIRE(chunk1->HasUserDataPayload() == true);
REQUIRE(chunk1->GetUserDataPayloadLength() == 2);
REQUIRE(chunk1->GetUserDataPayload()[0] == 0xAB);
REQUIRE(chunk1->GetUserDataPayload()[1] == 0xCD);
const auto* chunk2 = reinterpret_cast<const RTC::SCTP::UnknownChunk*>(packet->GetChunkAt(1));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::UnknownChunk>() == chunk2);
CHECK_SCTP_CHUNK(
chunk2,
nullptr,
8,
8,
static_cast<RTC::SCTP::Chunk::ChunkType>(0xEE),
true,
RTC::SCTP::Chunk::ActionForUnknownChunkType::SKIP_AND_REPORT,
0b00001100,
false,
0,
false,
0);
REQUIRE(chunk2->HasUnknownValue() == true);
REQUIRE(chunk2->GetUnknownValueLength() == 3);
REQUIRE(chunk2->GetUnknownValue()[0] == 0xAA);
REQUIRE(chunk2->GetUnknownValue()[1] == 0xBB);
REQUIRE(chunk2->GetUnknownValue()[2] == 0xCC);
REQUIRE(chunk2->GetUnknownValue()[3] == 0x00);
const auto* chunk3 = reinterpret_cast<const RTC::SCTP::HeartbeatAckChunk*>(packet->GetChunkAt(2));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatAckChunk>() == chunk3);
CHECK_SCTP_CHUNK(
chunk3,
nullptr,
12,
12,
RTC::SCTP::Chunk::ChunkType::HEARTBEAT_ACK,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
true,
1,
false,
0);
const auto* parameter3_1 =
reinterpret_cast<const RTC::SCTP::HeartbeatInfoParameter*>(chunk3->GetParameterAt(0));
CHECK_SCTP_PARAMETER(
parameter3_1,
nullptr,
8,
8,
RTC::SCTP::Parameter::ParameterType::HEARTBEAT_INFO,
false,
RTC::SCTP::Parameter::ActionForUnknownParameterType::STOP);
REQUIRE(parameter3_1->HasInfo() == true);
REQUIRE(parameter3_1->GetInfoLength() == 2);
REQUIRE(parameter3_1->GetInfo()[0] == 0x11);
REQUIRE(parameter3_1->GetInfo()[1] == 0x22);
REQUIRE(parameter3_1->GetInfo()[2] == 0x00);
REQUIRE(parameter3_1->GetInfo()[3] == 0x00);
packet->Serialize(sctpCommon::SerializeBuffer, sizeof(sctpCommon::SerializeBuffer));
std::memset(buffer, 0x00, sizeof(buffer));
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::SerializeBuffer,
sizeof(sctpCommon::SerializeBuffer),
52,
10000,
15999,
4294967285,
5,
false,
3);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == chunk1);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::UnknownChunk>() == chunk2);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatAckChunk>() == chunk3);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatRequestChunk>() == nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::ShutdownCompleteChunk>() == nullptr);
chunk1 = reinterpret_cast<const RTC::SCTP::DataChunk*>(packet->GetChunkAt(0));
CHECK_SCTP_CHUNK(
chunk1,
nullptr,
20,
20,
RTC::SCTP::Chunk::ChunkType::DATA,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00001011,
false,
0,
false,
0);
REQUIRE(chunk1->GetI() == true);
REQUIRE(chunk1->GetU() == false);
REQUIRE(chunk1->GetB() == true);
REQUIRE(chunk1->GetE() == true);
REQUIRE(chunk1->GetTsn() == 0x11223344);
REQUIRE(chunk1->GetStreamId() == 0xFF00);
REQUIRE(chunk1->GetStreamSequenceNumber() == 0x6677);
REQUIRE(chunk1->GetPayloadProtocolId() == 0x12341234);
REQUIRE(chunk1->HasUserDataPayload() == true);
REQUIRE(chunk1->GetUserDataPayloadLength() == 2);
REQUIRE(chunk1->GetUserDataPayload()[0] == 0xAB);
REQUIRE(chunk1->GetUserDataPayload()[1] == 0xCD);
chunk2 = reinterpret_cast<const RTC::SCTP::UnknownChunk*>(packet->GetChunkAt(1));
CHECK_SCTP_CHUNK(
chunk2,
nullptr,
8,
8,
static_cast<RTC::SCTP::Chunk::ChunkType>(0xEE),
true,
RTC::SCTP::Chunk::ActionForUnknownChunkType::SKIP_AND_REPORT,
0b00001100,
false,
0,
false,
0);
REQUIRE(chunk2->HasUnknownValue() == true);
REQUIRE(chunk2->GetUnknownValueLength() == 3);
REQUIRE(chunk2->GetUnknownValue()[0] == 0xAA);
REQUIRE(chunk2->GetUnknownValue()[1] == 0xBB);
REQUIRE(chunk2->GetUnknownValue()[2] == 0xCC);
REQUIRE(chunk2->GetUnknownValue()[3] == 0x00);
chunk3 = reinterpret_cast<const RTC::SCTP::HeartbeatAckChunk*>(packet->GetChunkAt(2));
CHECK_SCTP_CHUNK(
chunk3,
nullptr,
12,
12,
RTC::SCTP::Chunk::ChunkType::HEARTBEAT_ACK,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
true,
1,
false,
0);
parameter3_1 =
reinterpret_cast<const RTC::SCTP::HeartbeatInfoParameter*>(chunk3->GetParameterAt(0));
CHECK_SCTP_PARAMETER(
parameter3_1,
nullptr,
8,
8,
RTC::SCTP::Parameter::ParameterType::HEARTBEAT_INFO,
false,
RTC::SCTP::Parameter::ActionForUnknownParameterType::STOP);
REQUIRE(parameter3_1->HasInfo() == true);
REQUIRE(parameter3_1->GetInfoLength() == 2);
REQUIRE(parameter3_1->GetInfo()[0] == 0x11);
REQUIRE(parameter3_1->GetInfo()[1] == 0x22);
REQUIRE(parameter3_1->GetInfo()[2] == 0x00);
REQUIRE(parameter3_1->GetInfo()[3] == 0x00);
packet.reset(packet->Clone(sctpCommon::CloneBuffer, sizeof(sctpCommon::CloneBuffer)));
std::memset(sctpCommon::SerializeBuffer, 0x00, sizeof(sctpCommon::SerializeBuffer));
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::CloneBuffer,
sizeof(sctpCommon::CloneBuffer),
52,
10000,
15999,
4294967285,
5,
false,
3);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::UnknownChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatAckChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatRequestChunk>() == nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::ShutdownCompleteChunk>() == nullptr);
chunk1 = reinterpret_cast<const RTC::SCTP::DataChunk*>(packet->GetChunkAt(0));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::DataChunk>() == chunk1);
CHECK_SCTP_CHUNK(
chunk1,
nullptr,
20,
20,
RTC::SCTP::Chunk::ChunkType::DATA,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00001011,
false,
0,
false,
0);
REQUIRE(chunk1->GetI() == true);
REQUIRE(chunk1->GetU() == false);
REQUIRE(chunk1->GetB() == true);
REQUIRE(chunk1->GetE() == true);
REQUIRE(chunk1->GetTsn() == 0x11223344);
REQUIRE(chunk1->GetStreamId() == 0xFF00);
REQUIRE(chunk1->GetStreamSequenceNumber() == 0x6677);
REQUIRE(chunk1->GetPayloadProtocolId() == 0x12341234);
REQUIRE(chunk1->HasUserDataPayload() == true);
REQUIRE(chunk1->GetUserDataPayloadLength() == 2);
REQUIRE(chunk1->GetUserDataPayload()[0] == 0xAB);
REQUIRE(chunk1->GetUserDataPayload()[1] == 0xCD);
chunk2 = reinterpret_cast<const RTC::SCTP::UnknownChunk*>(packet->GetChunkAt(1));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::UnknownChunk>() == chunk2);
CHECK_SCTP_CHUNK(
chunk2,
nullptr,
8,
8,
static_cast<RTC::SCTP::Chunk::ChunkType>(0xEE),
true,
RTC::SCTP::Chunk::ActionForUnknownChunkType::SKIP_AND_REPORT,
0b00001100,
false,
0,
false,
0);
REQUIRE(chunk2->HasUnknownValue() == true);
REQUIRE(chunk2->GetUnknownValueLength() == 3);
REQUIRE(chunk2->GetUnknownValue()[0] == 0xAA);
REQUIRE(chunk2->GetUnknownValue()[1] == 0xBB);
REQUIRE(chunk2->GetUnknownValue()[2] == 0xCC);
REQUIRE(chunk2->GetUnknownValue()[3] == 0x00);
chunk3 = reinterpret_cast<const RTC::SCTP::HeartbeatAckChunk*>(packet->GetChunkAt(2));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatAckChunk>() == chunk3);
CHECK_SCTP_CHUNK(
chunk3,
nullptr,
12,
12,
RTC::SCTP::Chunk::ChunkType::HEARTBEAT_ACK,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
true,
1,
false,
0);
parameter3_1 =
reinterpret_cast<const RTC::SCTP::HeartbeatInfoParameter*>(chunk3->GetParameterAt(0));
CHECK_SCTP_PARAMETER(
parameter3_1,
nullptr,
8,
8,
RTC::SCTP::Parameter::ParameterType::HEARTBEAT_INFO,
false,
RTC::SCTP::Parameter::ActionForUnknownParameterType::STOP);
REQUIRE(parameter3_1->HasInfo() == true);
REQUIRE(parameter3_1->GetInfoLength() == 2);
REQUIRE(parameter3_1->GetInfo()[0] == 0x11);
REQUIRE(parameter3_1->GetInfo()[1] == 0x22);
REQUIRE(parameter3_1->GetInfo()[2] == 0x00);
REQUIRE(parameter3_1->GetInfo()[3] == 0x00);
}
SECTION("Factory() with Chunks succeeds")
{
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
sctpCommon::FactoryBuffer, sizeof(sctpCommon::FactoryBuffer)) };
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::FactoryBuffer,
sizeof(sctpCommon::FactoryBuffer),
12,
0,
0,
0,
0,
false,
0);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == nullptr);
packet->SetSourcePort(1000);
packet->SetDestinationPort(6000);
packet->SetVerificationTag(12345678);
packet->SetChecksum(0);
auto* chunk1 = packet->BuildChunkInPlace<RTC::SCTP::InitChunk>();
chunk1->SetInitiateTag(87654321);
chunk1->SetAdvertisedReceiverWindowCredit(12345678);
chunk1->SetNumberOfOutboundStreams(11100);
chunk1->SetNumberOfInboundStreams(22200);
chunk1->SetInitialTsn(14141414);
auto* parameter1_1 = chunk1->BuildParameterInPlace<RTC::SCTP::IPv4AddressParameter>();
uint8_t ipBuffer[] = { 0xC0, 0xA8, 0x00, 0x03 };
parameter1_1->SetIPv4Address(ipBuffer);
parameter1_1->Consolidate();
REQUIRE(chunk1->GetFirstParameterOfType<RTC::SCTP::IPv4AddressParameter>() == parameter1_1);
auto* parameter1_2 = chunk1->BuildParameterInPlace<RTC::SCTP::CookiePreservativeParameter>();
parameter1_2->SetLifeSpanIncrement(987654321);
parameter1_2->Consolidate();
REQUIRE(chunk1->GetFirstParameterOfType<RTC::SCTP::CookiePreservativeParameter>() == parameter1_2);
chunk1->Consolidate();
REQUIRE(chunk1->GetFirstParameterOfType<RTC::SCTP::IPv4AddressParameter>() == parameter1_1);
REQUIRE(chunk1->GetFirstParameterOfType<RTC::SCTP::CookiePreservativeParameter>() == parameter1_2);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == chunk1);
auto* chunk2 = packet->BuildChunkInPlace<RTC::SCTP::HeartbeatRequestChunk>();
auto* parameter2_1 = chunk2->BuildParameterInPlace<RTC::SCTP::HeartbeatInfoParameter>();
parameter2_1->SetInfo(sctpCommon::DataBuffer, 3);
parameter2_1->Consolidate();
REQUIRE(chunk2->GetFirstParameterOfType<RTC::SCTP::HeartbeatInfoParameter>() == parameter2_1);
std::memset(sctpCommon::DataBuffer, 0xFF, 3);
chunk2->Consolidate();
REQUIRE(chunk2->GetFirstParameterOfType<RTC::SCTP::HeartbeatInfoParameter>() == parameter2_1);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatRequestChunk>() == chunk2);
packet->WriteCRC32cChecksum();
auto crc32cChecksum = packet->GetChecksum();
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::FactoryBuffer,
sizeof(sctpCommon::FactoryBuffer),
60,
1000,
6000,
12345678,
crc32cChecksum,
true,
2);
packet->Serialize(sctpCommon::SerializeBuffer, packet->GetLength());
std::memset(sctpCommon::FactoryBuffer, 0xAA, sizeof(sctpCommon::FactoryBuffer));
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::SerializeBuffer,
60,
60,
1000,
6000,
12345678,
crc32cChecksum,
true,
2);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == chunk1);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatRequestChunk>() == chunk2);
packet.reset(packet->Clone(sctpCommon::CloneBuffer, packet->GetLength()));
std::memset(sctpCommon::SerializeBuffer, 0x00, sizeof(sctpCommon::SerializeBuffer));
const auto* obtainedChunk1 = reinterpret_cast<const RTC::SCTP::InitChunk*>(packet->GetChunkAt(0));
const auto* obtainedParameter1_1 =
reinterpret_cast<const RTC::SCTP::IPv4AddressParameter*>(obtainedChunk1->GetParameterAt(0));
const auto* obtainedParameter1_2 =
reinterpret_cast<const RTC::SCTP::CookiePreservativeParameter*>(
obtainedChunk1->GetParameterAt(1));
const auto* obtainedChunk2 =
reinterpret_cast<const RTC::SCTP::HeartbeatRequestChunk*>(packet->GetChunkAt(1));
const auto* obtainedParameter2_1 =
reinterpret_cast<const RTC::SCTP::HeartbeatInfoParameter*>(obtainedChunk2->GetParameterAt(0));
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::CloneBuffer,
60,
60,
1000,
6000,
12345678,
crc32cChecksum,
true,
2);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::InitChunk>() == obtainedChunk1);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::HeartbeatRequestChunk>() == obtainedChunk2);
CHECK_SCTP_CHUNK(
obtainedChunk1,
nullptr,
20 + 8 + 8,
20 + 8 + 8,
RTC::SCTP::Chunk::ChunkType::INIT,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
true,
2,
false,
0);
REQUIRE(obtainedChunk1->GetInitiateTag() == 87654321);
REQUIRE(obtainedChunk1->GetAdvertisedReceiverWindowCredit() == 12345678);
REQUIRE(obtainedChunk1->GetNumberOfOutboundStreams() == 11100);
REQUIRE(obtainedChunk1->GetNumberOfInboundStreams() == 22200);
REQUIRE(obtainedChunk1->GetInitialTsn() == 14141414);
CHECK_SCTP_PARAMETER(
obtainedParameter1_1,
nullptr,
8,
8,
RTC::SCTP::Parameter::ParameterType::IPV4_ADDRESS,
false,
RTC::SCTP::Parameter::ActionForUnknownParameterType::STOP);
REQUIRE(obtainedParameter1_1->GetIPv4Address()[0] == 0xC0);
REQUIRE(obtainedParameter1_1->GetIPv4Address()[1] == 0xA8);
REQUIRE(obtainedParameter1_1->GetIPv4Address()[2] == 0x00);
REQUIRE(obtainedParameter1_1->GetIPv4Address()[3] == 0x03);
CHECK_SCTP_PARAMETER(
obtainedParameter1_2,
nullptr,
8,
8,
RTC::SCTP::Parameter::ParameterType::COOKIE_PRESERVATIVE,
false,
RTC::SCTP::Parameter::ActionForUnknownParameterType::STOP);
REQUIRE(obtainedParameter1_2->GetLifeSpanIncrement() == 987654321);
CHECK_SCTP_CHUNK(
obtainedChunk2,
nullptr,
4 + 8,
4 + 8,
RTC::SCTP::Chunk::ChunkType::HEARTBEAT_REQUEST,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
true,
1,
false,
0);
CHECK_SCTP_PARAMETER(
obtainedParameter2_1,
nullptr,
8,
8,
RTC::SCTP::Parameter::ParameterType::HEARTBEAT_INFO,
false,
RTC::SCTP::Parameter::ActionForUnknownParameterType::STOP);
REQUIRE(obtainedParameter2_1->HasInfo() == true);
REQUIRE(obtainedParameter2_1->GetInfoLength() == 3);
REQUIRE(obtainedParameter2_1->GetInfo()[0] == 0x00);
REQUIRE(obtainedParameter2_1->GetInfo()[1] == 0x01);
REQUIRE(obtainedParameter2_1->GetInfo()[2] == 0x02);
}
SECTION("Factory() using AddChunk() succeeds")
{
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
sctpCommon::FactoryBuffer, 1000) };
packet->SetSourcePort(1);
packet->SetDestinationPort(2);
packet->SetVerificationTag(3);
packet->SetChecksum(4);
auto* chunk1 = RTC::SCTP::ShutdownCompleteChunk::Factory(sctpCommon::FactoryBuffer + 1000, 1000);
chunk1->SetT(true);
packet->AddChunk(chunk1);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::ShutdownCompleteChunk>() != nullptr);
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::ShutdownCompleteChunk>() != chunk1);
delete chunk1;
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::FactoryBuffer,
1000,
16,
1,
2,
3,
4,
false,
1);
const auto* obtainedChunk1 =
reinterpret_cast<const RTC::SCTP::ShutdownCompleteChunk*>(packet->GetChunkAt(0));
REQUIRE(packet->GetFirstChunkOfType<RTC::SCTP::ShutdownCompleteChunk>() == obtainedChunk1);
CHECK_SCTP_CHUNK(
obtainedChunk1,
nullptr,
4,
4,
RTC::SCTP::Chunk::ChunkType::SHUTDOWN_COMPLETE,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000001,
false,
0,
false,
0);
REQUIRE(obtainedChunk1->GetT() == true);
}
SECTION("BuildChunkInPlace() throws if given Chunk exceeds Packet buffer length")
{
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
sctpCommon::FactoryBuffer, 28) };
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::FactoryBuffer,
28,
12,
0,
0,
0,
0,
false,
0);
auto* chunk1 = packet->BuildChunkInPlace<RTC::SCTP::DataChunk>();
REQUIRE_THROWS_AS(chunk1->SetUserDataPayload(sctpCommon::DataBuffer, 10), MediaSoupError);
delete chunk1;
REQUIRE_THROWS_AS(packet->BuildChunkInPlace<RTC::SCTP::InitChunk>(), MediaSoupError);
CHECK_SCTP_PACKET(
packet.get(),
sctpCommon::FactoryBuffer,
28,
12,
0,
0,
0,
0,
false,
0);
}
SECTION("BuildChunkInPlace() and AddChunk() throw if the Packet needs consolidation")
{
std::unique_ptr<RTC::SCTP::Packet> packet{ RTC::SCTP::Packet::Factory(
sctpCommon::FactoryBuffer, 1000) };
REQUIRE(packet->NeedsConsolidation() == false);
const auto* chunk1 = packet->BuildChunkInPlace<RTC::SCTP::InitChunk>();
REQUIRE(packet->NeedsConsolidation() == true);
REQUIRE_THROWS_AS(packet->BuildChunkInPlace<RTC::SCTP::ShutdownCompleteChunk>(), MediaSoupError);
const auto* chunk2 = RTC::SCTP::ShutdownCompleteChunk::Factory(
sctpCommon::FactoryBuffer + 1000, sizeof(sctpCommon::FactoryBuffer));
REQUIRE_THROWS_AS(packet->AddChunk(chunk2), MediaSoupError);
delete chunk2;
chunk1->Consolidate();
REQUIRE(packet->NeedsConsolidation() == false);
const auto* chunk3 = packet->BuildChunkInPlace<RTC::SCTP::ShutdownCompleteChunk>();
REQUIRE(packet->NeedsConsolidation() == true);
chunk3->Consolidate();
REQUIRE(packet->NeedsConsolidation() == false);
const auto* chunk4 = RTC::SCTP::ShutdownCompleteChunk::Factory(
sctpCommon::FactoryBuffer + 1000, sizeof(sctpCommon::FactoryBuffer));
packet->AddChunk(chunk4);
REQUIRE(packet->NeedsConsolidation() == false);
delete chunk4;
}
}