1 /* 2 * MsgTrans - Message Transport Framework for DLang. Based on TCP, WebSocket, UDP transmission protocol. 3 * 4 * Copyright (C) 2019 HuntLabs 5 * 6 * Website: https://www.msgtrans.org 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module msgtrans.PacketHeader; 13 14 import msgtrans.MessageBuffer; 15 import std.bitmanip; 16 import std.format; 17 import std.stdint; 18 import hunt.logging; 19 /* -------------------------------------------------------------------------- */ 20 /* protocol */ 21 /* -------------------------------------------------------------------------- */ 22 23 enum int ID_FIELD_LENGTH = uint.sizeof; 24 enum int LENGTH_FIELD_LENGTH = uint.sizeof; 25 enum int COMPRESSION_FIELD_LENGTH = byte.sizeof; 26 // enum int RESERVED_FILED_LENGTH = -; 27 enum int EXTENSION_FIELD_LENGTH = uint.sizeof; 28 enum int PACKET_HEADER_LENGTH = 16; 29 30 enum int MAX_PACKET_SIZE = 4 * 1024 * 1024; // 4M 31 32 // Used to filter the invalid data 33 __gshared uint[] AvaliableMessageIds = []; 34 35 /* -------------------------------------------------------------------------- */ 36 37 // enum SERIALIZATION_TYPE : ushort { 38 // NONE, 39 // JSON, 40 // MSGPACK, 41 // PROTOBUF, 42 // FLATBUFFERS 43 // } 44 45 // enum ENCRYPT_TYPE : ushort { 46 // NONE, 47 // ACE_256, 48 // ACE_512 49 // } 50 51 // enum COMPACTION_TYPE : ushort { 52 // NONE, 53 // L4, 54 // ZIP, 55 // GZIP, 56 // LZMA 57 // } 58 59 /** 60 * 61 */ 62 class PacketHeader 63 { 64 65 private 66 { 67 // Message ID 68 uint _messageID = 0; 69 70 // Message data length 71 uint _messageLength = 0; 72 73 ubyte _compressionType; 74 75 uint _extendLength; 76 // Serialization type including json, protobuf, msgpack, flatbuffers and more 77 // ushort _serializationType = 0; 78 79 // used encrypt algorithm, 0 is none 80 // ushort _encryptType = 0; 81 82 // used compaction algorithm, 0 is none 83 // ushort _compactionType = 0; 84 } 85 86 this(uint id, uint length, uint extlen) 87 { 88 _messageID = id; 89 _messageLength = length; 90 //_compressionType = compr; 91 _extendLength = extlen; 92 } 93 94 static PacketHeader parse(ubyte[] data) 95 { 96 // if (data.length < PACKET_HEADER_LENGTH) 97 // { 98 // return null; 99 // } 100 // NOTE: Byte ordering is big endian. 101 version(HUNT_DEBUG) logInfof("ID_FIELD_LENGTH: %d",ID_FIELD_LENGTH); 102 ubyte[ID_FIELD_LENGTH] idBytes = data[0..ID_FIELD_LENGTH]; 103 uint id = bigEndianToNative!(uint)(idBytes); 104 if(id == 0) { 105 return null; 106 } 107 108 enum LengthStart = ID_FIELD_LENGTH; 109 enum LengthEnd = ID_FIELD_LENGTH + LENGTH_FIELD_LENGTH; 110 ubyte[LENGTH_FIELD_LENGTH] lengthBytes = data[LengthStart..LengthEnd]; 111 uint length = bigEndianToNative!uint(lengthBytes); 112 113 114 enum LengthCompression = LengthEnd + COMPRESSION_FIELD_LENGTH; 115 ubyte[COMPRESSION_FIELD_LENGTH] compression = data[LengthEnd .. LengthCompression]; 116 ubyte ucompre = (bigEndianToNative!ubyte(compression)); 117 118 enum LengthExtend = LengthCompression + EXTENSION_FIELD_LENGTH; 119 ubyte[EXTENSION_FIELD_LENGTH] ex = data[LengthCompression .. LengthExtend]; 120 uint extendLen = bigEndianToNative!uint(ex); 121 122 return new PacketHeader(id, length ,extendLen); 123 } 124 125 static ubyte[] encode(MessageBuffer message) { 126 ubyte[ID_FIELD_LENGTH] h0 = nativeToBigEndian(message.id); 127 ubyte[LENGTH_FIELD_LENGTH] h1 = nativeToBigEndian(cast(int)(message.data.length)); 128 ubyte[COMPRESSION_FIELD_LENGTH] h2 = message.compression; 129 ubyte[EXTENSION_FIELD_LENGTH] h3; 130 if (message.hasExtend) 131 { 132 h3 = nativeToBigEndian(message.extendLength); 133 }else 134 { 135 h3 = nativeToBigEndian(0); 136 } 137 138 139 ubyte[] buffer = new ubyte[PACKET_HEADER_LENGTH]; 140 buffer[0..ID_FIELD_LENGTH] = h0[]; 141 142 int lengthStart = ID_FIELD_LENGTH; 143 int lengthEnd1 = lengthStart + LENGTH_FIELD_LENGTH; 144 145 buffer[lengthStart .. lengthEnd1] = h1[]; 146 147 int lengthEnd2 = lengthEnd1 + COMPRESSION_FIELD_LENGTH; 148 149 buffer[lengthEnd1 .. lengthEnd2] = h2[]; 150 151 int lengthEnd3 = lengthEnd2 + EXTENSION_FIELD_LENGTH; 152 153 buffer[lengthEnd2 .. lengthEnd3] = h3[]; 154 155 return buffer; 156 } 157 158 ubyte[] data() 159 { 160 ubyte[ID_FIELD_LENGTH] h0 = nativeToBigEndian(_messageID); 161 ubyte[LENGTH_FIELD_LENGTH] h1 = nativeToBigEndian(_messageLength); 162 163 ubyte[] data = h0 ~ h1; 164 if (data.length < PACKET_HEADER_LENGTH) 165 { 166 ubyte[] h3 = new ubyte[PACKET_HEADER_LENGTH - data.length]; 167 return data ~ h3; 168 } 169 170 return data; 171 } 172 173 uint messageId() 174 { 175 return _messageID; 176 } 177 178 long messageLength() 179 { 180 return _messageLength; 181 } 182 183 uint extendLength() 184 { 185 return _extendLength; 186 } 187 188 override string toString() { 189 return format("id: %d, length: %d _extendLength: %d", _messageID, _messageLength,_extendLength); 190 } 191 }