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 abstract class Message 16 { 17 public: 18 19 alias byte int8; 20 alias ubyte uint8; 21 alias short int16; 22 alias ushort uint16; 23 alias int int32; 24 alias uint uint32; 25 alias long int64; 26 alias ulong uint64; 27 alias float float32; 28 alias double float64; 29 alias real float128; 30 //bool 31 //char 32 //string 33 34 static void settings(ushort magic, CryptType crypt = CryptType.NONE, string key = string.init) 35 { 36 assert((crypt == CryptType.NONE) || (crypt != CryptType.NONE && key != string.init), 37 "Must specify key when specifying the type of CryptType."); 38 39 _magic = magic; 40 _crypt = crypt; 41 _key = key; 42 43 if ((_crypt == CryptType.RSA) || (_crypt == CryptType.RSA_XTEA_MIXIN)) 44 { 45 _rsaKey = RSA.decodeKey(Message._key); 46 47 enforce(!_rsaKey.isNull, "Rsakey is incorrect."); 48 } 49 } 50 51 static void settings(ushort magic, RSAKeyInfo rsaKey, bool mixinXteaMode = false) 52 { 53 _magic = magic; 54 _crypt = mixinXteaMode ? CryptType.RSA_XTEA_MIXIN : CryptType.RSA; 55 _rsaKey = rsaKey; 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, string.init, method, t_params); 68 } 69 70 static void getMessageInfo(ubyte[] buffer, out string name, out string method) 71 { 72 Packet.parseInfo(buffer, name, method); 73 } 74 75 static Variant[] deserialize(ubyte[] buffer, out string name, out string method) 76 { 77 return Packet.parse(buffer, _magic, _crypt, _key, _rsaKey, name, method); 78 } 79 80 static T deserialize(T)(ubyte[] buffer) if (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message)) 81 { 82 string method; 83 84 return deserialize!T(buffer, method); 85 } 86 87 static T deserialize(T)(ubyte[] buffer, out string method) if (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message)) 88 { 89 string name; 90 Variant[] params = deserialize(buffer, name, method); 91 92 if (name == string.init || params == null) 93 { 94 return null; 95 } 96 97 T message = new T(); 98 if (getClassSimpleName(T.classinfo.name) != name) 99 { 100 assert(0, "The type T(" ~ T.classinfo.name ~ ") of the incoming template is incorrect. It should be " ~ name); 101 } 102 103 foreach (i, type; FieldTypeTuple!(T)) 104 { 105 mixin(` 106 message.` ~ FieldNameTuple!T[i] ~ ` = params[` ~ i.to!string ~ `].get!` ~ type.stringof ~ `; 107 `); 108 } 109 110 return message; 111 } 112 113 protected: 114 115 ubyte[] serialize(T)(T message, string method = string.init) if (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message)) 116 { 117 assert(message !is null, "The object to serialize cannot be null."); 118 119 Variant[] params; 120 121 foreach (i, type; FieldTypeTuple!T) 122 { 123 mixin(` 124 params ~= Variant(message.` ~ FieldNameTuple!T[i] ~ `); 125 `); 126 } 127 128 return Packet.build(_magic, _crypt, _key, _rsaKey, getClassSimpleName(T.classinfo.name), method, params); 129 } 130 131 private: 132 133 __gshared static ushort _magic; 134 __gshared static CryptType _crypt; 135 __gshared static string _key; 136 __gshared static Nullable!RSAKeyInfo _rsaKey; 137 }