- Proper encoding/decoding
This commit is contained in:
parent
8810c1c369
commit
64ba57778a
|
@ -1,16 +1,34 @@
|
|||
module davinci.base.base;
|
||||
|
||||
import msgpack;
|
||||
|
||||
/**
|
||||
* This is the base message type for all messages
|
||||
* in the Renaissance protocol; both client-to-server
|
||||
* and server-to-server
|
||||
*/
|
||||
public abstract class BaseMessage
|
||||
public class BaseMessage
|
||||
{
|
||||
static this()
|
||||
{
|
||||
registerPackHandler!(typeof(this), pkr);
|
||||
registerUnpackHandler!(typeof(this), upkr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current version of the protocol in use
|
||||
*/
|
||||
private ProtocolVersion protocolVersion;
|
||||
|
||||
|
||||
/**
|
||||
* The type of message
|
||||
*/
|
||||
private MessageType type;
|
||||
|
||||
private CommandType commandType;
|
||||
|
||||
private Command command;
|
||||
|
||||
/**
|
||||
* Constructs a new base message of the provided
|
||||
|
@ -19,9 +37,11 @@ public abstract class BaseMessage
|
|||
* Params:
|
||||
* type = the type of message
|
||||
*/
|
||||
this(MessageType type)
|
||||
this(MessageType type, CommandType commandType, Command command)
|
||||
{
|
||||
this.type = type;
|
||||
this.commandType = commandType;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,6 +54,16 @@ public abstract class BaseMessage
|
|||
return type;
|
||||
}
|
||||
|
||||
public CommandType getCommandType()
|
||||
{
|
||||
return commandType;
|
||||
}
|
||||
|
||||
public Command getCommand()
|
||||
{
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes this message into the wire format
|
||||
*
|
||||
|
@ -41,9 +71,48 @@ public abstract class BaseMessage
|
|||
*/
|
||||
public final byte[] encode()
|
||||
{
|
||||
import msgpack;
|
||||
// FIXME: It won't encode nested classes, so enforce each `Command`
|
||||
// ... to have an `encode()` that gives byte array then and we should
|
||||
// ... manually pack here then for that
|
||||
return cast(byte[])pack(this);
|
||||
}
|
||||
|
||||
|
||||
public static void pkr(ref Packer packer, ref BaseMessage message)
|
||||
{
|
||||
packer.pack(message.protocolVersion);
|
||||
packer.pack(message.type);
|
||||
packer.pack(message.commandType);
|
||||
|
||||
/* Payload bytes */
|
||||
byte[] payload = message.getCommand().getEncoded();
|
||||
packer.pack(payload);
|
||||
}
|
||||
|
||||
public static void upkr(ref Unpacker unpacker, ref BaseMessage message)
|
||||
{
|
||||
unpacker.unpack!(ProtocolVersion)(message.protocolVersion);
|
||||
unpacker.unpack!(MessageType)(message.type);
|
||||
unpacker.unpack!(CommandType)(message.commandType);
|
||||
|
||||
byte[] payload;
|
||||
unpacker.unpack!(byte[])(payload);
|
||||
|
||||
// TODO: Now COmmndType check
|
||||
if(message.commandType == CommandType.NOP_COMMAND)
|
||||
{
|
||||
import davinci.c2s.test : TestMessage;
|
||||
message.command = Command.decodeTo!(TestMessage)(payload);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum ProtocolVersion
|
||||
{
|
||||
VERSION_0_PHONK
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,4 +129,38 @@ public enum MessageType
|
|||
* If the message is server-to-server
|
||||
*/
|
||||
SERVER_TO_SERVER
|
||||
}
|
||||
|
||||
|
||||
public abstract class Command
|
||||
{
|
||||
private byte[] data;
|
||||
|
||||
this(byte[] data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public abstract byte[] encode();
|
||||
|
||||
public final byte[] getEncoded()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add a way to enforce that T must be derived from or equal to BaseMessage
|
||||
public static T decodeTo(T)(byte[] data)
|
||||
{
|
||||
// Currently we are using message pack
|
||||
import msgpack;
|
||||
return unpack!(T)(cast(ubyte[])data);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CommandType
|
||||
{
|
||||
NOP_COMMAND
|
||||
}
|
|
@ -2,10 +2,10 @@ module davinci.c2s.client;
|
|||
|
||||
import davinci.base.base : BaseMessage, MessageType;
|
||||
|
||||
public abstract class C2SMessage : BaseMessage
|
||||
{
|
||||
this()
|
||||
{
|
||||
super(MessageType.CLIENT_TO_SERVER);
|
||||
}
|
||||
}
|
||||
// public abstract class C2SMessage : BaseMessage
|
||||
// {
|
||||
// this()
|
||||
// {
|
||||
// super(MessageType.CLIENT_TO_SERVER);
|
||||
// }
|
||||
// }
|
|
@ -4,15 +4,19 @@ import davinci.base.base;
|
|||
import davinci.c2s.client;
|
||||
import msgpack;
|
||||
|
||||
public class TestMessage : C2SMessage
|
||||
public class TestMessage : Command
|
||||
{
|
||||
private string testField = "ABBA";
|
||||
private string testField = "ABBAd";
|
||||
|
||||
this()
|
||||
{
|
||||
import msgpack;
|
||||
registerClass!(typeof(this));
|
||||
super(cast(byte[])pack(this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string getTestField()
|
||||
{
|
||||
return testField;
|
||||
|
@ -26,7 +30,8 @@ version(unittest)
|
|||
|
||||
unittest
|
||||
{
|
||||
BaseMessage exampleMessage = new TestMessage();
|
||||
TestMessage exampleCommand = new TestMessage();
|
||||
BaseMessage exampleMessage = new BaseMessage(MessageType.CLIENT_TO_SERVER, CommandType.NOP_COMMAND, exampleCommand);
|
||||
|
||||
byte[] encodedBytes = exampleMessage.encode();
|
||||
writeln("Encoded bytes: ", encodedBytes);
|
||||
|
@ -38,7 +43,12 @@ unittest
|
|||
//
|
||||
// Here we just go ahead and assume it is a TestMessage
|
||||
// ... kind-of message
|
||||
TestMessage testMessage = unpack!(TestMessage)(cast(ubyte[])encodedBytes);
|
||||
writeln(testMessage.getMessageType());
|
||||
writeln(testMessage.getTestField());
|
||||
BaseMessage testMessage = unpack!(BaseMessage)(cast(ubyte[])encodedBytes);
|
||||
writeln(testMessage);
|
||||
if(testMessage.getCommandType() == CommandType.NOP_COMMAND)
|
||||
{
|
||||
TestMessage testCommand = cast(TestMessage)testMessage.getCommand();
|
||||
writeln(testCommand.getTestField());
|
||||
}
|
||||
|
||||
}
|
|
@ -2,10 +2,10 @@ module davinci.s2s.server;
|
|||
|
||||
import davinci.base.base : BaseMessage, MessageType;
|
||||
|
||||
public class S2SMessage : BaseMessage
|
||||
public class S2SMessage
|
||||
{
|
||||
this()
|
||||
{
|
||||
super(MessageType.SERVER_TO_SERVER);
|
||||
}
|
||||
// this()
|
||||
// {
|
||||
// super(MessageType.SERVER_TO_SERVER);
|
||||
// }
|
||||
}
|
|
@ -1,9 +1,2 @@
|
|||
module davinci.tools;
|
||||
|
||||
// TODO: Add a way to enforce that T must be derived from or equal to BaseMessage
|
||||
public T decodeTo(T)(byte[] data)
|
||||
{
|
||||
// Currently we are using message pack
|
||||
import msgpack;
|
||||
return unpack!(T)(cast(ubyte[])data);
|
||||
}
|
Loading…
Reference in New Issue