I've been coding a OO server this weekend. There is problem I cannot overcome and have to ask for guidance. I added a lot of comments in the problematic part of code. Quickly on design: pacbuf is an instance of packet_buffer which receives chunks of data and launches the lambda is the packet is complete (first 2 bytes of raw data is the size, so for example 0x06 0x00 0x01 0x22 is a valid packet of length 4). I am completly stuck on handling the parsed packet. I do not know how can I interpret an abstract response from received_packet (which is an abstract base class for any concrete packet). client instance represents one user (think of it as of session). Below I attach the main handler with my comments and example of concrete packets.
void client::process_received_data(const char data[], size_t size)
{
pacbuf.append_raw_data(data, size);
pacbuf.retrieve_packets([this](unsigned short opcode, std::string&& data)
{
//encdec is a class responsible for decrypting valid packet
encdec->decrypt_opcode(opcode); // here i got valid opcode (unique identifier of packet)
encdec->decrypt(data); // here i got decrypted contents
//packet factory returns a std::unique_ptr of abstraction -
// "class received_packet" which contains serialized contents
auto packet = packet_factory->construct(opcode, std::forward<std::string>(data));
if (packet == nullptr)
{
//when opcode is not associated with any implementation of received_packet
logger::get_logger().log_error(login_ + " sent unknown packet");
observer.request_close();
return;
}
try
{
//serialize the string with binary data into clean form
//eventually throw std::underflow_error if not enough data was passed
packet->parse_packet();
//below is the a problem. I somehow need to get response if the packet
//was a login request, or it was registration request,
//or maybe something else - and every packet is handled in different way.
//for example, login should update the "credentials" member of current client.
//But the execute is virtual member of "received_packet" and so its an abstraction again
//of course i can implement it in different ways but i got no idea how to pass it back to client
//i need some mechanism that would take the "received_packet" and knew how to operate on "client"
//so client could for example send back a packet with response to activity
//associated with concrete "received_packet"
packet->execute();
}
catch (std::underflow_error& e)
{
logger::get_logger().log_error(login_ + ' ' + e.what());
observer.request_close();
}
}
);
}
Thats the abstract base
#pragma once
#include <string>
#include "ByteSerializer.hpp"
class received_packet
{
public:
virtual void parse_packet() = 0;
virtual void execute() = 0; // execute should either know what to do or return something
virtual ~received_packet() = default;
protected:
received_packet(const std::string& rawData)
: bs(rawData, 0) {}
byte_serializer bs; // this is my own helper class (irrelevant)
};
And 2 example implementations.
#pragma once
#include "Packet.hpp"
class login_pass_packet : public received_packet
{
public:
login_pass_packet(const std::string& rawData)
:received_packet(rawData) {}
virtual void parse_packet() override;
virtual void execute() override;
private:
char login[20];
char pass[20];
};
void login_pass_packet::parse_packet()
{
bs >> login >> pass;
}
void login_pass_packet::execute()
{
//How can i let "client" know that its a login packet? Remember - execute is virtual
}
And it this case i expect different kind of reponse
#pragma once
#include "Packet.hpp"
class key_register_packet : public received_packet
{
public:
key_register_packet(const std::string& rawData)
:received_packet(rawData) {}
virtual void parse_packet() override;
virtual void execute() override;
private:
std::string key;
};
void key_register_packet::parse_packet()
{
bs >> key;
}
void key_register_packet::execute()
{
//and here, execute have to return key register request to client
}
So in the end - i am stuck handling the abstraction. After having concrete packet like login or key request i still see it is as received_packet. Could someone point me in right direction?
Aucun commentaire:
Enregistrer un commentaire