#include "common.hpp"
#include "MediaSoupErrors.hpp"
#include "RTC/SCTP/packet/Chunk.hpp"
#include "RTC/SCTP/packet/ErrorCause.hpp"
#include "RTC/SCTP/packet/chunks/OperationErrorChunk.hpp"
#include "RTC/SCTP/packet/errorCauses/InvalidStreamIdentifierErrorCause.hpp"
#include "RTC/SCTP/packet/errorCauses/OutOfResourceErrorCause.hpp"
#include "RTC/SCTP/packet/errorCauses/UnknownErrorCause.hpp"
#include "RTC/SCTP/packet/errorCauses/UnrecognizedChunkTypeErrorCause.hpp"
#include "RTC/SCTP/sctpCommon.hpp"
#include <catch2/catch_test_macros.hpp>
#include <cstring>
SCENARIO("SCTP Operation Error Chunk (9)", "[serializable][sctp][chunk]")
{
sctpCommon::ResetBuffers();
SECTION("OperationErrorChunk::Parse() succeeds")
{
alignas(4) uint8_t buffer[] =
{
0x09, 0b00000000, 0x00, 0x15,
0x00, 0x01, 0x00, 0x08,
0x12, 0x34, 0x00, 0x00,
0x00, 0x04, 0x00, 0x04,
0xC0, 0x07, 0x00, 0x05,
0xAB, 0x00, 0x00, 0x00,
0xAA, 0xBB, 0xCC, 0xDD,
0xAA, 0xBB, 0xCC, 0xDD,
};
auto* chunk = RTC::SCTP::OperationErrorChunk::Parse(buffer, sizeof(buffer));
CHECK_SCTP_CHUNK(
chunk,
buffer,
sizeof(buffer),
24,
RTC::SCTP::Chunk::ChunkType::OPERATION_ERROR,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
false,
0,
true,
3);
const auto* errorCause1 = reinterpret_cast<const RTC::SCTP::InvalidStreamIdentifierErrorCause*>(
chunk->GetErrorCauseAt(0));
REQUIRE(
chunk->GetFirstErrorCauseOfCode<RTC::SCTP::InvalidStreamIdentifierErrorCause>() == errorCause1);
CHECK_SCTP_ERROR_CAUSE(
errorCause1,
nullptr,
8,
8,
RTC::SCTP::ErrorCause::ErrorCauseCode::INVALID_STREAM_IDENTIFIER,
false);
REQUIRE(errorCause1->GetStreamIdentifier() == 0x1234);
const auto* errorCause2 =
reinterpret_cast<const RTC::SCTP::OutOfResourceErrorCause*>(chunk->GetErrorCauseAt(1));
REQUIRE(chunk->GetFirstErrorCauseOfCode<RTC::SCTP::OutOfResourceErrorCause>() == errorCause2);
CHECK_SCTP_ERROR_CAUSE(
errorCause2,
nullptr,
4,
4,
RTC::SCTP::ErrorCause::ErrorCauseCode::OUT_OF_RESOURCE,
false);
const auto* errorCause3 =
reinterpret_cast<const RTC::SCTP::UnknownErrorCause*>(chunk->GetErrorCauseAt(2));
REQUIRE(chunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnknownErrorCause>() == errorCause3);
CHECK_SCTP_ERROR_CAUSE(
errorCause3,
nullptr,
8,
8,
static_cast<RTC::SCTP::ErrorCause::ErrorCauseCode>(49159),
true);
REQUIRE(errorCause3->HasUnknownValue() == true);
REQUIRE(errorCause3->GetUnknownValueLength() == 1);
REQUIRE(errorCause3->GetUnknownValue()[0] == 0xAB);
REQUIRE(errorCause3->GetUnknownValue()[1] == 0x00);
REQUIRE(errorCause3->GetUnknownValue()[2] == 0x00);
REQUIRE(errorCause3->GetUnknownValue()[3] == 0x00);
chunk->Serialize(sctpCommon::SerializeBuffer, sizeof(sctpCommon::SerializeBuffer));
std::memset(buffer, 0x00, sizeof(buffer));
CHECK_SCTP_CHUNK(
chunk,
sctpCommon::SerializeBuffer,
sizeof(sctpCommon::SerializeBuffer),
24,
RTC::SCTP::Chunk::ChunkType::OPERATION_ERROR,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
false,
0,
true,
3);
errorCause1 = reinterpret_cast<const RTC::SCTP::InvalidStreamIdentifierErrorCause*>(
chunk->GetErrorCauseAt(0));
REQUIRE(
chunk->GetFirstErrorCauseOfCode<RTC::SCTP::InvalidStreamIdentifierErrorCause>() == errorCause1);
CHECK_SCTP_ERROR_CAUSE(
errorCause1,
nullptr,
8,
8,
RTC::SCTP::ErrorCause::ErrorCauseCode::INVALID_STREAM_IDENTIFIER,
false);
REQUIRE(errorCause1->GetStreamIdentifier() == 0x1234);
errorCause2 =
reinterpret_cast<const RTC::SCTP::OutOfResourceErrorCause*>(chunk->GetErrorCauseAt(1));
REQUIRE(chunk->GetFirstErrorCauseOfCode<RTC::SCTP::OutOfResourceErrorCause>() == errorCause2);
CHECK_SCTP_ERROR_CAUSE(
errorCause2,
nullptr,
4,
4,
RTC::SCTP::ErrorCause::ErrorCauseCode::OUT_OF_RESOURCE,
false);
errorCause3 = reinterpret_cast<const RTC::SCTP::UnknownErrorCause*>(chunk->GetErrorCauseAt(2));
REQUIRE(chunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnknownErrorCause>() == errorCause3);
CHECK_SCTP_ERROR_CAUSE(
errorCause3,
nullptr,
8,
8,
static_cast<RTC::SCTP::ErrorCause::ErrorCauseCode>(49159),
true);
REQUIRE(errorCause3->HasUnknownValue() == true);
REQUIRE(errorCause3->GetUnknownValueLength() == 1);
REQUIRE(errorCause3->GetUnknownValue()[0] == 0xAB);
REQUIRE(errorCause3->GetUnknownValue()[1] == 0x00);
REQUIRE(errorCause3->GetUnknownValue()[2] == 0x00);
REQUIRE(errorCause3->GetUnknownValue()[3] == 0x00);
auto* clonedChunk = chunk->Clone(sctpCommon::CloneBuffer, sizeof(sctpCommon::CloneBuffer));
std::memset(sctpCommon::SerializeBuffer, 0x00, sizeof(sctpCommon::SerializeBuffer));
delete chunk;
CHECK_SCTP_CHUNK(
clonedChunk,
sctpCommon::CloneBuffer,
sizeof(sctpCommon::CloneBuffer),
24,
RTC::SCTP::Chunk::ChunkType::OPERATION_ERROR,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
false,
0,
true,
3);
errorCause1 = reinterpret_cast<const RTC::SCTP::InvalidStreamIdentifierErrorCause*>(
clonedChunk->GetErrorCauseAt(0));
REQUIRE(
clonedChunk->GetFirstErrorCauseOfCode<RTC::SCTP::InvalidStreamIdentifierErrorCause>() ==
errorCause1);
CHECK_SCTP_ERROR_CAUSE(
errorCause1,
nullptr,
8,
8,
RTC::SCTP::ErrorCause::ErrorCauseCode::INVALID_STREAM_IDENTIFIER,
false);
REQUIRE(errorCause1->GetStreamIdentifier() == 0x1234);
errorCause2 =
reinterpret_cast<const RTC::SCTP::OutOfResourceErrorCause*>(clonedChunk->GetErrorCauseAt(1));
REQUIRE(
clonedChunk->GetFirstErrorCauseOfCode<RTC::SCTP::OutOfResourceErrorCause>() == errorCause2);
CHECK_SCTP_ERROR_CAUSE(
errorCause2,
nullptr,
4,
4,
RTC::SCTP::ErrorCause::ErrorCauseCode::OUT_OF_RESOURCE,
false);
errorCause3 =
reinterpret_cast<const RTC::SCTP::UnknownErrorCause*>(clonedChunk->GetErrorCauseAt(2));
REQUIRE(clonedChunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnknownErrorCause>() == errorCause3);
CHECK_SCTP_ERROR_CAUSE(
errorCause3,
nullptr,
8,
8,
static_cast<RTC::SCTP::ErrorCause::ErrorCauseCode>(49159),
true);
REQUIRE(errorCause3->HasUnknownValue() == true);
REQUIRE(errorCause3->GetUnknownValueLength() == 1);
REQUIRE(errorCause3->GetUnknownValue()[0] == 0xAB);
REQUIRE(errorCause3->GetUnknownValue()[1] == 0x00);
REQUIRE(errorCause3->GetUnknownValue()[2] == 0x00);
REQUIRE(errorCause3->GetUnknownValue()[3] == 0x00);
delete clonedChunk;
}
SECTION("OperationErrorChunk::Factory() succeeds")
{
auto* chunk = RTC::SCTP::OperationErrorChunk::Factory(
sctpCommon::FactoryBuffer, sizeof(sctpCommon::FactoryBuffer));
CHECK_SCTP_CHUNK(
chunk,
sctpCommon::FactoryBuffer,
sizeof(sctpCommon::FactoryBuffer),
4,
RTC::SCTP::Chunk::ChunkType::OPERATION_ERROR,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
false,
0,
true,
0);
REQUIRE(chunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnrecognizedChunkTypeErrorCause>() == nullptr);
REQUIRE(chunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnknownErrorCause>() == nullptr);
auto* errorCause1 = chunk->BuildErrorCauseInPlace<RTC::SCTP::UnrecognizedChunkTypeErrorCause>();
errorCause1->SetUnrecognizedChunk(sctpCommon::DataBuffer, 5);
errorCause1->Consolidate();
REQUIRE(
chunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnrecognizedChunkTypeErrorCause>() == errorCause1);
auto* errorCause2 = chunk->BuildErrorCauseInPlace<RTC::SCTP::UnrecognizedChunkTypeErrorCause>();
errorCause2->SetUnrecognizedChunk(sctpCommon::DataBuffer, 2);
errorCause2->Consolidate();
REQUIRE(
chunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnrecognizedChunkTypeErrorCause>() == errorCause1);
CHECK_SCTP_CHUNK(
chunk,
sctpCommon::FactoryBuffer,
sizeof(sctpCommon::FactoryBuffer),
4 + (4 + 5 + 3) + (4 + 2 + 2),
RTC::SCTP::Chunk::ChunkType::OPERATION_ERROR,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
false,
0,
true,
2);
const auto* addedErrorCause1 =
reinterpret_cast<const RTC::SCTP::UnrecognizedChunkTypeErrorCause*>(chunk->GetErrorCauseAt(0));
CHECK_SCTP_ERROR_CAUSE(
addedErrorCause1,
nullptr,
12,
12,
RTC::SCTP::ErrorCause::ErrorCauseCode::UNRECOGNIZED_CHUNK_TYPE,
false);
REQUIRE(addedErrorCause1->HasUnrecognizedChunk() == true);
REQUIRE(addedErrorCause1->GetUnrecognizedChunkLength() == 5);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[0] == 0x00);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[1] == 0x01);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[2] == 0x02);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[3] == 0x03);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[4] == 0x04);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[5] == 0x00);
REQUIRE(addedErrorCause1->GetUnrecognizedChunk()[6] == 0x00);
const auto* addedErrorCause2 =
reinterpret_cast<const RTC::SCTP::UnrecognizedChunkTypeErrorCause*>(chunk->GetErrorCauseAt(1));
CHECK_SCTP_ERROR_CAUSE(
addedErrorCause2,
nullptr,
8,
8,
RTC::SCTP::ErrorCause::ErrorCauseCode::UNRECOGNIZED_CHUNK_TYPE,
false);
REQUIRE(addedErrorCause2->HasUnrecognizedChunk() == true);
REQUIRE(addedErrorCause2->GetUnrecognizedChunkLength() == 2);
REQUIRE(addedErrorCause2->GetUnrecognizedChunk()[0] == 0x00);
REQUIRE(addedErrorCause2->GetUnrecognizedChunk()[1] == 0x01);
REQUIRE(addedErrorCause2->GetUnrecognizedChunk()[2] == 0x00);
REQUIRE(addedErrorCause2->GetUnrecognizedChunk()[3] == 0x00);
auto* parsedChunk = RTC::SCTP::OperationErrorChunk::Parse(chunk->GetBuffer(), chunk->GetLength());
delete chunk;
CHECK_SCTP_CHUNK(
parsedChunk,
sctpCommon::FactoryBuffer,
4 + (4 + 5 + 3) + (4 + 2 + 2),
4 + (4 + 5 + 3) + (4 + 2 + 2),
RTC::SCTP::Chunk::ChunkType::OPERATION_ERROR,
false,
RTC::SCTP::Chunk::ActionForUnknownChunkType::STOP,
0b00000000,
false,
0,
true,
2);
const auto* parsedErrorCause1 =
reinterpret_cast<const RTC::SCTP::UnrecognizedChunkTypeErrorCause*>(
parsedChunk->GetErrorCauseAt(0));
REQUIRE(
parsedChunk->GetFirstErrorCauseOfCode<RTC::SCTP::UnrecognizedChunkTypeErrorCause>() ==
parsedErrorCause1);
CHECK_SCTP_ERROR_CAUSE(
parsedErrorCause1,
nullptr,
12,
12,
RTC::SCTP::ErrorCause::ErrorCauseCode::UNRECOGNIZED_CHUNK_TYPE,
false);
REQUIRE(parsedErrorCause1->HasUnrecognizedChunk() == true);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunkLength() == 5);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[0] == 0x00);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[1] == 0x01);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[2] == 0x02);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[3] == 0x03);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[4] == 0x04);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[5] == 0x00);
REQUIRE(parsedErrorCause1->GetUnrecognizedChunk()[6] == 0x00);
const auto* parsedErrorCause2 =
reinterpret_cast<const RTC::SCTP::UnrecognizedChunkTypeErrorCause*>(
parsedChunk->GetErrorCauseAt(1));
CHECK_SCTP_ERROR_CAUSE(
parsedErrorCause2,
nullptr,
8,
8,
RTC::SCTP::ErrorCause::ErrorCauseCode::UNRECOGNIZED_CHUNK_TYPE,
false);
REQUIRE(parsedErrorCause2->HasUnrecognizedChunk() == true);
REQUIRE(parsedErrorCause2->GetUnrecognizedChunkLength() == 2);
REQUIRE(parsedErrorCause2->GetUnrecognizedChunk()[0] == 0x00);
REQUIRE(parsedErrorCause2->GetUnrecognizedChunk()[1] == 0x01);
REQUIRE(parsedErrorCause2->GetUnrecognizedChunk()[2] == 0x00);
REQUIRE(parsedErrorCause2->GetUnrecognizedChunk()[3] == 0x00);
delete parsedChunk;
}
}