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_DWORD = 1;
const uint32_t FIELD_TYPE_DATA = 2; const uint32_t FIELD_TYPE_DATA = 2;
const uint32_t FIELD_TYPE_WSTRING = 3; const uint32_t FIELD_TYPE_WSTRING = 3;
const uint32_t FIELD_TYPE_GUID = 4;
PacketSerialiser::PacketSerialiser(uint32_t type) 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; ((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) PacketDeserialiser::PacketDeserialiser(const void *serialised_packet, size_t packet_size)
{ {
header = (const TLVChunk*)(serialised_packet); 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; return header->type;
} }
size_t PacketDeserialiser::num_fields() size_t PacketDeserialiser::num_fields() const
{ {
return fields.size(); return fields.size();
} }
bool PacketDeserialiser::is_null(size_t index) bool PacketDeserialiser::is_null(size_t index) const
{ {
if(fields.size() <= index) if(fields.size() <= index)
{ {
@ -125,7 +138,7 @@ bool PacketDeserialiser::is_null(size_t index)
return (fields[index]->type == FIELD_TYPE_NULL); 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) if(fields.size() <= index)
{ {
@ -145,7 +158,7 @@ DWORD PacketDeserialiser::get_dword(size_t index)
return *(DWORD*)(fields[index]->value); 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) 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)); 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) 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))); 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_dword(DWORD value);
void append_data(const void *data, size_t size); void append_data(const void *data, size_t size);
void append_wstring(const std::wstring &string); void append_wstring(const std::wstring &string);
void append_guid(const GUID &guid);
}; };
class PacketDeserialiser class PacketDeserialiser
@ -53,13 +54,14 @@ class PacketDeserialiser
PacketDeserialiser(const void *serialised_packet, size_t packet_size); PacketDeserialiser(const void *serialised_packet, size_t packet_size);
uint32_t packet_type(); uint32_t packet_type() const;
size_t num_fields(); size_t num_fields() const;
bool is_null(size_t index); bool is_null(size_t index) const;
DWORD get_dword(size_t index); DWORD get_dword(size_t index) const;
std::pair<const void*,size_t> get_data(size_t index); std::pair<const void*,size_t> get_data(size_t index) const;
std::wstring get_wstring(size_t index); std::wstring get_wstring(size_t index) const;
GUID get_guid(size_t index) const;
}; };
class PacketDeserialiser::Error::Incomplete: public Error 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); 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 { class PacketDeserialiserNull: public PacketDeserialiserTest {
protected: protected:
virtual void SetUp() override virtual void SetUp() override
@ -107,6 +112,12 @@ TEST_F(PacketDeserialiserNull, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField); 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 { class PacketDeserialiserDWORD: public PacketDeserialiserTest {
protected: protected:
virtual void SetUp() override virtual void SetUp() override
@ -158,6 +169,12 @@ TEST_F(PacketDeserialiserDWORD, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField); 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 { class PacketDeserialiserData: public PacketDeserialiserTest {
protected: protected:
virtual void SetUp() override virtual void SetUp() override
@ -219,6 +236,12 @@ TEST_F(PacketDeserialiserData, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField); 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 { class PacketDeserialiserWString: public PacketDeserialiserTest {
protected: protected:
virtual void SetUp() override virtual void SetUp() override
@ -272,6 +295,74 @@ TEST_F(PacketDeserialiserWString, GetWString)
EXPECT_THROW({ pd->get_wstring(1); }, PacketDeserialiser::Error::MissingField); 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 { class PacketDeserialiserNullDWORDDataWString: public PacketDeserialiserTest {
protected: protected:
virtual void SetUp() override virtual void SetUp() override
@ -558,3 +649,66 @@ TEST(PacketDeserialiser, OneByteWString)
delete pd; 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); 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) TEST(PacketSerialiser, NullDWORDDataWString)
{ {
PacketSerialiser p(0x1234); PacketSerialiser p(0x1234);