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