1 module draklib.protocol.reliability; 2 import draklib.core : RakNetInfo; 3 import draklib.bytestream : ByteStream, OutOfBoundsException; 4 import draklib.protocol.packet; 5 import draklib.util; 6 7 /// Header for the Container Packet's PID. 8 /// Information taken from 9 /// https://github.com/OculusVR/RakNet/blob/master/Source/ReliabilityLayer.cpp#L110 10 11 deprecated("Implementation seems to be incorrect") struct ContainerHeader { 12 bool isACK; 13 bool isNACK; 14 bool isPacketPair; 15 bool hasBAndAS; 16 bool isContinuousSend; 17 bool needsBAndAs; 18 bool isValid; 19 20 ubyte encode() { 21 bool[] bits = new bool[8]; 22 bits[0] = isValid; //IsValid 23 if(isACK) { 24 bits[1] = true; 25 bits[2] = hasBAndAS; 26 } else if(isNACK) { 27 bits[1] = false; 28 bits[2] = true; 29 } else { 30 bits[1] = false; 31 bits[2] = false; 32 bits[3] = isPacketPair; 33 bits[4] = isContinuousSend; 34 bits[5] = needsBAndAs; 35 } 36 37 return writeBits(bits); 38 } 39 40 void decode(in ubyte header) { 41 bool[] vals = readBits(header); 42 isValid = vals[0]; 43 isACK = vals[1]; 44 if(isACK) { 45 isNACK = false; 46 isPacketPair = false; 47 hasBAndAS = vals[2]; 48 } else { 49 isNACK = vals[2]; 50 if(isNACK) { 51 isPacketPair = false; 52 } else { 53 isPacketPair = vals[3]; 54 isContinuousSend = vals[4]; 55 needsBAndAs = vals[5]; 56 } 57 } 58 } 59 } 60 61 enum Reliability { 62 UNRELIABLE = 0, 63 UNRELIABLE_SEQUENCED = 1, 64 RELIABLE = 2, 65 RELIABLE_ORDERED = 3, 66 RELIABLE_SEQUENCED = 4, 67 UNRELIABLE_WITH_ACK_RECEIPT = 5, 68 RELIABLE_WITH_ACK_RECEIPT = 6, 69 RELIABLE_ORDERED_WITH_ACK_RECEIPT = 7 70 } 71 72 class AcknowledgePacket : Packet { 73 uint[] nums; 74 75 override { 76 protected void _encode(ref ByteStream stream) { 77 assert(nums !is null, "no sequence numbers provided"); 78 uint count = cast(uint) nums.length; 79 uint records = 0; 80 81 stream.setPosition(3); 82 if(count > 0) { 83 uint pointer = 0; 84 uint start = nums[0]; 85 uint last = nums[0]; 86 87 while(pointer + 1 < count) { 88 uint current = nums[pointer++]; 89 uint diff = current - last; 90 if(diff == 1) { 91 last = current; 92 } else if(diff > 1) { // Skip duplicated packets 93 if(start == last) { 94 stream.writeByte(0); // False 95 stream.writeUInt24_LE(start); 96 start = last = current; 97 } else { 98 stream.writeByte(1); // True 99 stream.writeUInt24_LE(start); 100 stream.writeUInt24_LE(last); 101 start = last = current; 102 } 103 records = records + 1; 104 } 105 } 106 107 if(start == last) { 108 stream.writeByte(1); // True 109 stream.writeUInt24_LE(start); 110 } else { 111 stream.writeByte(0); // False 112 stream.writeUInt24_LE(start); 113 stream.writeUInt24_LE(last); 114 } 115 records = records + 1; 116 } 117 118 uint oldPos = stream.getPosition(); 119 120 stream.setPosition(1); 121 stream.writeUShort(cast(ushort)records); 122 stream.trimTo(oldPos); 123 } 124 125 protected void _decode(ref ByteStream stream) { 126 nums = cast(uint[]) []; 127 128 uint count = stream.readUShort(); 129 uint cnt = 0; 130 for(uint i = 0; i < count && stream.getRemainingLength() > 0 && cnt < 4096; i++) { 131 if(stream.readByte == 0) { 132 uint start = stream.readUInt24_LE(); 133 uint end = stream.readUInt24_LE(); 134 if((end - start) > 512) { 135 end = start + 512; 136 } 137 for(uint c = start; c <= end; c++) { 138 cnt = cnt + 1; 139 nums ~= c; 140 } 141 } else { 142 nums ~= stream.readUInt24_LE(); 143 } 144 } 145 } 146 147 uint getSize() { 148 return 2048; 149 } 150 } 151 } 152 153 class ACKPacket : AcknowledgePacket { 154 override { 155 ubyte getID() { 156 return RakNetInfo.ACK; 157 } 158 } 159 } 160 161 class NACKPacket : AcknowledgePacket { 162 override { 163 ubyte getID() { 164 return RakNetInfo.NACK; 165 } 166 } 167 } 168 169 class ContainerPacket : Packet { 170 //ContainerHeader header; 171 ubyte header; 172 uint sequenceNumber; 173 EncapsulatedPacket[] packets; 174 175 override { 176 void decode(byte[] data) { 177 ByteStream stream = ByteStream.wrap(data); 178 /* 179 header = ContainerHeader(); 180 header.decode(stream.readUByte()); 181 */ 182 header = stream.readUByte(); 183 _decode(stream); 184 } 185 186 protected void _encode(ref ByteStream stream) { 187 stream.writeUInt24_LE(sequenceNumber); 188 foreach(packet; packets) { 189 packet._encode(stream); 190 } 191 } 192 193 protected void _decode(ref ByteStream stream) { 194 packets = cast(EncapsulatedPacket[]) []; 195 196 sequenceNumber = stream.readUInt24_LE(); 197 while(stream.getRemainingLength() > 0) { 198 try { 199 EncapsulatedPacket ep = new EncapsulatedPacket(); 200 ep._decode(stream); 201 packets ~= ep; 202 } catch(OutOfBoundsException e) { 203 debug { 204 import std.stdio; 205 writeln("WARNING: OutofBoundsException while processing ContainerPacket!"); 206 } 207 } 208 } 209 } 210 211 ubyte getID() { 212 return header; 213 } 214 215 uint getSize() { 216 uint size = 4; 217 foreach(pk; packets) { 218 size = size + pk.getSize(); 219 } 220 return size; 221 } 222 } 223 } 224 225 class EncapsulatedPacket : Packet { 226 byte reliability; 227 bool split = false; 228 int messageIndex = -1; 229 int orderIndex = -1; 230 byte orderChannel = -1; 231 uint splitCount; 232 ushort splitID; 233 uint splitIndex; 234 byte[] payload; 235 236 override { 237 protected void _encode(ref ByteStream stream) { 238 stream.writeByte(cast(byte) ((reliability << 5) | (split ? 0b00010000 : 0))); 239 stream.writeUShort(cast(ushort) (payload.length * 8)); 240 if(reliability > 0) { 241 if(reliability >= Reliability.RELIABLE && reliability != Reliability.UNRELIABLE_WITH_ACK_RECEIPT) { 242 stream.writeUInt24_LE(messageIndex); 243 } 244 if(reliability <= Reliability.RELIABLE_SEQUENCED && reliability != Reliability.RELIABLE) { 245 stream.writeUInt24_LE(orderIndex); 246 stream.writeByte(orderChannel); 247 } 248 } 249 if(split) { 250 stream.writeUInt(splitCount); 251 stream.writeUShort(splitID); 252 stream.writeUInt(splitIndex); 253 } 254 255 stream.write(payload); 256 } 257 258 protected void _decode(ref ByteStream stream) { 259 ubyte header = stream.readUByte(); 260 reliability = (header & 0b11100000) >> 5; 261 split = (header & 0b00010000) > 0; 262 //writeln(reliability, " ", split); 263 264 import std.math : ceil; 265 266 ushort len = cast(ushort) ceil(cast(float) stream.readUShort() / 8); 267 if(reliability > 0) { 268 if(reliability >= Reliability.RELIABLE && Reliability.UNRELIABLE_WITH_ACK_RECEIPT) { 269 messageIndex = stream.readUInt24_LE(); 270 } 271 if(reliability <= Reliability.RELIABLE_SEQUENCED && reliability != Reliability.RELIABLE) { 272 orderIndex = stream.readUInt24_LE(); 273 orderChannel = stream.readByte(); 274 } 275 } 276 if(split) { 277 splitCount = stream.readUInt(); 278 splitID = stream.readUShort(); 279 splitIndex = stream.readUInt(); 280 } 281 payload = stream.read(len); 282 } 283 284 ubyte getID() { 285 return 0; 286 } 287 288 uint getSize() { 289 return cast(uint) (3 + (messageIndex != -1 ? 3 : 0) + ((orderIndex != -1 && orderChannel != -1) ? 4 : 0) + (split ? 10 : 0) + (payload.length)); 290 } 291 } 292 }