public void TestDecode() { ShortHeaderPacket shp = new ShortHeaderPacket(); shp.PacketNumber = 42; shp.DCID = new byte[] { 0x00, 0x00, 0x00, 0x7b }; shp.AddFrame(new DebugFrame { Message = "Message" }); byte[] pack = shp.Encode(); Packet p = Packet.Unpack(pack); Assert.AreEqual(p.GetType(), typeof(ShortHeaderPacket)); ShortHeaderPacket sh = p as ShortHeaderPacket; CollectionAssert.AreEqual(sh.DCID, new byte[] { 0x00, 0x00, 0x00, 0x7b }); Assert.AreEqual(sh.PacketNumber, (UInt64)42); Assert.AreEqual(sh.Spin, false); Assert.AreEqual(sh.KeyPhase, false); Assert.AreEqual(sh.PacketNumberLength, (UInt32)4); foreach (Frame f in p.Frames) { Assert.AreEqual(f.Type, 0x1e); DebugFrame fd = f as DebugFrame; Assert.AreEqual(fd.Message, "Message"); } }
static void Main(string[] args) { byte[] bytes = new VariableInteger(12345); VariableInteger integer = bytes; UInt64 uinteger = integer; int size = VariableInteger.Size(bytes[0]); InitialPacket packet = new InitialPacket() { Version = 16, SourceConnectionId = 124, DestinationConnectionId = 0, PacketNumber = 777521, TokenLength = 0 }; packet = new PacketCreator().CreateInitialPacket(124, 0); ConnectionCloseFrame frame = new ConnectionCloseFrame(ErrorCode.SERVER_BUSY, "The server is too busy to process your request."); MaxStreamIdFrame msidframe = new MaxStreamIdFrame(144123, StreamType.ClientUnidirectional); //packet.AttachFrame(frame); packet.AttachFrame(msidframe); byte[] data = packet.Encode(); string b64 = ToBase64(data); byte[] shpdata1 = new byte[] { 1, 1, 2, 3, 5, 8 }; byte[] shpdata2 = new byte[] { 13, 21, 34, 55, 89, 144 }; ShortHeaderPacket shp = new ShortHeaderPacket(); shp.DestinationConnectionId = 124; shp.PacketNumber = 2; shp.AttachFrame(new StreamFrame() { StreamId = 1, Length = new VariableInteger((UInt64)shpdata2.Length), StreamData = shpdata2, Offset = 6, EndOfStream = true }); shp.AttachFrame(new StreamFrame() { StreamId = 1, Length = new VariableInteger((UInt64)shpdata1.Length), StreamData = shpdata1, Offset = 0 }); string shpb64 = ToBase64(shp.Encode()); packet.Decode(data); byte[] ccfData = frame.Encode(); frame.Decode(new ByteArray(ccfData)); byte[] streamIdData = new StreamId(123, StreamType.ClientUnidirectional); StreamId streamId = streamIdData; QuicListener listener = new QuicListener(11000); listener.OnClientConnected += Listener_OnClientConnected; listener.Start(); }
public ShortHeaderPacket CreateDataPacket(UInt64 streamId, byte[] data) { ShortHeaderPacket packet = new ShortHeaderPacket(); packet.PacketNumber = _ns.Get(); packet.DestinationConnectionId = (byte)_peerConnectionId; packet.AttachFrame(new StreamFrame(streamId, data, 0, true)); return(packet); }
public ShortHeaderPacket CreateConnectionClosePacket(ErrorCode code, string reason) { ShortHeaderPacket packet = new ShortHeaderPacket(); packet.PacketNumber = _ns.Get(); packet.DestinationConnectionId = (byte)_peerConnectionId; packet.AttachFrame(new ConnectionCloseFrame(code, reason)); return(packet); }
public ShortHeaderPacket CreateDataPacket(UInt64 streamId, byte[] data, UInt64 offset, bool eos) { ShortHeaderPacket packet = new ShortHeaderPacket(_peerConnectionId.Size); packet.PacketNumber = _ns.Get(); packet.DestinationConnectionId = (byte)_peerConnectionId; packet.AttachFrame(new StreamFrame(streamId, data, offset, eos)); return(packet); }
public ShortHeaderPacket CreateDataPacket(ulong streamId, byte[] data) { var packet = new ShortHeaderPacket { PacketNumber = _ns.Get(), DestinationConnectionId = (byte)_peerConnectionId }; packet.AttachFrame(new StreamFrame(streamId, data, 0, true)); return(packet); }
private void ProcessShortHeaderPacket(Packet packet) { ShortHeaderPacket shp = (ShortHeaderPacket)packet; QuicConnection connection = ConnectionPool.Find(shp.DestinationConnectionId); if (connection == null) { return; // TODO: Figure out if the packet should be discarded in that case? } connection.ProcessFrames(shp.GetFrames()); }
public void TestEncode() { ShortHeaderPacket shp = new ShortHeaderPacket(); shp.PacketNumber = 42; shp.DCID = new byte[] { 0x00, 0x00, 0x00, 0x7b }; shp.AddFrame(new DebugFrame { Message = "Message" }); byte[] pack = shp.Encode(); /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0 | 1 | S | R | R | K | P P | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Connection ID(0..160) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Number(8 / 16 / 24 / 32)... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Protected Payload(*)... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ Assert.AreEqual(pack.Length, 17); Assert.AreEqual(pack[0] & 0x80, 0); // First bit Assert.AreEqual(pack[0] & 0x40, 0x40); // Second bit Assert.AreEqual(pack[0] & 0x20, 0); Assert.AreEqual(pack[0] & 0x04, 0); Assert.AreEqual(pack[0] & 0x02, 0x02); Assert.AreEqual(pack[0] & 0x01, 0x01); Assert.AreEqual(pack[1], 0); Assert.AreEqual(pack[2], 0); Assert.AreEqual(pack[3], 0); Assert.AreEqual(pack[4], 0x7b); Assert.AreEqual(pack[5], 0); Assert.AreEqual(pack[6], 0); Assert.AreEqual(pack[7], 0); Assert.AreEqual(pack[8], 42); // Payload Assert.AreEqual(pack[9], 0x1e); // Type Debug Assert.AreEqual(pack[10], Convert.ToByte('M')); Assert.AreEqual(pack[11], Convert.ToByte('e')); Assert.AreEqual(pack[12], Convert.ToByte('s')); Assert.AreEqual(pack[13], Convert.ToByte('s')); Assert.AreEqual(pack[14], Convert.ToByte('a')); Assert.AreEqual(pack[15], Convert.ToByte('g')); Assert.AreEqual(pack[16], Convert.ToByte('e')); }
/// <summary> /// Processes short header packet, by distributing the frames towards connections. /// </summary> /// <param name="packet"></param> private void ProcessShortHeaderPacket(Packet packet) { ShortHeaderPacket shp = (ShortHeaderPacket)packet; QuicConnection connection = ConnectionPool.Find(shp.DestinationConnectionId); // No suitable connection found. Discard the packet. if (connection == null) { return; } connection.ProcessFrames(shp.GetFrames()); }
public void ProcessData(StreamFrame frame) { // Do not accept data if the stream is reset. if (State == StreamState.ResetRecvd) { return; } byte[] data = frame.StreamData; if (frame.Offset != null) { _data.Add(frame.Offset.Value, frame.StreamData); } else { // TODO: Careful with duplicate 0 offset packets on the same stream. Probably PROTOCOL_VIOLATION? _data.Add(0, frame.StreamData); } // Either this frame marks the end of the stream, // or fin frame came before the data frames if (frame.EndOfStream) { State = StreamState.SizeKnown; } _currentTransferRate += (UInt64)data.Length; // Terminate connection if maximum stream data is reached if (_currentTransferRate >= _maximumStreamData) { ShortHeaderPacket errorPacket = _connection.PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.FLOW_CONTROL_ERROR, frame.ActualType, ErrorConstants.MaxDataTransfer); _connection.SendData(errorPacket); _connection.TerminateConnection(); return; } if (State == StreamState.SizeKnown && IsStreamFull()) { State = StreamState.DataRecvd; OnStreamDataReceived?.Invoke(this, Data); } }
public bool Send(byte[] data) { if (Type == StreamType.ServerUnidirectional) { throw new StreamException("Cannot send data on unidirectional stream."); } _connection.IncrementRate(data.Length); ShortHeaderPacket packet = _connection.PacketCreator.CreateDataPacket(this.StreamId.IntegerValue, data); if (_connection.MaximumReached()) { packet.AttachFrame(new StreamDataBlockedFrame(StreamId.IntegerValue, (UInt64)data.Length)); } return(_connection.SendData(packet)); }
public bool Send(byte[] data) { if (Type == StreamType.ServerUnidirectional) { throw new StreamException("Cannot send data on unidirectional stream."); } _connection.IncrementRate(data.Length); int numberOfPackets = (data.Length / QuicSettings.PMTU) + 1; int leftoverCarry = data.Length % QuicSettings.PMTU; for (int i = 0; i < numberOfPackets; i++) { bool eos = false; int dataSize = QuicSettings.PMTU; if (i == numberOfPackets - 1) { eos = true; dataSize = leftoverCarry; } byte[] buffer = new byte[dataSize]; Buffer.BlockCopy(data, (Int32)_sendOffset, buffer, 0, dataSize); ShortHeaderPacket packet = _connection.PacketCreator.CreateDataPacket(this.StreamId.IntegerValue, buffer, _sendOffset, eos); if (i == 0 && data.Length >= QuicSettings.MaxStreamData) { packet.AttachFrame(new MaxStreamDataFrame(this.StreamId.IntegerValue, (UInt64)(data.Length + 1))); } if (_connection.MaximumReached()) { packet.AttachFrame(new StreamDataBlockedFrame(StreamId.IntegerValue, (UInt64)data.Length)); } _sendOffset += (UInt64)buffer.Length; _connection.SendData(packet); } return(true); }
public Packet Unpack(byte[] data) { Packet result = null; var type = GetPacketType(data); switch (type) { case QuicPacketType.Initial: result = new InitialPacket(); break; case QuicPacketType.ShortHeader: result = new ShortHeaderPacket(); break; } if (result == null) { return(null); } result.Decode(data); return(result); }
/// <summary> /// Client only! /// </summary> /// <returns></returns> internal void ReceivePacket() { Packet packet = _pwt.ReadPacket(); if (packet is ShortHeaderPacket) { ShortHeaderPacket shp = (ShortHeaderPacket)packet; ProcessFrames(shp.GetFrames()); } // If the connection has been closed if (_state == ConnectionState.Draining) { if (string.IsNullOrWhiteSpace(_lastError)) { _lastError = "Protocol error"; } TerminateConnection(); throw new QuicConnectivityException(_lastError); } }
internal void SendMaximumStreamReachedError() { ShortHeaderPacket packet = PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.STREAM_LIMIT_ERROR, 0x00, ErrorConstants.MaxNumberOfStreams); Send(packet); }
internal void SendMaximumStreamReachedError() { ShortHeaderPacket packet = PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.STREAM_LIMIT_ERROR, "Maximum number of streams reached."); Context.Send(packet); }