public void TestEncodeDecode() { AckFrame af = new AckFrame { LargestAcknowledged = new VariableLengthInteger(32767), Delay = new VariableLengthInteger(500), AckRangeCount = new VariableLengthInteger(1), FirstAckRange = new VariableLengthInteger(10), AckRanges = new List <(VariableLengthInteger, VariableLengthInteger)> { (new VariableLengthInteger(3), new VariableLengthInteger(40)) }, ECT0 = new VariableLengthInteger(1345), ECT1 = new VariableLengthInteger(1234), ECN_CE = new VariableLengthInteger(84), }; byte[] b = af.Encode(); AckFrame afDecoded = new AckFrame(); Assert.AreEqual(b.Length * 8, afDecoded.Decode(b, 0)); Assert.AreEqual((UInt64)32767, afDecoded.LargestAcknowledged.Value); Assert.AreEqual((UInt64)500, afDecoded.Delay.Value); Assert.AreEqual((UInt64)1, afDecoded.AckRangeCount.Value); Assert.AreEqual((UInt64)10, afDecoded.FirstAckRange.Value); Assert.AreEqual((UInt64)1345, afDecoded.ECT0.Value); Assert.AreEqual((UInt64)1234, afDecoded.ECT1.Value); Assert.AreEqual((UInt64)84, afDecoded.ECN_CE.Value); Assert.AreEqual(1, afDecoded.AckRanges.Count); Assert.AreEqual((UInt64)3, afDecoded.AckRanges[0].Item1.Value); Assert.AreEqual((UInt64)40, afDecoded.AckRanges[0].Item2.Value); }
public void TestEncode() { VariableLengthInteger n = new VariableLengthInteger((UInt64)61); Assert.AreEqual((UInt64)61, n.Value); Assert.AreEqual(8, n.Size); byte[] b = n.Encode(); Assert.AreEqual(1, b.Length); Assert.AreEqual(61, b[0]); n.Value = 1414; Assert.AreEqual((UInt64)1414, n.Value); Assert.AreEqual(16, n.Size); b = n.Encode(); Assert.AreEqual(2, b.Length); Assert.AreEqual(0x40, b[0] & 0xc0); Assert.AreEqual(0x05, b[0] % 0x40); // 1024 + 256 Assert.AreEqual(134, b[1]); n.Value = 65536; Assert.AreEqual((UInt64)65536, n.Value); Assert.AreEqual(32, n.Size); b = n.Encode(); Assert.AreEqual(4, b.Length); Assert.AreEqual(0x80, b[0] & 0xc0); Assert.AreEqual(0, b[0] % 0x40); Assert.AreEqual(1, b[1]); Assert.AreEqual(0, b[2]); Assert.AreEqual(0, b[3]); n.Value = (1UL << 32); Assert.AreEqual(1UL << 32, n.Value); Assert.AreEqual(64, n.Size); b = n.Encode(); Assert.AreEqual(8, b.Length); Assert.AreEqual(0xc0, b[0] & 0xc0); Assert.AreEqual(0, b[0] % 0x40); Assert.AreEqual(0, b[1]); Assert.AreEqual(0, b[2]); Assert.AreEqual(1, b[3]); Assert.AreEqual(0, b[4]); Assert.AreEqual(0, b[5]); Assert.AreEqual(0, b[6]); Assert.AreEqual(0, b[7]); n.Value = (UInt64)151288809941952652; Assert.AreEqual(64, n.Size); b = n.Encode(); Assert.AreEqual(8, b.Length); Assert.AreEqual(0xc2, b[0]); Assert.AreEqual(0x19, b[1]); Assert.AreEqual(0x7c, b[2]); Assert.AreEqual(0x5e, b[3]); Assert.AreEqual(0xff, b[4]); Assert.AreEqual(0x14, b[5]); Assert.AreEqual(0xe8, b[6]); Assert.AreEqual(0x8c, b[7]); }
public StreamFrame(UInt64 streamID, UInt64 offset, byte[] data, bool isLastFrameOfPacket, bool isEndOfStream) { StreamID = new VariableLengthInteger(streamID); OFF = offset != 0; Offset = new VariableLengthInteger(offset); LEN = !isLastFrameOfPacket; _length = new VariableLengthInteger(data.Length); FIN = isEndOfStream; _writableType = Convert.ToByte(0b00001000 + (OFF ? (1 << 2) : 0) + (LEN ? (1 << 1) : 0) + (FIN ? (1 << 0) : 0)); Data = data; }
/// <summary> /// Decode a StreamFrame from a raw byte array /// </summary> /// <param name="content">The raw byte array</param> /// <param name="begin">The bit index of the byte array where the AckFrame is located</param> /// <returns>The number of bits read</returns> public override int Decode(byte[] content, int begin) { if (content.Length < 1 + (begin / 8)) { throw new ArgumentException(); } _writableType = content[begin / 8]; if (Type < _minType || Type > _maxType) { throw new ArgumentException("Wrong frame type created"); } OFF = (Type & (1 << 2)) != 0; LEN = (Type & (1 << 1)) != 0; FIN = (Type & (1 << 0)) != 0; int cursor = (begin / 8) + 1; cursor += StreamID.Decode(cursor * 8, content) / 8; if (OFF) { cursor += Offset.Decode(cursor * 8, content) / 8; } if (LEN) { cursor += _length.Decode(cursor * 8, content) / 8; } else { _length = new VariableLengthInteger(Convert.ToUInt64(content.Length) - Convert.ToUInt64(cursor)); } Data = new byte[_length.Value]; // TODO: error handling if source packet is not long enough Array.Copy(content, cursor, Data, 0, Convert.ToInt32(_length.Value)); return((cursor + Convert.ToInt32(_length.Value)) * 8 - begin); }
public void TestDecode() { VariableLengthInteger n = new VariableLengthInteger(0); byte[] b = new byte[] { 0, 0, 3, 0 }; Assert.AreEqual(8, n.Decode(16, b)); Assert.AreEqual(8, n.Size); Assert.AreEqual((UInt64)3, n.Value); b = new byte[] { 0, 128, 1, 0, 0, 0, 0 }; Assert.AreEqual(32, n.Decode(8, b)); Assert.AreEqual(32, n.Size); Assert.AreEqual((UInt64)65536, n.Value); b = new byte[] { 0x9d, 0x7f, 0x3e, 0x7d }; Assert.AreEqual(32, n.Decode(0, b)); Assert.AreEqual(32, n.Size); Assert.AreEqual((UInt64)494878333, n.Value); b = new byte[] { 0x7b, 0xbd }; Assert.AreEqual(16, n.Decode(0, b)); Assert.AreEqual(16, n.Size); Assert.AreEqual((UInt64)15293, n.Value); b = new byte[] { 0x25 }; Assert.AreEqual(8, n.Decode(0, b)); Assert.AreEqual(8, n.Size); Assert.AreEqual((UInt64)37, n.Value); b = new byte[] { 0x40, 0x25 }; Assert.AreEqual(16, n.Decode(0, b)); Assert.AreEqual(16, n.Size); Assert.AreEqual((UInt64)37, n.Value); b = new byte[] { 0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c }; Assert.AreEqual(64, n.Decode(0, b)); Assert.AreEqual(64, n.Size); Assert.AreEqual((UInt64)151288809941952652, n.Value); }
/// <remarks> /// 0 1 2 3 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 /// +-+-+-+-+-+-+-+-+ /// |1| Type (7) | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Version (32) | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// |DCIL(4)|SCIL(4)| /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Destination Connection ID (0/32..144) ... /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Source Connection ID (0/32..144) ... /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Payload Length (i) ... /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Packet Number (32) | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Payload (*) ... /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// </remarks> /// <param name="buffer">Buffer to parse the long header from.</param> /// <param name="offset">Current offset.</param> public LongHeader(Span <byte> buffer, ref int offset) { // Read version (32-bit) this.Version = BitConverter.ToString(buffer.Slice(offset, 4).ToArray(), 0, 4); offset += 4; // Read length of destination and source connection ID's byte dcilscil = buffer.Slice(offset++, 1).ToArray()[0]; int dcil = dcilscil >> 4; int scil = dcilscil & 0x0F; if (dcil != 0) { dcil += 3; } if (scil != 0) { scil += 3; } // Read destination and source connection ID's this.DestinationConnectionID = "0x" + BitConverter.ToString(buffer.Slice(offset, dcil).ToArray()).ToLower().Replace("-", string.Empty); offset += dcil; this.SourceConnectionID = "0x" + BitConverter.ToString(buffer.Slice(offset, scil).ToArray()).ToLower().Replace("-", string.Empty); offset += scil; // Read payload length (Variable length Integer) this.PayloadLength = VariableLengthInteger.Parse(buffer, ref offset); // Read packet number byte[] packetNumberBytes = buffer.Slice(offset, 4).ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(packetNumberBytes); } this.PacketNumber = BitConverter.ToUInt32(packetNumberBytes, 0); offset += 4; }