1
0
mirror of https://github.com/solemnwarning/directplay-lite synced 2024-12-30 16:45:37 +01:00

Implement serialising of GUIDs in packets.

This commit is contained in:
Daniel Collins 2018-09-11 21:53:00 +01:00
parent 971119edae
commit 286c86ea46
4 changed files with 228 additions and 12 deletions

View File

@ -10,6 +10,7 @@ const uint32_t FIELD_TYPE_NULL = 0;
const uint32_t FIELD_TYPE_DWORD = 1;
const uint32_t FIELD_TYPE_DATA = 2;
const uint32_t FIELD_TYPE_WSTRING = 3;
const uint32_t FIELD_TYPE_GUID = 4;
PacketSerialiser::PacketSerialiser(uint32_t type)
{
@ -77,6 +78,18 @@ void PacketSerialiser::append_wstring(const std::wstring &string)
((TLVChunk*)(sbuf.data()))->value_length += sizeof(header) + string_bytes;
}
void PacketSerialiser::append_guid(const GUID &guid)
{
TLVChunk header;
header.type = FIELD_TYPE_GUID;
header.value_length = sizeof(GUID);
sbuf.insert(sbuf.end(), (unsigned char*)(&header), (unsigned char*)(&header + 1));
sbuf.insert(sbuf.end(), (unsigned char*)(&guid), (unsigned char*)(&guid) + sizeof(GUID));
((TLVChunk*)(sbuf.data()))->value_length += sizeof(header) + sizeof(GUID);
}
PacketDeserialiser::PacketDeserialiser(const void *serialised_packet, size_t packet_size)
{
header = (const TLVChunk*)(serialised_packet);
@ -105,17 +118,17 @@ PacketDeserialiser::PacketDeserialiser(const void *serialised_packet, size_t pac
}
}
uint32_t PacketDeserialiser::packet_type()
uint32_t PacketDeserialiser::packet_type() const
{
return header->type;
}
size_t PacketDeserialiser::num_fields()
size_t PacketDeserialiser::num_fields() const
{
return fields.size();
}
bool PacketDeserialiser::is_null(size_t index)
bool PacketDeserialiser::is_null(size_t index) const
{
if(fields.size() <= index)
{
@ -125,7 +138,7 @@ bool PacketDeserialiser::is_null(size_t index)
return (fields[index]->type == FIELD_TYPE_NULL);
}
DWORD PacketDeserialiser::get_dword(size_t index)
DWORD PacketDeserialiser::get_dword(size_t index) const
{
if(fields.size() <= index)
{
@ -145,7 +158,7 @@ DWORD PacketDeserialiser::get_dword(size_t index)
return *(DWORD*)(fields[index]->value);
}
std::pair<const void*,size_t> PacketDeserialiser::get_data(size_t index)
std::pair<const void*,size_t> PacketDeserialiser::get_data(size_t index) const
{
if(fields.size() <= index)
{
@ -160,7 +173,7 @@ std::pair<const void*,size_t> PacketDeserialiser::get_data(size_t index)
return std::make_pair<const void*, size_t>((const void*)(fields[index]->value), (size_t)(fields[index]->value_length));
}
std::wstring PacketDeserialiser::get_wstring(size_t index)
std::wstring PacketDeserialiser::get_wstring(size_t index) const
{
if(fields.size() <= index)
{
@ -179,3 +192,23 @@ std::wstring PacketDeserialiser::get_wstring(size_t index)
return std::wstring((const wchar_t*)(fields[index]->value), (fields[index]->value_length / sizeof(wchar_t)));
}
GUID PacketDeserialiser::get_guid(size_t index) const
{
if(fields.size() <= index)
{
throw Error::MissingField();
}
if(fields[index]->type != FIELD_TYPE_GUID)
{
throw Error::TypeMismatch();
}
if(fields[index]->value_length != sizeof(GUID))
{
throw Error::Malformed();
}
return *(GUID*)(fields[index]->value);
}

View File

@ -30,6 +30,7 @@ class PacketSerialiser
void append_dword(DWORD value);
void append_data(const void *data, size_t size);
void append_wstring(const std::wstring &string);
void append_guid(const GUID &guid);
};
class PacketDeserialiser
@ -53,13 +54,14 @@ class PacketDeserialiser
PacketDeserialiser(const void *serialised_packet, size_t packet_size);
uint32_t packet_type();
size_t num_fields();
uint32_t packet_type() const;
size_t num_fields() const;
bool is_null(size_t index);
DWORD get_dword(size_t index);
std::pair<const void*,size_t> get_data(size_t index);
std::wstring get_wstring(size_t index);
bool is_null(size_t index) const;
DWORD get_dword(size_t index) const;
std::pair<const void*,size_t> get_data(size_t index) const;
std::wstring get_wstring(size_t index) const;
GUID get_guid(size_t index) const;
};
class PacketDeserialiser::Error::Incomplete: public Error

View File

@ -57,6 +57,11 @@ TEST_F(PacketDeserialiserEmpty, GetWString)
EXPECT_THROW({ pd->get_wstring(0); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserEmpty, GetGUID)
{
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::MissingField);
}
class PacketDeserialiserNull: public PacketDeserialiserTest {
protected:
virtual void SetUp() override
@ -107,6 +112,12 @@ TEST_F(PacketDeserialiserNull, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserNull, GetGUID)
{
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_guid(1); }, PacketDeserialiser::Error::MissingField);
}
class PacketDeserialiserDWORD: public PacketDeserialiserTest {
protected:
virtual void SetUp() override
@ -158,6 +169,12 @@ TEST_F(PacketDeserialiserDWORD, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserDWORD, GetGUID)
{
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_guid(1); }, PacketDeserialiser::Error::MissingField);
}
class PacketDeserialiserData: public PacketDeserialiserTest {
protected:
virtual void SetUp() override
@ -219,6 +236,12 @@ TEST_F(PacketDeserialiserData, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserData, GetGUID)
{
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_guid(1); }, PacketDeserialiser::Error::MissingField);
}
class PacketDeserialiserWString: public PacketDeserialiserTest {
protected:
virtual void SetUp() override
@ -272,6 +295,74 @@ TEST_F(PacketDeserialiserWString, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserWString, GetGUID)
{
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_guid(1); }, PacketDeserialiser::Error::MissingField);
}
class PacketDeserialiserGUID: public PacketDeserialiserTest {
protected:
virtual void SetUp() override
{
static const unsigned char RAW[] = {
0x06, 0x00, 0x00, 0x00, /* type */
0x18, 0x00, 0x00, 0x00, /* value_length */
0x04, 0x00, 0x00, 0x00, /* type */
0x10, 0x00, 0x00, 0x00, /* value_length */
0x01, 0x23, 0x45, 0x67, /* value */
0x89, 0x1A, 0xBC, 0xDE,
0xF0, 0x12, 0x34, 0x56,
0x78, 0x91, 0xAB, 0xCD,
};
ASSERT_NO_THROW({ pd = new PacketDeserialiser(RAW, sizeof(RAW)); });
}
};
TEST_F(PacketDeserialiserGUID, Type)
{
EXPECT_EQ(pd->packet_type(), (uint32_t)(6));
}
TEST_F(PacketDeserialiserGUID, NumFields)
{
EXPECT_EQ(pd->num_fields(), (size_t)(1));
}
TEST_F(PacketDeserialiserGUID, IsNull)
{
EXPECT_NO_THROW({ EXPECT_EQ(pd->is_null(0), false); });
EXPECT_THROW({ pd->is_null(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserGUID, GetDWORD)
{
EXPECT_THROW({ pd->get_dword(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_dword(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserGUID, GetData)
{
EXPECT_THROW({ pd->get_data(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_data(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserGUID, GetWString)
{
EXPECT_THROW({ pd->get_wstring(0); }, PacketDeserialiser::Error::TypeMismatch);
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField);
}
TEST_F(PacketDeserialiserGUID, GetGUID)
{
const GUID EXPECT = { 0x67452301, 0x1A89, 0xDEBC, { 0xF0, 0x12, 0x34, 0x56, 0x78, 0x91, 0xAB, 0xCD } };
EXPECT_NO_THROW({ EXPECT_EQ(pd->get_guid(0), EXPECT); });
EXPECT_THROW({ pd->get_guid(1); }, PacketDeserialiser::Error::MissingField);
}
class PacketDeserialiserNullDWORDDataWString: public PacketDeserialiserTest {
protected:
virtual void SetUp() override
@ -558,3 +649,66 @@ TEST(PacketDeserialiser, OneByteWString)
delete pd;
}
TEST(PacketDeserialiser, ZeroLengthGUID)
{
const unsigned char RAW[] = {
0x01, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
PacketDeserialiser *pd = NULL;
ASSERT_NO_THROW({ pd = new PacketDeserialiser(RAW, sizeof(RAW)); });
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::Malformed);
delete pd;
}
TEST(PacketDeserialiser, UndersizeGUID)
{
static const unsigned char RAW[] = {
0x06, 0x00, 0x00, 0x00, /* type */
0x17, 0x00, 0x00, 0x00, /* value_length */
0x04, 0x00, 0x00, 0x00, /* type */
0x0F, 0x00, 0x00, 0x00, /* value_length */
0x01, 0x23, 0x45, 0x67, /* value */
0x89, 0x1A, 0xBC, 0xDE,
0xF0, 0x12, 0x34, 0x56,
0x78, 0x91, 0xAB,
};
PacketDeserialiser *pd = NULL;
ASSERT_NO_THROW({ pd = new PacketDeserialiser(RAW, sizeof(RAW)); });
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::Malformed);
delete pd;
}
TEST(PacketDeserialiser, OversizeGUID)
{
static const unsigned char RAW[] = {
0x06, 0x00, 0x00, 0x00, /* type */
0x19, 0x00, 0x00, 0x00, /* value_length */
0x04, 0x00, 0x00, 0x00, /* type */
0x11, 0x00, 0x00, 0x00, /* value_length */
0x01, 0x23, 0x45, 0x67, /* value */
0x89, 0x1A, 0xBC, 0xDE,
0xF0, 0x12, 0x34, 0x56,
0x78, 0x91, 0xAB, 0xCD,
0xAA,
};
PacketDeserialiser *pd = NULL;
ASSERT_NO_THROW({ pd = new PacketDeserialiser(RAW, sizeof(RAW)); });
EXPECT_THROW({ pd->get_guid(0); }, PacketDeserialiser::Error::Malformed);
delete pd;
}

View File

@ -124,6 +124,33 @@ TEST(PacketSerialiser, WString)
ASSERT_EQ(got, expect);
}
TEST(PacketSerialiser, GUID)
{
const GUID guid = { 0x67452301, 0x1A89, 0xDEBC, { 0xF0, 0x12, 0x34, 0x56, 0x78, 0x91, 0xAB, 0xCD } };
PacketSerialiser p(0x1234);
p.append_guid(guid);
std::pair<const void*, size_t> raw = p.raw_packet();
const unsigned char EXPECT[] = {
0x34, 0x12, 0x00, 0x00, /* type */
0x18, 0x00, 0x00, 0x00, /* value_length */
0x04, 0x00, 0x00, 0x00, /* type */
0x10, 0x00, 0x00, 0x00, /* value_length */
0x01, 0x23, 0x45, 0x67, /* value */
0x89, 0x1A, 0xBC, 0xDE,
0xF0, 0x12, 0x34, 0x56,
0x78, 0x91, 0xAB, 0xCD,
};
std::vector<unsigned char> got((unsigned char*)(raw.first), (unsigned char*)(raw.first) + raw.second);
std::vector<unsigned char> expect(EXPECT, EXPECT + sizeof(EXPECT));
ASSERT_EQ(got, expect);
}
TEST(PacketSerialiser, NullDWORDDataWString)
{
PacketSerialiser p(0x1234);