зеркало из https://github.com/microsoft/msquic.git
Add test cases for QuicDrill Initial Packet fuzzing (#44)
These test cases cover fuzzing the Connection ID (CID) in the initial packet, as well the optional Token field. Changes are passing in both TAEF and gtest.
This commit is contained in:
Родитель
e7bc785c09
Коммит
74cc1a5b73
|
@ -219,6 +219,20 @@ void
|
|||
QuicDrillTestVarIntEncoder(
|
||||
);
|
||||
|
||||
void
|
||||
QuicDrillTestInitialCid(
|
||||
_In_ int Family,
|
||||
_In_ bool Source, // or Dest
|
||||
_In_ bool ValidActualLength, // or invalid
|
||||
_In_ bool Short, // or long
|
||||
_In_ bool ValidLengthField // or invalid
|
||||
);
|
||||
|
||||
void
|
||||
QuicDrillTestInitialToken(
|
||||
_In_ int Family
|
||||
);
|
||||
|
||||
//
|
||||
// Platform Specific Functions
|
||||
//
|
||||
|
@ -470,6 +484,22 @@ typedef struct {
|
|||
#define IOCTL_QUIC_RUN_DRILL_ENCODE_VAR_INT \
|
||||
QUIC_CTL_CODE(35, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
|
||||
#define QUIC_MAX_IOCTL_FUNC_CODE 35
|
||||
typedef struct {
|
||||
INT32 Family;
|
||||
BOOLEAN SourceOrDest;
|
||||
BOOLEAN ActualCidLengthValid;
|
||||
BOOLEAN ShortCidLength;
|
||||
BOOLEAN CidLengthFieldValid;
|
||||
} QUIC_RUN_DRILL_INITIAL_PACKET_CID_PARAMS;
|
||||
|
||||
#define IOCTL_QUIC_RUN_DRILL_INITIAL_PACKET_CID \
|
||||
QUIC_CTL_CODE(36, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
// QUIC_RUN_DRILL_INITIAL_PACKET_CID_PARAMS
|
||||
|
||||
#define IOCTL_QUIC_RUN_DRILL_INITIAL_PACKET_TOKEN \
|
||||
QUIC_CTL_CODE(37, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
// INT32 - Family
|
||||
|
||||
#define QUIC_MAX_IOCTL_FUNC_CODE 37
|
||||
|
||||
#endif // _WIN32
|
|
@ -19,8 +19,13 @@ QUIC_SEC_CONFIG* SecurityConfig;
|
|||
extern "C" _IRQL_requires_max_(PASSIVE_LEVEL) void QuicTraceRundown(void) { }
|
||||
|
||||
class QuicTestEnvironment : public ::testing::Environment {
|
||||
bool PlatformInitialized;
|
||||
public:
|
||||
void SetUp() override {
|
||||
if (QUIC_FAILED(QuicPlatformInitialize())) {
|
||||
return; // TODO - FAIL SetUp
|
||||
}
|
||||
PlatformInitialized = true;
|
||||
if (QUIC_FAILED(MsQuicOpenV1(&MsQuic))) {
|
||||
return; // TODO - FAIL SetUp
|
||||
}
|
||||
|
@ -51,6 +56,9 @@ public:
|
|||
Registration = nullptr;
|
||||
MsQuicClose(MsQuic);
|
||||
MsQuic = nullptr;
|
||||
if (PlatformInitialized) {
|
||||
QuicPlatformUninitialize();
|
||||
}
|
||||
}
|
||||
_Function_class_(QUIC_SEC_CONFIG_CREATE_COMPLETE)
|
||||
static void
|
||||
|
@ -419,6 +427,21 @@ TEST_P(WithReceiveResumeNoDataArgs, ReceiveResumeNoData) {
|
|||
QuicTestReceiveResumeNoData(GetParam().Family, GetParam().ShutdownType);
|
||||
}
|
||||
|
||||
TEST_P(WithDrillInitialPacketCidArgs, DrillInitialPacketCids) {
|
||||
TestLoggerT<ParamType> Logger("QuicDrillInitialPacketCids", GetParam());
|
||||
QuicDrillTestInitialCid(
|
||||
GetParam().Family,
|
||||
GetParam().SourceOrDest,
|
||||
GetParam().ActualCidLengthValid,
|
||||
GetParam().ShortCidLength,
|
||||
GetParam().CidLengthFieldValid);
|
||||
}
|
||||
|
||||
TEST_P(WithDrillInitialPacketTokenArgs, DrillInitialPacketToken) {
|
||||
TestLoggerT<ParamType> Logger("QuicDrillInitialPacketToken", GetParam());
|
||||
QuicDrillTestInitialToken(GetParam().Family);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ParameterValidation,
|
||||
WithBool,
|
||||
|
@ -479,6 +502,16 @@ INSTANTIATE_TEST_CASE_P(
|
|||
WithReceiveResumeNoDataArgs,
|
||||
testing::ValuesIn(ReceiveResumeNoDataArgs::Generate()));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
Drill,
|
||||
WithDrillInitialPacketCidArgs,
|
||||
testing::ValuesIn(DrillInitialPacketCidArgs::Generate()));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
Drill,
|
||||
WithDrillInitialPacketTokenArgs,
|
||||
testing::ValuesIn(DrillInitialPacketTokenArgs::Generate()));
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::AddGlobalTestEnvironment(new QuicTestEnvironment);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
|
|
@ -318,3 +318,55 @@ std::ostream& operator << (std::ostream& o, const ReceiveResumeNoDataArgs& args)
|
|||
class WithReceiveResumeNoDataArgs : public testing::Test,
|
||||
public testing::WithParamInterface<ReceiveResumeNoDataArgs> {
|
||||
};
|
||||
|
||||
struct DrillInitialPacketCidArgs {
|
||||
int Family;
|
||||
bool SourceOrDest;
|
||||
bool ActualCidLengthValid;
|
||||
bool ShortCidLength;
|
||||
bool CidLengthFieldValid;
|
||||
|
||||
static ::std::vector<DrillInitialPacketCidArgs> Generate() {
|
||||
::std::vector<DrillInitialPacketCidArgs> list;
|
||||
for (int Family : { 4, 6 })
|
||||
for (bool SourceOrDest : { true, false })
|
||||
for (bool ActualCidLengthValid : { true, false })
|
||||
for (bool ShortCidLength : { true, false })
|
||||
for (bool CidLengthFieldValid : { true, false })
|
||||
list.push_back({ Family, SourceOrDest, ActualCidLengthValid, ShortCidLength, CidLengthFieldValid });
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator << (std::ostream& o, const DrillInitialPacketCidArgs& args) {
|
||||
return o <<
|
||||
(args.Family == 4 ? "v4" : "v6") << "/" <<
|
||||
(args.SourceOrDest ? "SourceCid" : "DestCid") << "/" <<
|
||||
(args.ActualCidLengthValid ? "Valid" : "Invalid") << "/" <<
|
||||
(args.ShortCidLength ? "Short" : "Long") << "/" <<
|
||||
(args.CidLengthFieldValid ? "Valid" : "Invalid") << " length";
|
||||
}
|
||||
|
||||
class WithDrillInitialPacketCidArgs: public testing::Test,
|
||||
public testing::WithParamInterface<DrillInitialPacketCidArgs> {
|
||||
};
|
||||
|
||||
struct DrillInitialPacketTokenArgs {
|
||||
int Family;
|
||||
|
||||
static ::std::vector<DrillInitialPacketTokenArgs> Generate() {
|
||||
::std::vector<DrillInitialPacketTokenArgs> list;
|
||||
for (int Family : { 4, 6 })
|
||||
list.push_back({ Family, });
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator << (std::ostream& o, const DrillInitialPacketTokenArgs& args) {
|
||||
return o <<
|
||||
(args.Family == 4 ? "v4" : "v6");
|
||||
}
|
||||
|
||||
class WithDrillInitialPacketTokenArgs: public testing::Test,
|
||||
public testing::WithParamInterface<DrillInitialPacketTokenArgs> {
|
||||
};
|
||||
|
|
|
@ -9,23 +9,28 @@
|
|||
|
||||
DrillBuffer
|
||||
QuicDrillEncodeQuicVarInt(
|
||||
uint64_t input
|
||||
uint64_t input,
|
||||
const DrillVarIntSize size
|
||||
)
|
||||
{
|
||||
DrillBuffer result;
|
||||
uint8_t* inputPointer = ((uint8_t*)&input);
|
||||
|
||||
if (input < 0x40) {
|
||||
if (size == OneByte) {
|
||||
QUIC_FRE_ASSERT(input < 0x40);
|
||||
result.push_back((uint8_t) input);
|
||||
} else if (input < 0x4000) {
|
||||
} else if (size == TwoBytes) {
|
||||
QUIC_FRE_ASSERT(input < 0x4000);
|
||||
result.push_back(0x40 | inputPointer[1]);
|
||||
result.push_back(inputPointer[0]);
|
||||
} else if (input < 0x40000000) {
|
||||
} else if (size == FourBytes) {
|
||||
QUIC_FRE_ASSERT(input < 0x40000000);
|
||||
result.push_back(0x80 | inputPointer[3]);
|
||||
result.push_back(inputPointer[2]);
|
||||
result.push_back(inputPointer[1]);
|
||||
result.push_back(inputPointer[0]);
|
||||
} else if (input < 0x4000000000000000ull) {
|
||||
} else if (size == EightBytes) {
|
||||
QUIC_FRE_ASSERT(input < 0x4000000000000000ull);
|
||||
result.push_back(0xc0 | inputPointer[7]);
|
||||
result.push_back(inputPointer[6]);
|
||||
result.push_back(inputPointer[5]);
|
||||
|
@ -36,15 +41,37 @@ QuicDrillEncodeQuicVarInt(
|
|||
result.push_back(inputPointer[0]);
|
||||
} else {
|
||||
QUIC_FRE_ASSERTMSG(
|
||||
input < 0x4000000000000000ull,
|
||||
"Supplied value is larger than QUIC_VAR_INT allowed (2^62)");
|
||||
size == EightBytes,
|
||||
"Supplied size is not a valid QUIC_VAR_INT size");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DrillBuffer
|
||||
DrillPacketDescriptor::write(
|
||||
QuicDrillEncodeQuicVarInt (
|
||||
uint64_t input
|
||||
)
|
||||
{
|
||||
if (input < 0x40) {
|
||||
return QuicDrillEncodeQuicVarInt(input, OneByte);
|
||||
} else if (input < 0x4000) {
|
||||
return QuicDrillEncodeQuicVarInt(input, TwoBytes);
|
||||
} else if (input < 0x40000000) {
|
||||
return QuicDrillEncodeQuicVarInt(input, FourBytes);
|
||||
} else if (input < 0x4000000000000000ull) {
|
||||
return QuicDrillEncodeQuicVarInt(input, EightBytes);
|
||||
} else {
|
||||
QUIC_FRE_ASSERTMSG(
|
||||
input < 0x4000000000000000ull,
|
||||
"Supplied value is larger than QUIC_VAR_INT allowed (2^62)");
|
||||
return DrillBuffer();
|
||||
}
|
||||
return DrillBuffer();
|
||||
}
|
||||
|
||||
DrillBuffer
|
||||
DrillPacketDescriptor::write(
|
||||
) const
|
||||
{
|
||||
size_t RequiredSize = 0;
|
||||
|
||||
|
@ -52,11 +79,11 @@ DrillPacketDescriptor::write(
|
|||
// Calculate the size required to write the packet.
|
||||
//
|
||||
RequiredSize += 1; // For the bit fields.
|
||||
RequiredSize += sizeof(this->Version);
|
||||
RequiredSize += sizeof(Version);
|
||||
RequiredSize += 1; // For the size of DestCid.
|
||||
RequiredSize += this->DestCid.size();
|
||||
RequiredSize += DestCid.size();
|
||||
RequiredSize += 1; // For the size of SourceCid.
|
||||
RequiredSize += this->SourceCid.size();
|
||||
RequiredSize += SourceCid.size();
|
||||
|
||||
QUIC_FRE_ASSERTMSG(
|
||||
RequiredSize <= UINT16_MAX,
|
||||
|
@ -77,8 +104,8 @@ DrillPacketDescriptor::write(
|
|||
//
|
||||
// Copy version.
|
||||
//
|
||||
for (int i = 0; i < sizeof(this->Version); ++i) {
|
||||
PacketBuffer.push_back((uint8_t) (Version >> ((3 - i) * 8)));
|
||||
for (int i = 0; i < sizeof(Version); ++i) {
|
||||
PacketBuffer.push_back((uint8_t) (Version >> (((sizeof(Version) - 1) - i) * 8)));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -109,17 +136,23 @@ DrillPacketDescriptor::write(
|
|||
}
|
||||
|
||||
DrillInitialPacketDescriptor::DrillInitialPacketDescriptor(
|
||||
)
|
||||
) : DrillPacketDescriptor(), TokenLen(nullptr), PacketLength(nullptr), PacketNumber(0)
|
||||
{
|
||||
this->Type = Initial;
|
||||
this->Header.LongHeader = 1;
|
||||
this->Header.FixedBit = 1;
|
||||
this->Version = 1;
|
||||
Type = Initial;
|
||||
Header.LongHeader = 1;
|
||||
Header.FixedBit = 1;
|
||||
Version = QUIC_VERSION_LATEST_H;
|
||||
|
||||
const uint8_t CidValMax = 8;
|
||||
for (uint8_t CidVal = 0; CidVal <= CidValMax; CidVal++) {
|
||||
DestCid.push_back(CidVal);
|
||||
SourceCid.push_back(CidValMax - CidVal);
|
||||
}
|
||||
}
|
||||
|
||||
DrillBuffer
|
||||
DrillInitialPacketDescriptor::write(
|
||||
)
|
||||
) const
|
||||
{
|
||||
DrillBuffer PacketBuffer = DrillPacketDescriptor::write();
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ class DrillBuffer : public Rtl::KArray<uint8_t>
|
|||
QUIC_FRE_ASSERT(append(value));
|
||||
}
|
||||
|
||||
size_t size() { return count(); }
|
||||
const uint8_t* data() const { return &(*this)[0]; }
|
||||
|
||||
size_t size() const { return count(); }
|
||||
|
||||
void
|
||||
insert(
|
||||
|
@ -80,10 +82,12 @@ struct DrillPacketDescriptor {
|
|||
uint8_t* SourceCidLen;
|
||||
DrillBuffer SourceCid;
|
||||
|
||||
DrillPacketDescriptor() : SourceCidLen(nullptr), DestCidLen(nullptr) {};
|
||||
|
||||
//
|
||||
// Write this descriptor to a byte array to send on the wire.
|
||||
//
|
||||
virtual DrillBuffer write();
|
||||
virtual DrillBuffer write() const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -117,10 +121,23 @@ struct DrillInitialPacketDescriptor : DrillPacketDescriptor {
|
|||
//
|
||||
// Write this descriptor to a byte array to send on the wire.
|
||||
//
|
||||
virtual DrillBuffer write();
|
||||
virtual DrillBuffer write() const;
|
||||
};
|
||||
|
||||
enum DrillVarIntSize {
|
||||
OneByte = 1,
|
||||
TwoBytes = 2,
|
||||
FourBytes = 4,
|
||||
EightBytes = 8
|
||||
};
|
||||
|
||||
DrillBuffer
|
||||
QuicDrillEncodeQuicVarInt (
|
||||
const uint64_t input,
|
||||
const DrillVarIntSize size
|
||||
);
|
||||
|
||||
DrillBuffer
|
||||
QuicDrillEncodeQuicVarInt(
|
||||
uint64_t input
|
||||
);
|
||||
);
|
||||
|
|
|
@ -7,9 +7,18 @@ Abstract:
|
|||
|
||||
MsQuic Packet-level tests.
|
||||
|
||||
Future:
|
||||
Additional test cases to implement:
|
||||
* Test packet number encoded larger than necessary with valid Initial
|
||||
packet.
|
||||
* Test reserved header flags, and packet number size mismatch.
|
||||
|
||||
--*/
|
||||
|
||||
#include "precomp.h"
|
||||
extern "C" {
|
||||
#include <quic_datapath.h>
|
||||
}
|
||||
|
||||
void
|
||||
QuicDrillTestVarIntEncoder(
|
||||
|
@ -56,4 +65,409 @@ QuicDrillTestVarIntEncoder(
|
|||
TEST_EQUAL(output[5], 0xff);
|
||||
TEST_EQUAL(output[6], 0xff);
|
||||
TEST_EQUAL(output[7], 0xff);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
_Function_class_(NEW_CONNECTION_CALLBACK)
|
||||
static
|
||||
void
|
||||
QuicDrillConnectionCallbackHandler(
|
||||
_In_ TestListener* /* Listener */,
|
||||
_In_ HQUIC ConnectionHandle
|
||||
)
|
||||
{
|
||||
TEST_FAILURE("Quic Drill listener received an unexpected event!");
|
||||
MsQuic->ConnectionClose(ConnectionHandle);
|
||||
}
|
||||
|
||||
struct DrillSender {
|
||||
QUIC_DATAPATH* Datapath;
|
||||
QUIC_DATAPATH_BINDING* Binding;
|
||||
QUIC_ADDR ServerAddress;
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
_Function_class_(QUIC_DATAPATH_RECEIVE_CALLBACK)
|
||||
static void
|
||||
DrillUdpRecvCallback(
|
||||
_In_ QUIC_DATAPATH_BINDING* /* Binding */,
|
||||
_In_ void* /* Context */,
|
||||
_In_ QUIC_RECV_DATAGRAM* RecvBufferChain
|
||||
)
|
||||
{
|
||||
QuicDataPathBindingReturnRecvDatagrams(RecvBufferChain);
|
||||
}
|
||||
|
||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||
_Function_class_(QUIC_DATAPATH_UNREACHABLE_CALLBACK)
|
||||
static void
|
||||
DrillUdpUnreachCallback(
|
||||
_In_ QUIC_DATAPATH_BINDING* /* Binding */,
|
||||
_In_ void* /* Context */,
|
||||
_In_ const QUIC_ADDR* /* RemoteAddress */
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
DrillSender() : Datapath(nullptr), Binding(nullptr) {}
|
||||
|
||||
~DrillSender() {
|
||||
if (Binding != nullptr) {
|
||||
QuicDataPathBindingDelete(Binding);
|
||||
}
|
||||
|
||||
if (Datapath != nullptr) {
|
||||
QuicDataPathUninitialize(Datapath);
|
||||
}
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
Initialize(
|
||||
_In_ const char* HostName,
|
||||
_In_ QUIC_ADDRESS_FAMILY Family,
|
||||
_In_ uint16_t NetworkPort
|
||||
)
|
||||
{
|
||||
QUIC_ADDR ServerAddress;
|
||||
QUIC_STATUS Status =
|
||||
QuicDataPathInitialize(
|
||||
0,
|
||||
DrillUdpRecvCallback,
|
||||
DrillUdpUnreachCallback,
|
||||
&Datapath);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("Datapath init failed 0x%x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ServerAddress.si_family = Family;
|
||||
|
||||
Status =
|
||||
QuicDataPathResolveAddress(
|
||||
Datapath,
|
||||
HostName,
|
||||
&ServerAddress);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("Address resolution failed 0x%x", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Family == AF_INET) {
|
||||
ServerAddress.Ipv4.sin_port = NetworkPort;
|
||||
} else {
|
||||
ServerAddress.Ipv6.sin6_port = NetworkPort;
|
||||
}
|
||||
|
||||
Status =
|
||||
QuicDataPathBindingCreate(
|
||||
Datapath,
|
||||
nullptr,
|
||||
&ServerAddress,
|
||||
this,
|
||||
&Binding);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("Binding failed: 0x%x", Status);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
Send(
|
||||
_In_ const DrillBuffer* PacketBuffer
|
||||
)
|
||||
{
|
||||
QUIC_STATUS Status = QUIC_STATUS_SUCCESS;
|
||||
QUIC_FRE_ASSERT(PacketBuffer->size() <= UINT16_MAX);
|
||||
const uint16_t DatagramLength = (uint16_t) PacketBuffer->size();
|
||||
|
||||
QUIC_DATAPATH_SEND_CONTEXT* SendContext =
|
||||
QuicDataPathBindingAllocSendContext(Binding, DatagramLength);
|
||||
|
||||
QUIC_BUFFER* SendBuffer =
|
||||
QuicDataPathBindingAllocSendDatagram(SendContext, DatagramLength);
|
||||
|
||||
if (SendBuffer == nullptr) {
|
||||
TEST_FAILURE("Buffer null");
|
||||
Status = QUIC_STATUS_OUT_OF_MEMORY;
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Copy test packet into SendBuffer.
|
||||
memcpy(SendBuffer->Buffer, PacketBuffer->data(), DatagramLength);
|
||||
|
||||
QuicDataPathBindingSendTo(
|
||||
Binding,
|
||||
&ServerAddress,
|
||||
SendContext);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
bool
|
||||
QuicDrillInitialPacketFailureTest(
|
||||
_In_ QUIC_ADDRESS_FAMILY QuicAddrFamily,
|
||||
_In_ const DrillInitialPacketDescriptor& InitialPacketDescriptor
|
||||
)
|
||||
{
|
||||
QUIC_STATUS Status;
|
||||
QUIC_LISTENER_STATISTICS Stats;
|
||||
uint64_t DroppedPacketsBefore;
|
||||
uint64_t DroppedPacketsAfter;
|
||||
uint8_t Disabled = FALSE;
|
||||
|
||||
QuicAddr ServerAddress(QuicAddrFamily);
|
||||
MsQuicRegistration QuicDrillRegistration;
|
||||
if (!QuicDrillRegistration.IsValid()) {
|
||||
TEST_FAILURE("QuicDrillRegistration not valid!");
|
||||
return false;
|
||||
}
|
||||
DrillSender Sender;
|
||||
|
||||
Status =
|
||||
MsQuic->SetParam(
|
||||
QuicDrillRegistration,
|
||||
QUIC_PARAM_LEVEL_REGISTRATION,
|
||||
QUIC_PARAM_REGISTRATION_ENCRYPTION,
|
||||
sizeof(Disabled),
|
||||
&Disabled);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("Failed to disable encryption for test. 0x%x", Status);
|
||||
return false;
|
||||
}
|
||||
|
||||
MsQuicSession Session(QuicDrillRegistration);
|
||||
if (!Session.IsValid()) {
|
||||
TEST_FAILURE("Session not valid!");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
//
|
||||
// Start the server.
|
||||
//
|
||||
TestListener Listener(Session.Handle, QuicDrillConnectionCallbackHandler);
|
||||
|
||||
Status = Listener.Start(&ServerAddress.SockAddr);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("ListenerStart failed, 0x%x.", Status);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Get server address (port) here.
|
||||
//
|
||||
Status = Listener.GetLocalAddr(ServerAddress);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("MsQuic->GetParam failed, 0x%x.", Status);
|
||||
return false;
|
||||
}
|
||||
|
||||
Status =
|
||||
Sender.Initialize(
|
||||
QUIC_LOCALHOST_FOR_AF(QuicAddrFamily),
|
||||
QuicAddrFamily,
|
||||
(QuicAddrFamily == AF_INET) ?
|
||||
ServerAddress.SockAddr.Ipv4.sin_port :
|
||||
ServerAddress.SockAddr.Ipv6.sin6_port);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DrillBuffer PacketBuffer = InitialPacketDescriptor.write();
|
||||
|
||||
Status = Listener.GetStatistics(Stats);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("Get Listener statistics before test failed, 0x%x.", Status);
|
||||
return false;
|
||||
}
|
||||
DroppedPacketsBefore = Stats.Binding.Recv.DroppedPackets;
|
||||
|
||||
//
|
||||
// Send test packet to the server.
|
||||
//
|
||||
Status = Sender.Send(&PacketBuffer);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Generously wait for server to process packet.
|
||||
//
|
||||
QuicSleep(100);
|
||||
|
||||
Status = Listener.GetStatistics(Stats);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
TEST_FAILURE("Get Listener statistics after test failed, 0x%x.", Status);
|
||||
return false;
|
||||
}
|
||||
DroppedPacketsAfter = Stats.Binding.Recv.DroppedPackets;
|
||||
|
||||
//
|
||||
// Validate the server rejected the packet just sent.
|
||||
// N.B. Could fail if the server has other packets sent to it accidentally.
|
||||
//
|
||||
if (DroppedPacketsAfter - DroppedPacketsBefore != 1) {
|
||||
TEST_FAILURE("DroppedPacketsAfter - DroppedPacketsBefore not equal to 1");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define VALID_CID_LENGTH_SHORT 8
|
||||
#define VALID_CID_LENGTH_LONG 20
|
||||
#define INVALID_CID_LENGTH_SHORT 7
|
||||
#define INVALID_CID_LENGTH_LONG 21
|
||||
|
||||
void
|
||||
QuicDrillTestInitialCid(
|
||||
_In_ int Family,
|
||||
_In_ bool Source, // or Dest
|
||||
_In_ bool ValidActualLength, // or invalid
|
||||
_In_ bool Short, // or long
|
||||
_In_ bool ValidLengthField // or invalid
|
||||
)
|
||||
{
|
||||
/**
|
||||
* SourceCid valid length, but longer than valid length field indicates.
|
||||
* SourceCid valid length, but shorter than valid length field indicates.
|
||||
* SourceCid valid length, but shorter than invalid length field.
|
||||
* SourceCid valid length, but longer than invalid length field.
|
||||
* SourceCid invalidly short, but length field indicates valid length.
|
||||
* SourceCid invalidly long, but length field indicates valid length.
|
||||
* SourceCid invalidly short, and length field matches.
|
||||
* SourceCid invalidly long, and length field matches.
|
||||
* (Ditto for DestCid)
|
||||
|
||||
(source, dest), [(valid length, invalid length), (valid length field, invalid length field)], (short, long)
|
||||
|
||||
*/
|
||||
|
||||
uint8_t ActualCidLength;
|
||||
uint8_t CidLengthField;
|
||||
|
||||
QUIC_ADDRESS_FAMILY QuicAddrFamily = (Family == 4) ? AF_INET : AF_INET6;
|
||||
DrillInitialPacketDescriptor InitialDescriptor;
|
||||
|
||||
// Calculate the test parameters
|
||||
if (ValidActualLength) {
|
||||
if (Short) {
|
||||
ActualCidLength = VALID_CID_LENGTH_SHORT;
|
||||
} else {
|
||||
ActualCidLength = VALID_CID_LENGTH_LONG;
|
||||
}
|
||||
|
||||
if (ValidLengthField) {
|
||||
// When both lengths are valid, we want to make the field different
|
||||
// than the actual length so they don't agree.
|
||||
if (!Short) {
|
||||
CidLengthField = VALID_CID_LENGTH_SHORT;
|
||||
} else {
|
||||
CidLengthField = VALID_CID_LENGTH_LONG;
|
||||
}
|
||||
} else {
|
||||
// When the length field is invalid, but the actual length valid,
|
||||
// we want to make the length field very invalid.
|
||||
if (!Short) {
|
||||
CidLengthField = INVALID_CID_LENGTH_SHORT;
|
||||
} else {
|
||||
CidLengthField = INVALID_CID_LENGTH_LONG;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Short) {
|
||||
ActualCidLength = INVALID_CID_LENGTH_SHORT;
|
||||
} else {
|
||||
ActualCidLength = INVALID_CID_LENGTH_LONG;
|
||||
}
|
||||
|
||||
if (ValidLengthField) {
|
||||
// When the actual length is invalid, but the length field valid,
|
||||
// make the field the closest valid value.
|
||||
if (Short) {
|
||||
CidLengthField = VALID_CID_LENGTH_SHORT;
|
||||
} else {
|
||||
CidLengthField = VALID_CID_LENGTH_LONG;
|
||||
}
|
||||
} else {
|
||||
// When both length field and actual length are invalid, make the
|
||||
// values agree.
|
||||
if (Short) {
|
||||
CidLengthField = INVALID_CID_LENGTH_SHORT;
|
||||
} else {
|
||||
CidLengthField = INVALID_CID_LENGTH_LONG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrillBuffer TestCid;
|
||||
for (int value = 0; value < ActualCidLength; value++) {
|
||||
TestCid.push_back(0xff - (uint8_t) value); // Make this Cid look different from the default one.
|
||||
}
|
||||
|
||||
if (Source) {
|
||||
InitialDescriptor.SourceCid.clear();
|
||||
InitialDescriptor.SourceCid.insert(InitialDescriptor.SourceCid.begin(), TestCid.begin(), TestCid.end());
|
||||
InitialDescriptor.SourceCidLen = &CidLengthField;
|
||||
} else {
|
||||
InitialDescriptor.DestCid.clear();
|
||||
InitialDescriptor.DestCid.insert(InitialDescriptor.DestCid.begin(), TestCid.begin(), TestCid.end());
|
||||
InitialDescriptor.DestCidLen = &CidLengthField;
|
||||
}
|
||||
|
||||
QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor);
|
||||
}
|
||||
|
||||
void
|
||||
QuicDrillTestInitialToken(
|
||||
_In_ int Family
|
||||
)
|
||||
{
|
||||
QUIC_ADDRESS_FAMILY QuicAddrFamily = (Family == 4) ? AF_INET : AF_INET6;
|
||||
const uint8_t GeneratedTokenLength = 20;
|
||||
uint64_t TokenLen;
|
||||
|
||||
// Token length is larger than actual token.
|
||||
{
|
||||
DrillInitialPacketDescriptor InitialDescriptor;
|
||||
|
||||
for (uint8_t TokenValue = 0; TokenValue < GeneratedTokenLength; TokenValue++) {
|
||||
InitialDescriptor.Token.push_back(TokenValue);
|
||||
}
|
||||
TokenLen = GeneratedTokenLength + 1;
|
||||
InitialDescriptor.TokenLen = &TokenLen;
|
||||
|
||||
if (!QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Token length is shorter than actual token.
|
||||
{
|
||||
DrillInitialPacketDescriptor InitialDescriptor;
|
||||
|
||||
for (uint8_t TokenValue = 0; TokenValue < GeneratedTokenLength; TokenValue++) {
|
||||
InitialDescriptor.Token.push_back(TokenValue);
|
||||
}
|
||||
TokenLen = GeneratedTokenLength - 1;
|
||||
InitialDescriptor.TokenLen = &TokenLen;
|
||||
|
||||
if (!QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Token length is non-zero and token is not present.
|
||||
{
|
||||
DrillInitialPacketDescriptor InitialDescriptor;
|
||||
|
||||
TokenLen = 1;
|
||||
InitialDescriptor.TokenLen = &TokenLen;
|
||||
|
||||
if (!QuicDrillInitialPacketFailureTest(QuicAddrFamily, InitialDescriptor)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -78,6 +78,21 @@ TestListener::GetLocalAddr(
|
|||
&localAddr.SockAddr);
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
TestListener::GetStatistics(
|
||||
_Out_ QUIC_LISTENER_STATISTICS &stats
|
||||
)
|
||||
{
|
||||
uint32_t Size = sizeof(stats);
|
||||
return
|
||||
MsQuic->GetParam(
|
||||
QuicListener,
|
||||
QUIC_PARAM_LEVEL_LISTENER,
|
||||
QUIC_PARAM_LISTENER_STATS,
|
||||
&Size,
|
||||
&stats);
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
TestListener::HandleListenerEvent(
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
|
|
|
@ -92,4 +92,5 @@ public:
|
|||
//
|
||||
|
||||
QUIC_STATUS GetLocalAddr(_Out_ QuicAddr &localAddr);
|
||||
QUIC_STATUS GetStatistics(_Out_ QUIC_LISTENER_STATISTICS &stats);
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче