mirror of https://github.com/SeanOMik/libki.git
protocol: Give exceptions their own error codes
This commit is contained in:
parent
a00f9b5003
commit
6d02bfe06a
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "../../util/Serializable.h"
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
namespace ki
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "../../util/Serializable.h"
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
namespace ki
|
||||
{
|
||||
|
|
|
@ -8,19 +8,57 @@ namespace protocol
|
|||
class runtime_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
runtime_error(std::string message) : std::runtime_error(message) { }
|
||||
explicit runtime_error(std::string message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
class parse_error : public runtime_error
|
||||
{
|
||||
public:
|
||||
parse_error(std::string message) : runtime_error(message) { }
|
||||
enum code
|
||||
{
|
||||
NONE,
|
||||
INVALID_XML_DATA,
|
||||
INVALID_HEADER_DATA,
|
||||
INSUFFICIENT_MESSAGE_DATA,
|
||||
INVALID_MESSAGE_DATA
|
||||
};
|
||||
|
||||
explicit parse_error(std::string message, code error = code::NONE)
|
||||
: runtime_error(message)
|
||||
{
|
||||
m_code = error;
|
||||
}
|
||||
|
||||
code get_error_code() const { return m_code; }
|
||||
private:
|
||||
code m_code;
|
||||
};
|
||||
|
||||
class value_error : public runtime_error
|
||||
{
|
||||
public:
|
||||
value_error(std::string message) : runtime_error(message) { }
|
||||
enum code
|
||||
{
|
||||
NONE,
|
||||
MISSING_FILE,
|
||||
OVERWRITES_LOOKUP,
|
||||
EXCEEDS_LIMIT,
|
||||
|
||||
DML_INVALID_SERVICE,
|
||||
DML_INVALID_PROTOCOL_TYPE,
|
||||
DML_INVALID_MESSAGE_TYPE,
|
||||
DML_INVALID_MESSAGE_NAME
|
||||
};
|
||||
|
||||
explicit value_error(std::string message, code error = code::NONE)
|
||||
: runtime_error(message)
|
||||
{
|
||||
m_code = error;
|
||||
}
|
||||
|
||||
code get_error_code() const { return m_code; }
|
||||
private:
|
||||
code m_code;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -10,7 +10,12 @@ namespace net
|
|||
{
|
||||
enum class InvalidDMLMessageErrorCode
|
||||
{
|
||||
NONE,
|
||||
UNKNOWN,
|
||||
INVALID_HEADER_DATA,
|
||||
INVALID_MESSAGE_DATA,
|
||||
INVALID_SERVICE,
|
||||
INVALID_MESSAGE_TYPE,
|
||||
INSUFFICIENT_ACCESS
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "../../util/Serializable.h"
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
namespace ki
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace control
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Error reading ClientKeepAlive payload: " << e.what();
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_MESSAGE_DATA);
|
||||
}
|
||||
|
||||
m_session_id = session_id->get_value();
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace control
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Error reading ServerKeepAlive payload: " << e.what();
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_MESSAGE_DATA);
|
||||
}
|
||||
|
||||
m_timestamp = timestamp->get_value();
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace control
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Error reading SessionAccept payload: " << e.what();
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_MESSAGE_DATA);
|
||||
}
|
||||
|
||||
m_timestamp = timestamp->get_value();
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace control
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Error reading SessionOffer payload: " << e.what();
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_MESSAGE_DATA);
|
||||
}
|
||||
|
||||
m_session_id = session_id->get_value();
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace dml
|
|||
|
||||
std::ostringstream oss;
|
||||
oss << "Error reading DML message payload: " << e.what();
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_MESSAGE_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,10 +140,12 @@ namespace dml
|
|||
{
|
||||
// Check for mismatches between the header and template
|
||||
if (m_header.get_service_id() != m_template->get_service_id())
|
||||
throw value_error("ServiceID mismatch between MessageHeader and assigned template.");
|
||||
throw value_error("ServiceID mismatch between MessageHeader and assigned template.",
|
||||
value_error::DML_INVALID_SERVICE);
|
||||
if (m_header.get_type() != m_template->get_type())
|
||||
throw value_error("Message Type mismatch between MessageHeader and assigned template.");
|
||||
|
||||
throw value_error("Message Type mismatch between MessageHeader and assigned template.",
|
||||
value_error::DML_INVALID_MESSAGE_TYPE);
|
||||
|
||||
// Read the payload into the record
|
||||
m_record->read_from(istream);
|
||||
}
|
||||
|
@ -155,7 +157,8 @@ namespace dml
|
|||
m_raw_data.resize(size);
|
||||
istream.read(m_raw_data.data(), size);
|
||||
if (istream.fail())
|
||||
throw parse_error("Not enough data was available to read DML message payload.");
|
||||
throw parse_error("Not enough data was available to read DML message payload.",
|
||||
parse_error::INSUFFICIENT_MESSAGE_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace dml
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Error reading MessageHeader: " << e.what();
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_HEADER_DATA);
|
||||
}
|
||||
|
||||
m_service_id = service_id->get_value();
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace dml
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Could not open file: " << filepath;
|
||||
throw value_error(oss.str());
|
||||
throw value_error(oss.str(), value_error::MISSING_FILE);
|
||||
}
|
||||
|
||||
// Load contents into memory
|
||||
|
@ -52,7 +52,7 @@ namespace dml
|
|||
|
||||
std::ostringstream oss;
|
||||
oss << "Failed to parse: " << filepath;
|
||||
throw parse_error(oss.str());
|
||||
throw parse_error(oss.str(), parse_error::INVALID_XML_DATA);
|
||||
}
|
||||
|
||||
// It's safe to allocate the module we're working on now
|
||||
|
@ -118,8 +118,8 @@ namespace dml
|
|||
|
||||
std::ostringstream oss;
|
||||
oss << "Message Module has already been loaded with Service ID ";
|
||||
oss << message_module->get_service_id();
|
||||
throw value_error(oss.str());
|
||||
oss << (uint16_t)message_module->get_service_id();
|
||||
throw value_error(oss.str(), value_error::OVERWRITES_LOOKUP);
|
||||
}
|
||||
|
||||
if (m_protocol_type_map.count(message_module->get_protocol_type()) == 1)
|
||||
|
@ -130,7 +130,7 @@ namespace dml
|
|||
std::ostringstream oss;
|
||||
oss << "Message Module has already been loaded with Protocol Type ";
|
||||
oss << message_module->get_protocol_type();
|
||||
throw value_error(oss.str());
|
||||
throw value_error(oss.str(), value_error::OVERWRITES_LOOKUP);
|
||||
}
|
||||
|
||||
// Add it to our maps
|
||||
|
@ -162,8 +162,8 @@ namespace dml
|
|||
if (!message_module)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No service exists with id: " << service_id;
|
||||
throw value_error(oss.str());
|
||||
oss << "No service exists with id: " << (uint16_t)service_id;
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_SERVICE);
|
||||
}
|
||||
|
||||
return message_module->create_message(message_type);
|
||||
|
@ -175,8 +175,8 @@ namespace dml
|
|||
if (!message_module)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No service exists with id: " << service_id;
|
||||
throw value_error(oss.str());
|
||||
oss << "No service exists with id: " << (uint16_t)service_id;
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_SERVICE);
|
||||
}
|
||||
|
||||
return message_module->create_message(message_name);
|
||||
|
@ -189,7 +189,7 @@ namespace dml
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No service exists with protocol type: " << protocol_type;
|
||||
throw value_error(oss.str());
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_PROTOCOL_TYPE);
|
||||
}
|
||||
|
||||
return message_module->create_message(message_type);
|
||||
|
@ -202,7 +202,7 @@ namespace dml
|
|||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No service exists with protocol type: " << protocol_type;
|
||||
throw value_error(oss.str());
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_PROTOCOL_TYPE);
|
||||
}
|
||||
|
||||
return message_module->create_message(message_name);
|
||||
|
@ -212,28 +212,35 @@ namespace dml
|
|||
{
|
||||
// Read the message header
|
||||
MessageHeader header;
|
||||
try
|
||||
{
|
||||
header.read_from(istream);
|
||||
}
|
||||
catch (parse_error &e)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
header.read_from(istream);
|
||||
|
||||
// Get the message module that uses the specified service id
|
||||
auto *message_module = get_module(header.get_service_id());
|
||||
if (!message_module)
|
||||
return nullptr;
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No service exists with id: " << (uint16_t)header.get_service_id();
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_SERVICE);
|
||||
}
|
||||
|
||||
// Get the message template for this message type
|
||||
auto *message_template = message_module->get_message_template(header.get_type());
|
||||
if (!message_template)
|
||||
return nullptr;
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No message exists with type: " << (uint16_t)header.get_service_id();
|
||||
oss << "(service=" << message_module->get_protocol_type() << ")";
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_MESSAGE_TYPE);
|
||||
}
|
||||
|
||||
// Make sure that the size specified is enough to read this message
|
||||
if (header.get_message_size() < message_template->get_record().get_size())
|
||||
return nullptr;
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "No message exists with type: " << (uint16_t)header.get_service_id();
|
||||
oss << "(service=" << message_module->get_protocol_type() << ")";
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_MESSAGE_TYPE);
|
||||
}
|
||||
|
||||
// Create a new Message from the template
|
||||
auto *message = new Message(message_template);
|
||||
|
@ -244,7 +251,7 @@ namespace dml
|
|||
catch (ki::dml::parse_error &e)
|
||||
{
|
||||
delete message;
|
||||
return nullptr;
|
||||
throw parse_error("Failed to read DML message payload.", parse_error::INVALID_MESSAGE_DATA);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ namespace dml
|
|||
|
||||
// Make sure we haven't overflowed
|
||||
if (message_type == 0)
|
||||
throw value_error("Module has more than 254 messages.");
|
||||
throw value_error("Module has more than 254 messages.", value_error::EXCEEDS_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ namespace dml
|
|||
std::ostringstream oss;
|
||||
oss << "No message exists with type: " << message_type;
|
||||
oss << "(service=" << m_protocol_type << ")";
|
||||
throw value_error(oss.str());
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_MESSAGE_TYPE);
|
||||
}
|
||||
|
||||
return message_template->create_message();
|
||||
|
@ -161,7 +161,7 @@ namespace dml
|
|||
std::ostringstream oss;
|
||||
oss << "No message exists with name: " << message_name;
|
||||
oss << "(service=" << m_protocol_type << ")";
|
||||
throw value_error(oss.str());
|
||||
throw value_error(oss.str(), value_error::DML_INVALID_MESSAGE_NAME);
|
||||
}
|
||||
|
||||
return message_template->create_message();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "ki/protocol/net/DMLSession.h"
|
||||
#include "ki/protocol/exception.h"
|
||||
|
||||
namespace ki
|
||||
{
|
||||
|
@ -22,10 +23,45 @@ namespace net
|
|||
void DMLSession::on_application_message(const PacketHeader& header)
|
||||
{
|
||||
// Attempt to create a Message instance from the data in the stream
|
||||
const auto *message = m_manager.message_from_binary(m_data_stream);
|
||||
auto error_code = InvalidDMLMessageErrorCode::NONE;
|
||||
const dml::Message *message = nullptr;
|
||||
try
|
||||
{
|
||||
message = m_manager.message_from_binary(m_data_stream);
|
||||
}
|
||||
catch (parse_error &e)
|
||||
{
|
||||
switch (e.get_error_code())
|
||||
{
|
||||
case parse_error::INVALID_HEADER_DATA:
|
||||
error_code = InvalidDMLMessageErrorCode::INVALID_HEADER_DATA;
|
||||
break;
|
||||
case parse_error::INSUFFICIENT_MESSAGE_DATA:
|
||||
case parse_error::INVALID_MESSAGE_DATA:
|
||||
error_code = InvalidDMLMessageErrorCode::INVALID_MESSAGE_DATA;
|
||||
break;
|
||||
default:
|
||||
error_code = InvalidDMLMessageErrorCode::UNKNOWN;
|
||||
}
|
||||
}
|
||||
catch (value_error &e)
|
||||
{
|
||||
switch (e.get_error_code())
|
||||
{
|
||||
case value_error::DML_INVALID_SERVICE:
|
||||
error_code = InvalidDMLMessageErrorCode::INVALID_SERVICE;
|
||||
break;
|
||||
case value_error::DML_INVALID_MESSAGE_TYPE:
|
||||
error_code = InvalidDMLMessageErrorCode::INVALID_MESSAGE_TYPE;
|
||||
break;
|
||||
default:
|
||||
error_code = InvalidDMLMessageErrorCode::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (!message)
|
||||
{
|
||||
on_invalid_message(InvalidDMLMessageErrorCode::INVALID_MESSAGE_DATA);
|
||||
on_invalid_message(error_code);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,13 +46,16 @@ namespace net
|
|||
{
|
||||
m_control = istream.get() >= 1;
|
||||
if (istream.fail())
|
||||
throw parse_error("Not enough data was available to read packet header. (m_control)");
|
||||
throw parse_error("Not enough data was available to read packet header. (m_control)",
|
||||
parse_error::INVALID_HEADER_DATA);
|
||||
m_opcode = istream.get();
|
||||
if (istream.fail())
|
||||
throw parse_error("Not enough data was available to read packet header. (m_opcode)");
|
||||
throw parse_error("Not enough data was available to read packet header. (m_opcode)",
|
||||
parse_error::INVALID_HEADER_DATA);
|
||||
istream.ignore(2);
|
||||
if (istream.eof())
|
||||
throw parse_error("Not enough data was available to read packet header. (ignored bytes)");
|
||||
throw parse_error("Not enough data was available to read packet header. (ignored bytes)",
|
||||
parse_error::INVALID_HEADER_DATA);
|
||||
}
|
||||
|
||||
size_t PacketHeader::get_size() const
|
||||
|
|
Loading…
Reference in New Issue