1 module buffer.message; 2 3 import std.traits; 4 import std.typecons; 5 import std.variant; 6 import std.conv : to; 7 8 import cryption.rsa; 9 10 public import buffer.compiler; 11 public import buffer.packet; 12 13 abstract class Message 14 { 15 public: 16 17 alias byte int8; 18 alias ubyte uint8; 19 alias short int16; 20 alias ushort uint16; 21 alias int int32; 22 alias uint uint32; 23 alias long int64; 24 alias ulong uint64; 25 alias float float32; 26 alias double float64; 27 //bool 28 //char 29 //string 30 31 @property ushort messageId() 32 { 33 return _messageId; 34 } 35 36 @property TypeInfo_Class messageName() 37 { 38 return _messages[_messageId]; 39 } 40 41 static void settings(ushort magic, CryptType crypt = CryptType.NONE, string key = string.init) 42 { 43 assert(crypt == CryptType.NONE || (crypt != CryptType.NONE && key != string.init), 44 "Must specify key when specifying the type of CryptType."); 45 46 _magic = magic; 47 _crypt = crypt; 48 _key = key; 49 50 if (_crypt == CryptType.RSA) 51 { 52 _rsaKey = RSA.decodeKey(Message._key); 53 54 assert(!_rsaKey.isNull, "Rsakey is incorrect."); 55 } 56 } 57 58 static ubyte[] serialize_without_msginfo(Params...)(string method, Params params) 59 { 60 Variant[] t_params; 61 62 foreach(p; params) 63 { 64 t_params ~= Variant(p); 65 } 66 67 return Packet.build(_magic, _crypt, _key, _rsaKey, 0x00, method, t_params); 68 } 69 70 static void getMessageInfo(ubyte[] buffer, out ushort messageId, out TypeInfo_Class messageName, out string method) 71 { 72 Packet.parseInfo(buffer, messageId, method); 73 74 if (messageId in _messages) 75 { 76 messageName = _messages[messageId]; 77 } 78 } 79 80 static Variant[] deserialize(ubyte[] buffer, out ushort messageId, out TypeInfo_Class messageName, out string method) 81 { 82 Variant[] ret = Packet.parse(buffer, _magic, _crypt, _key, _rsaKey, messageId, method); 83 84 if (messageId in _messages) 85 { 86 messageName = _messages[messageId]; 87 } 88 89 return ret; 90 } 91 92 static T deserialize(T)(ubyte[] buffer) if (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message)) 93 { 94 string method; 95 96 return deserialize!T(buffer, method); 97 } 98 99 static T deserialize(T)(ubyte[] buffer, out string method) if (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message)) 100 { 101 ushort messageId; 102 TypeInfo_Class messageName; 103 Variant[] params = deserialize(buffer, messageId, messageName, method); 104 105 if (messageName is null || params == null) 106 return null; 107 108 T message = new T(); 109 if (message.messageId != messageId) 110 { 111 assert(0, "The type T(" ~ T.classinfo.name ~ ") of the incoming template is incorrect. It should be " ~ messageName.name); 112 } 113 114 foreach (i, type; FieldTypeTuple!(T)) 115 { 116 mixin(` 117 message.` ~ FieldNameTuple!T[i] ~ ` = params[` ~ i.to!string ~ `].get!` ~ type.stringof ~ `; 118 `); 119 } 120 121 return message; 122 } 123 124 protected: 125 126 ubyte[] serialize(T)(T message, string method = string.init) if (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message)) 127 { 128 assert(message !is null, "The object to serialize cannot be null."); 129 130 Variant[] params; 131 132 foreach (i, type; FieldTypeTuple!T) 133 { 134 mixin(` 135 params ~= Variant(message.` ~ FieldNameTuple!T[i] ~ `); 136 `); 137 } 138 139 return Packet.build(_magic, _crypt, _key, _rsaKey, message.messageId, method, params); 140 } 141 142 ushort _messageId; 143 __gshared static TypeInfo_Class[ushort] _messages; 144 145 private: 146 147 __gshared static ushort _magic; 148 __gshared static CryptType _crypt; 149 __gshared static string _key; 150 __gshared static Nullable!RSAKeyInfo _rsaKey; 151 }