diff --git a/QuicNet.Infrastructure/ErrorCodes.cs b/QuicNet.Infrastructure/ErrorCodes.cs
index 163febe..bcd57a3 100644
--- a/QuicNet.Infrastructure/ErrorCodes.cs
+++ b/QuicNet.Infrastructure/ErrorCodes.cs
@@ -10,15 +10,20 @@ public enum ErrorCode : UInt16
{
NO_ERROR = 0x0,
INTERNAL_ERROR = 0x1,
- SERVER_BUSY = 0x2,
+ CONNECTION_REFUSED = 0x2,
FLOW_CONTROL_ERROR = 0x3,
STREAM_LIMIT_ERROR = 0x4,
STREAM_STATE_ERROR = 0x5,
- FINAL_OFFSET_ERROR = 0x6,
+ FINAL_SIZE_ERROR = 0x6,
FRAME_ENCODING_ERROR = 0x7,
TRANSPORT_PARAMETER_ERROR = 0x8,
- VERSION_NEGOTIATION_ERROR = 0x9,
+ CONNECTION_ID_LIMIT_ERROR = 0x9,
PROTOCOL_VIOLATION = 0xA,
- INVALID_MIGRATION = 0xC
+ INVALID_TOKEN = 0xB,
+ APPLICATION_ERROR = 0xC,
+ CRYPTO_BUFFER_EXCEEDED = 0xD,
+ KEY_UPDATE_ERROR = 0xE,
+ AEAD_LIMIT_REACHED = 0xF,
+ CRYPTO_ERROR = 0x100
}
}
diff --git a/QuicNet.Infrastructure/Frames/ConnectionCloseFrame.cs b/QuicNet.Infrastructure/Frames/ConnectionCloseFrame.cs
index 8fff599..2fe9317 100644
--- a/QuicNet.Infrastructure/Frames/ConnectionCloseFrame.cs
+++ b/QuicNet.Infrastructure/Frames/ConnectionCloseFrame.cs
@@ -9,8 +9,10 @@ namespace QuicNet.Infrastructure.Frames
{
public class ConnectionCloseFrame : Frame
{
+ public byte ActualType { get; set; }
public override byte Type => 0x1c;
- public UInt16 ErrorCode { get; set; }
+ public VariableInteger ErrorCode { get; set; }
+ public VariableInteger FrameType { get; set; }
public VariableInteger ReasonPhraseLength { get; set; }
public string ReasonPhrase { get; set; }
@@ -20,19 +22,36 @@ public ConnectionCloseFrame()
ReasonPhraseLength = new VariableInteger(0);
}
- public ConnectionCloseFrame(ErrorCode error, string reason)
+ ///
+ /// 0x1d not yet supported (Application Protocol Error)
+ ///
+ public ConnectionCloseFrame(ErrorCode error, byte frameType, string reason)
{
- ReasonPhraseLength = new VariableInteger(0);
+ ActualType = 0x1c;
+
+ ErrorCode = (UInt64)error;
+ FrameType = new VariableInteger((UInt64)frameType);
+ if (!string.IsNullOrWhiteSpace(reason))
+ {
+ ReasonPhraseLength = new VariableInteger((UInt64)reason.Length);
+ }
+ else
+ {
+ ReasonPhraseLength = new VariableInteger(0);
+ }
- ErrorCode = (UInt16)error;
ReasonPhrase = reason;
}
public override void Decode(ByteArray array)
{
- byte type = array.ReadByte();
+ ActualType = array.ReadByte();
+ ErrorCode = array.ReadVariableInteger();
+ if (ActualType == 0x1c)
+ {
+ FrameType = array.ReadVariableInteger();
+ }
- ErrorCode = array.ReadUInt16();
ReasonPhraseLength = array.ReadVariableInteger();
byte[] rp = array.ReadBytes((int)ReasonPhraseLength.Value);
@@ -42,16 +61,19 @@ public override void Decode(ByteArray array)
public override byte[] Encode()
{
List result = new List();
- result.Add(Type);
-
- byte[] errorCode = ByteUtilities.GetBytes(ErrorCode);
- result.AddRange(errorCode);
+ result.Add(ActualType);
+ result.AddRange(ErrorCode.ToByteArray());
+ if (ActualType == 0x1c)
+ {
+ result.AddRange(FrameType.ToByteArray());
+ }
if (string.IsNullOrWhiteSpace(ReasonPhrase) == false)
{
- byte[] reasonPhrase = ByteUtilities.GetBytes(ReasonPhrase);
byte[] rpl = new VariableInteger((UInt64)ReasonPhrase.Length);
result.AddRange(rpl);
+
+ byte[] reasonPhrase = ByteUtilities.GetBytes(ReasonPhrase);
result.AddRange(reasonPhrase);
}
diff --git a/QuicNet.Infrastructure/Frames/DataBlockedFrame.cs b/QuicNet.Infrastructure/Frames/DataBlockedFrame.cs
index 9bccea7..3f95179 100644
--- a/QuicNet.Infrastructure/Frames/DataBlockedFrame.cs
+++ b/QuicNet.Infrastructure/Frames/DataBlockedFrame.cs
@@ -10,7 +10,7 @@ namespace QuicNet.Infrastructure.Frames
public class DataBlockedFrame : Frame
{
public override byte Type => 0x14;
- public VariableInteger DataLimit { get; set; }
+ public VariableInteger MaximumData { get; set; }
public DataBlockedFrame()
{
@@ -19,22 +19,20 @@ public DataBlockedFrame()
public DataBlockedFrame(UInt64 dataLimit)
{
- DataLimit = dataLimit;
+ MaximumData = dataLimit;
}
public override void Decode(ByteArray array)
{
byte type = array.ReadByte();
- DataLimit = array.ReadVariableInteger();
+ MaximumData = array.ReadVariableInteger();
}
public override byte[] Encode()
{
List result = new List();
result.Add(Type);
- byte[] dataLimit = DataLimit;
-
- result.AddRange(dataLimit);
+ result.AddRange(MaximumData.ToByteArray());
return result.ToArray();
}
diff --git a/QuicNet.Infrastructure/Frames/MaxDataFrame.cs b/QuicNet.Infrastructure/Frames/MaxDataFrame.cs
index cccfce6..142cc40 100644
--- a/QuicNet.Infrastructure/Frames/MaxDataFrame.cs
+++ b/QuicNet.Infrastructure/Frames/MaxDataFrame.cs
@@ -21,10 +21,9 @@ public override void Decode(ByteArray array)
public override byte[] Encode()
{
List result = new List();
- byte[] maxData = MaximumData;
result.Add(Type);
- result.AddRange(maxData);
+ result.AddRange(MaximumData.ToByteArray());
return result.ToArray();
}
diff --git a/QuicNet.Infrastructure/Frames/MaxStreamDataFrame.cs b/QuicNet.Infrastructure/Frames/MaxStreamDataFrame.cs
index dc5d69b..3edda71 100644
--- a/QuicNet.Infrastructure/Frames/MaxStreamDataFrame.cs
+++ b/QuicNet.Infrastructure/Frames/MaxStreamDataFrame.cs
@@ -36,13 +36,10 @@ public override void Decode(ByteArray array)
public override byte[] Encode()
{
List result = new List();
- result.Add(Type);
-
- byte[] streamId = StreamId;
- result.AddRange(streamId);
- byte[] maximumStreamData = MaximumStreamData;
- result.AddRange(maximumStreamData);
+ result.Add(Type);
+ result.AddRange(StreamId.ToByteArray());
+ result.AddRange(MaximumStreamData.ToByteArray());
return result.ToArray();
}
diff --git a/QuicNet.Infrastructure/Frames/MaxStreamsFrame.cs b/QuicNet.Infrastructure/Frames/MaxStreamsFrame.cs
index 9729a93..fbf39f1 100644
--- a/QuicNet.Infrastructure/Frames/MaxStreamsFrame.cs
+++ b/QuicNet.Infrastructure/Frames/MaxStreamsFrame.cs
@@ -31,10 +31,9 @@ public override void Decode(ByteArray array)
public override byte[] Encode()
{
List result = new List();
- result.Add(Type);
- byte[] streamId = MaximumStreams;
- result.AddRange(streamId);
+ result.Add(Type);
+ result.AddRange(MaximumStreams.ToByteArray());
return result.ToArray();
}
diff --git a/QuicNet.Infrastructure/Frames/PingFrame.cs b/QuicNet.Infrastructure/Frames/PingFrame.cs
index c758af8..5819801 100644
--- a/QuicNet.Infrastructure/Frames/PingFrame.cs
+++ b/QuicNet.Infrastructure/Frames/PingFrame.cs
@@ -13,12 +13,15 @@ public class PingFrame : Frame
public override void Decode(ByteArray array)
{
- throw new NotImplementedException();
+ byte type = array.ReadByte();
}
public override byte[] Encode()
{
- throw new NotImplementedException();
+ List data = new List();
+ data.Add(Type);
+
+ return data.ToArray();
}
}
}
diff --git a/QuicNet.Infrastructure/Frames/ResetStreamFrame.cs b/QuicNet.Infrastructure/Frames/ResetStreamFrame.cs
index b8715eb..0bfc640 100644
--- a/QuicNet.Infrastructure/Frames/ResetStreamFrame.cs
+++ b/QuicNet.Infrastructure/Frames/ResetStreamFrame.cs
@@ -11,15 +11,15 @@ public class ResetStreamFrame : Frame
{
public override byte Type => 0x04;
public VariableInteger StreamId { get; set; }
- public UInt16 ApplicationErrorCode { get; set; }
- public VariableInteger FinalOffset { get; set; }
+ public VariableInteger ApplicationProtocolErrorCode { get; set; }
+ public VariableInteger FinalSize { get; set; }
public override void Decode(ByteArray array)
{
byte type = array.ReadByte();
StreamId = array.ReadVariableInteger();
- ApplicationErrorCode = array.ReadUInt16();
- FinalOffset = array.ReadVariableInteger();
+ ApplicationProtocolErrorCode = array.ReadVariableInteger();
+ FinalSize = array.ReadVariableInteger();
}
public override byte[] Encode()
@@ -27,13 +27,9 @@ public override byte[] Encode()
List result = new List();
result.Add(Type);
- byte[] streamId = StreamId;
- result.AddRange(streamId);
-
- result.AddRange(ByteUtilities.GetBytes(ApplicationErrorCode));
-
- byte[] offset = FinalOffset;
- result.AddRange(offset);
+ result.AddRange(StreamId.ToByteArray());
+ result.AddRange(ApplicationProtocolErrorCode.ToByteArray());
+ result.AddRange(FinalSize.ToByteArray());
return result.ToArray();
}
diff --git a/QuicNet.Infrastructure/Frames/StreamDataBlockedFrame.cs b/QuicNet.Infrastructure/Frames/StreamDataBlockedFrame.cs
index 3a34d04..b3d5b7d 100644
--- a/QuicNet.Infrastructure/Frames/StreamDataBlockedFrame.cs
+++ b/QuicNet.Infrastructure/Frames/StreamDataBlockedFrame.cs
@@ -11,9 +11,7 @@ public class StreamDataBlockedFrame : Frame
{
public override byte Type => 0x15;
public VariableInteger StreamId { get; set; }
- public VariableInteger StreamDataLimit { get; set; }
-
- public StreamId ConvertedStreamId { get; set; }
+ public VariableInteger MaximumStreamData { get; set; }
public StreamDataBlockedFrame()
{
@@ -23,26 +21,23 @@ public StreamDataBlockedFrame()
public StreamDataBlockedFrame(UInt64 streamId, UInt64 streamDataLimit)
{
StreamId = streamId;
- StreamDataLimit = streamDataLimit;
+ MaximumStreamData = streamDataLimit;
}
public override void Decode(ByteArray array)
{
byte type = array.ReadByte();
StreamId = array.ReadVariableInteger();
- StreamDataLimit = array.ReadVariableInteger();
+ MaximumStreamData = array.ReadVariableInteger();
}
public override byte[] Encode()
{
List result = new List();
- result.Add(Type);
- byte[] streamId = StreamId;
- byte[] streamDataLimit = StreamDataLimit;
-
- result.AddRange(streamId);
- result.AddRange(streamDataLimit);
+ result.Add(Type);
+ result.AddRange(StreamId.ToByteArray());
+ result.AddRange(MaximumStreamData.ToByteArray());
return result.ToArray();
}
diff --git a/QuicNet.Infrastructure/Frames/StreamFrame.cs b/QuicNet.Infrastructure/Frames/StreamFrame.cs
index 7e7bbf6..4175e2d 100644
--- a/QuicNet.Infrastructure/Frames/StreamFrame.cs
+++ b/QuicNet.Infrastructure/Frames/StreamFrame.cs
@@ -9,14 +9,13 @@ namespace QuicNet.Infrastructure.Frames
{
public class StreamFrame : Frame
{
- private byte ActualType = 0x08;
+ public byte ActualType = 0x08;
public override byte Type => 0x08;
public VariableInteger StreamId { get; set; }
public VariableInteger Offset { get; set; }
public VariableInteger Length { get; set; }
public byte[] StreamData { get; set; }
- public StreamId ConvertedStreamId { get; set; }
public bool EndOfStream { get; set; }
public StreamFrame()
@@ -28,8 +27,8 @@ public StreamFrame(UInt64 streamId, byte[] data, UInt64 offset, bool eos)
{
StreamId = streamId;
StreamData = data;
- Length = (UInt64)data.Length;
Offset = offset;
+ Length = (UInt64)data.Length;
EndOfStream = eos;
}
@@ -50,7 +49,6 @@ public override void Decode(ByteArray array)
EndOfStream = true;
StreamData = array.ReadBytes((int)Length.Value);
- ConvertedStreamId = QuickNet.Utilities.StreamId.Decode(ByteUtilities.GetBytes(StreamId.Value));
}
public override byte[] Encode()
@@ -72,16 +70,10 @@ public override byte[] Encode()
result.AddRange(streamId);
if (OFF_BIT > 0)
- {
- byte[] offset = Offset;
- result.AddRange(offset);
- }
+ result.AddRange(Offset.ToByteArray());
if (LEN_BIT > 0)
- {
- byte[] length = Length;
- result.AddRange(length);
- }
+ result.AddRange(Length.ToByteArray());
result.AddRange(StreamData);
diff --git a/QuicNet.Infrastructure/PacketProcessing/PacketCreator.cs b/QuicNet.Infrastructure/PacketProcessing/PacketCreator.cs
index b5cfbea..b57545e 100644
--- a/QuicNet.Infrastructure/PacketProcessing/PacketCreator.cs
+++ b/QuicNet.Infrastructure/PacketProcessing/PacketCreator.cs
@@ -24,12 +24,12 @@ public PacketCreator(UInt32 connectionId, UInt32 peerConnectionId)
_peerConnectionId = peerConnectionId;
}
- public ShortHeaderPacket CreateConnectionClosePacket(ErrorCode code, string reason)
+ public ShortHeaderPacket CreateConnectionClosePacket(ErrorCode code, byte frameType, string reason)
{
ShortHeaderPacket packet = new ShortHeaderPacket();
packet.PacketNumber = _ns.Get();
packet.DestinationConnectionId = (byte)_peerConnectionId;
- packet.AttachFrame(new ConnectionCloseFrame(code, reason));
+ packet.AttachFrame(new ConnectionCloseFrame(code, frameType, reason));
return packet;
}
diff --git a/QuicNet.Infrastructure/Packets/LongHeaderPacket.cs b/QuicNet.Infrastructure/Packets/LongHeaderPacket.cs
index 22b33f6..bfd281a 100644
--- a/QuicNet.Infrastructure/Packets/LongHeaderPacket.cs
+++ b/QuicNet.Infrastructure/Packets/LongHeaderPacket.cs
@@ -7,34 +7,46 @@ namespace QuicNet.Infrastructure.Packets
{
public class LongHeaderPacket : Packet
{
- public override byte Type => 0xC0; // 1100 0000
+ public override byte Type => 0b1100_0000; // 1100 0000
- public byte DCID { get; set; }
- public byte DestinationConnectionId { get; set; }
- public byte SCID { get; set; }
- public byte SourceConnectionId { get; set; }
+ public byte DestinationConnectionIdLength { get; set; }
+ public GranularInteger DestinationConnectionId { get; set; }
+ public byte SourceConnectionIdLength { get; set; }
+ public GranularInteger SourceConnectionId { get; set; }
public PacketType PacketType { get; set; }
- public LongHeaderPacket(PacketType packetType)
+
+ public LongHeaderPacket()
+ {
+
+ }
+
+ public LongHeaderPacket(PacketType packetType, GranularInteger destinationConnectionId, GranularInteger sourceConnectionId)
{
PacketType = packetType;
+ DestinationConnectionIdLength = destinationConnectionId.Size;
+ DestinationConnectionId = destinationConnectionId;
+
+ SourceConnectionIdLength = sourceConnectionId.Size;
+ SourceConnectionId = sourceConnectionId;
}
public override void Decode(byte[] packet)
{
ByteArray array = new ByteArray(packet);
+
byte type = array.ReadByte();
- PacketType = (PacketType)(type & 0x30);
+ PacketType = DecodeTypeFiled(type);
Version = array.ReadUInt32();
- DCID = array.ReadByte();
- if (DCID > 0)
- DestinationConnectionId = array.ReadByte();
+ DestinationConnectionIdLength = array.ReadByte();
+ if (DestinationConnectionIdLength > 0)
+ DestinationConnectionId = array.ReadGranularInteger(DestinationConnectionIdLength);
- SCID = array.ReadByte();
- if (SCID > 0)
- SourceConnectionId = array.ReadByte();
+ SourceConnectionIdLength = array.ReadByte();
+ if (SourceConnectionIdLength > 0)
+ SourceConnectionId = array.ReadGranularInteger(SourceConnectionIdLength);
this.DecodeFrames(array);
}
@@ -48,12 +60,13 @@ public override byte[] Encode()
result.Add(EncodeTypeField());
result.AddRange(ByteUtilities.GetBytes(Version));
- result.Add(DCID);
- if (DCID > 0)
- result.Add(DestinationConnectionId);
- result.Add(SCID);
- if (SCID > 0)
- result.Add(SourceConnectionId);
+ result.Add(DestinationConnectionId.Size);
+ if (DestinationConnectionId.Size > 0)
+ result.AddRange(DestinationConnectionId.ToByteArray());
+
+ result.Add(SourceConnectionId.Size);
+ if (SourceConnectionId.Size > 0)
+ result.AddRange(SourceConnectionId.ToByteArray());
result.AddRange(frames);
@@ -62,9 +75,16 @@ public override byte[] Encode()
private byte EncodeTypeField()
{
- byte type = (byte)(Type | (byte)PacketType | 0x03);
+ byte type = (byte)(Type | ((byte)PacketType << 4) & 0b0011_0000);
return type;
}
+
+ private PacketType DecodeTypeFiled(byte type)
+ {
+ PacketType result = (PacketType)((type & 0b0011_0000) >> 4);
+
+ return result;
+ }
}
}
diff --git a/QuicNet.Infrastructure/Packets/ShortHeaderPacket.cs b/QuicNet.Infrastructure/Packets/ShortHeaderPacket.cs
index 1c6eaf9..18a86e2 100644
--- a/QuicNet.Infrastructure/Packets/ShortHeaderPacket.cs
+++ b/QuicNet.Infrastructure/Packets/ShortHeaderPacket.cs
@@ -7,7 +7,9 @@ namespace QuicNet.Infrastructure.Packets
{
public class ShortHeaderPacket : Packet
{
- public override byte Type => 0x40; // 0100 0000;
+ public byte ActualType = 0b01000000;
+ public override byte Type => 0b01000000;
+
public byte DestinationConnectionId { get; set; }
public GranularInteger PacketNumber { get; set; }
diff --git a/QuicNet.Tests.Unit/FrameTests.cs b/QuicNet.Tests.Unit/FrameTests.cs
new file mode 100644
index 0000000..5d4dbe2
--- /dev/null
+++ b/QuicNet.Tests.Unit/FrameTests.cs
@@ -0,0 +1,28 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using QuickNet.Utilities;
+using QuicNet.Constants;
+using QuicNet.Infrastructure;
+using QuicNet.Infrastructure.Frames;
+
+namespace QuicNet.Tests.Unit
+{
+ [TestClass]
+ public class FrameTests
+ {
+ [TestMethod]
+ public void ConnectionCloseFrameTest()
+ {
+ var ccf = new ConnectionCloseFrame(ErrorCode.PROTOCOL_VIOLATION, 0x00, ErrorConstants.PMTUNotReached);
+ byte[] data = ccf.Encode();
+
+ var nccf = new ConnectionCloseFrame();
+ nccf.Decode(new ByteArray(data));
+
+ Assert.AreEqual(ccf.ActualType, nccf.ActualType);
+ Assert.AreEqual(ccf.FrameType.Value, nccf.FrameType.Value);
+ Assert.AreEqual(ccf.ReasonPhraseLength.Value, nccf.ReasonPhraseLength.Value);
+ Assert.AreEqual(ccf.ReasonPhrase, nccf.ReasonPhrase);
+ }
+ }
+}
diff --git a/QuicNet.Tests.Unit/PacketTests.cs b/QuicNet.Tests.Unit/PacketTests.cs
new file mode 100644
index 0000000..c88115c
--- /dev/null
+++ b/QuicNet.Tests.Unit/PacketTests.cs
@@ -0,0 +1,37 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using QuicNet.Infrastructure.Frames;
+using QuicNet.Infrastructure.Packets;
+
+namespace QuicNet.Tests.Unit
+{
+ [TestClass]
+ public class PacketTests
+ {
+ [TestMethod]
+ public void LongeHeaderPacketTest()
+ {
+ LongHeaderPacket packet = new LongHeaderPacket(Infrastructure.PacketType.Handshake, 123415332, 1);
+ packet.Version = 32;
+
+ for (int i = 0; i < 123; i++)
+ {
+ packet.AttachFrame(new PaddingFrame());
+ }
+
+ byte[] data = packet.Encode();
+
+ LongHeaderPacket result = new LongHeaderPacket();
+ result.Decode(data);
+
+ Assert.AreEqual(packet.Type, result.Type);
+ Assert.AreEqual(packet.Version, result.Version);
+ Assert.AreEqual(packet.DestinationConnectionIdLength, result.DestinationConnectionIdLength);
+ Assert.AreEqual(packet.DestinationConnectionId.Value, result.DestinationConnectionId.Value);
+ Assert.AreEqual(packet.SourceConnectionIdLength, result.SourceConnectionIdLength);
+ Assert.AreEqual(packet.SourceConnectionId.Value, result.SourceConnectionId.Value);
+ Assert.AreEqual(packet.PacketType, result.PacketType);
+ Assert.AreEqual(packet.GetFrames().Count, result.GetFrames().Count);
+ }
+ }
+}
diff --git a/QuicNet.Tests.Unit/QuicNet.Tests.Unit.csproj b/QuicNet.Tests.Unit/QuicNet.Tests.Unit.csproj
index 43339e8..de88d6f 100644
--- a/QuicNet.Tests.Unit/QuicNet.Tests.Unit.csproj
+++ b/QuicNet.Tests.Unit/QuicNet.Tests.Unit.csproj
@@ -51,6 +51,8 @@
+
+
diff --git a/QuicNet.Tests.Unit/StreamIdTests.cs b/QuicNet.Tests.Unit/StreamIdTests.cs
index b47a26a..36894df 100644
--- a/QuicNet.Tests.Unit/StreamIdTests.cs
+++ b/QuicNet.Tests.Unit/StreamIdTests.cs
@@ -58,5 +58,17 @@ public void ServerUnidirectional()
Assert.AreEqual(data[6], 1);
Assert.AreEqual(data[7], 239);
}
+
+ [TestMethod]
+ public void VariableIntegerTest()
+ {
+ StreamId id = new StreamId(123, StreamType.ClientBidirectional);
+
+ VariableInteger integer = id;
+
+ StreamId converted = integer;
+
+ Assert.AreEqual(id.Id, converted.Id);
+ }
}
}
diff --git a/QuicNet/Connections/QuicConnection.cs b/QuicNet/Connections/QuicConnection.cs
index 67333bd..9d658b0 100644
--- a/QuicNet/Connections/QuicConnection.cs
+++ b/QuicNet/Connections/QuicConnection.cs
@@ -1,4 +1,5 @@
using QuickNet.Utilities;
+using QuicNet.Constants;
using QuicNet.Context;
using QuicNet.Exceptions;
using QuicNet.Infrastructure;
@@ -69,7 +70,7 @@ public void ProcessFrames(List frames)
OnMaxStreamFrame(frame);
if (frame.Type == 0x14)
OnDataBlockedFrame(frame);
- if (frame.Type == 0x1c)
+ if (frame.Type >= 0x1c && frame.Type <= 0x1d)
OnConnectionCloseFrame(frame);
}
}
@@ -111,19 +112,21 @@ private void OnRstStreamFrame(Frame frame)
private void OnStreamFrame(Frame frame)
{
StreamFrame sf = (StreamFrame)frame;
- if (_streams.ContainsKey(sf.ConvertedStreamId.Id) == false)
+ StreamId streamId = sf.StreamId;
+
+ if (_streams.ContainsKey(streamId.Id) == false)
{
- QuicStream stream = new QuicStream(this, sf.ConvertedStreamId);
+ QuicStream stream = new QuicStream(this, streamId);
stream.ProcessData(sf);
if ((UInt64)_streams.Count < MaxStreams)
- _streams.Add(sf.ConvertedStreamId.Id, stream);
+ _streams.Add(streamId.Id, stream);
else
SendMaximumStreamReachedError();
}
else
{
- QuicStream stream = _streams[sf.ConvertedStreamId.Id];
+ QuicStream stream = _streams[streamId.Id];
stream.ProcessData(sf);
}
}
@@ -165,15 +168,16 @@ private void OnDataBlockedFrame(Frame frame)
private void OnStreamDataBlockedFrame(Frame frame)
{
StreamDataBlockedFrame sdbf = (StreamDataBlockedFrame)frame;
+ StreamId streamId = sdbf.StreamId;
- if (_streams.ContainsKey(sdbf.ConvertedStreamId.Id) == false)
+ if (_streams.ContainsKey(streamId.Id) == false)
return;
- QuicStream stream = _streams[sdbf.ConvertedStreamId.Id];
+ QuicStream stream = _streams[streamId.Id];
stream.ProcessStreamDataBlocked(sdbf);
// Remove the stream from the connection
- _streams.Remove(sdbf.ConvertedStreamId.Id);
+ _streams.Remove(streamId.Id);
}
#region Internal
@@ -241,7 +245,7 @@ internal void TerminateConnection()
internal void SendMaximumStreamReachedError()
{
- ShortHeaderPacket packet = PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.STREAM_LIMIT_ERROR, "Maximum number of streams reached.");
+ ShortHeaderPacket packet = PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.STREAM_LIMIT_ERROR, 0x00, ErrorConstants.MaxNumberOfStreams);
Send(packet);
}
@@ -261,7 +265,7 @@ internal bool Send(Packet packet)
// If the maximum transfer rate is reached, send FLOW_CONTROL_ERROR
if (MaximumReached())
{
- packet = PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.FLOW_CONTROL_ERROR, "Maximum data transfer reached.");
+ packet = PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.FLOW_CONTROL_ERROR, 0x00, ErrorConstants.MaxDataTransfer);
TerminateConnection();
}
diff --git a/QuicNet/Constants/ErrorConstants.cs b/QuicNet/Constants/ErrorConstants.cs
new file mode 100644
index 0000000..b84ef67
--- /dev/null
+++ b/QuicNet/Constants/ErrorConstants.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace QuicNet.Constants
+{
+ public class ErrorConstants
+ {
+ public const string ServerTooBusy = "The server is too busy to process your request.";
+ public const string MaxDataTransfer = "Maximum data transfer reached.";
+ public const string MaxNumberOfStreams = "Maximum number of streams reached.";
+ public const string PMTUNotReached = "PMTU have not been reached.";
+ }
+}
diff --git a/QuicNet/QuicListener.cs b/QuicNet/QuicListener.cs
index c7d233c..b45a5e2 100644
--- a/QuicNet/QuicListener.cs
+++ b/QuicNet/QuicListener.cs
@@ -1,5 +1,6 @@
using QuickNet.Utilities;
using QuicNet.Connections;
+using QuicNet.Constants;
using QuicNet.Context;
using QuicNet.Exceptions;
using QuicNet.Infrastructure;
@@ -147,7 +148,7 @@ private QuicConnection ProcessInitialPacket(Packet packet, IPEndPoint endPoint)
// Protocol violation if the initial packet is smaller than the PMTU. (pt. 14 / 16th draft)
if (cast.Encode().Length < QuicSettings.PMTU)
{
- ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.PROTOCOL_VIOLATION, "PMTU have not been reached."));
+ ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.PROTOCOL_VIOLATION, 0x00, ErrorConstants.PMTUNotReached));
}
else if (ConnectionPool.AddConnection(new ConnectionData(_pwt, cast.SourceConnectionId, 0), out availableConnectionId) == true)
{
@@ -165,7 +166,7 @@ private QuicConnection ProcessInitialPacket(Packet packet, IPEndPoint endPoint)
// Not accepting connections. Send initial packet with CONNECTION_CLOSE frame.
// TODO: Buffering. The server might buffer incomming 0-RTT packets in anticipation of late delivery InitialPacket.
// Maximum buffer size should be set in QuicSettings.
- ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.SERVER_BUSY, "The server is too busy to process your request."));
+ ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.CONNECTION_REFUSED, 0x00, ErrorConstants.ServerTooBusy));
}
data = ip.Encode();
diff --git a/QuicNet/Streams/QuicStream.cs b/QuicNet/Streams/QuicStream.cs
index f882ef8..3053f12 100644
--- a/QuicNet/Streams/QuicStream.cs
+++ b/QuicNet/Streams/QuicStream.cs
@@ -1,5 +1,6 @@
using QuickNet.Utilities;
using QuicNet.Connections;
+using QuicNet.Constants;
using QuicNet.Context;
using QuicNet.Exceptions;
using QuicNet.Infrastructure.Frames;
@@ -131,7 +132,7 @@ public void ProcessData(StreamFrame frame)
// Terminate connection if maximum stream data is reached
if (_currentTransferRate >= _maximumStreamData)
{
- ShortHeaderPacket errorPacket = _connection.PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.FLOW_CONTROL_ERROR, "Maximum stream data transfer reached.");
+ ShortHeaderPacket errorPacket = _connection.PacketCreator.CreateConnectionClosePacket(Infrastructure.ErrorCode.FLOW_CONTROL_ERROR, frame.ActualType, ErrorConstants.MaxDataTransfer);
_connection.SendData(errorPacket);
_connection.TerminateConnection();
diff --git a/QuickNet.Tests.ConsoleServer/Program.cs b/QuickNet.Tests.ConsoleServer/Program.cs
index 2518f49..07a0a95 100644
--- a/QuickNet.Tests.ConsoleServer/Program.cs
+++ b/QuickNet.Tests.ConsoleServer/Program.cs
@@ -60,7 +60,7 @@ static void Main(string[] args)
packet = new InitialPacketCreator().CreateInitialPacket(124, 0);
- ConnectionCloseFrame frame = new ConnectionCloseFrame(ErrorCode.SERVER_BUSY, "The server is too busy to process your request.");
+ ConnectionCloseFrame frame = new ConnectionCloseFrame(ErrorCode.CONNECTION_REFUSED, 0x00, "The server is too busy to process your request.");
MaxStreamsFrame msidframe = new MaxStreamsFrame(144123, StreamType.ClientUnidirectional);
//packet.AttachFrame(frame);
packet.AttachFrame(msidframe);
diff --git a/QuickNet.Utilities/ByteArray.cs b/QuickNet.Utilities/ByteArray.cs
index 6253941..cbad4fa 100644
--- a/QuickNet.Utilities/ByteArray.cs
+++ b/QuickNet.Utilities/ByteArray.cs
@@ -80,6 +80,14 @@ public VariableInteger ReadVariableInteger()
return bytes;
}
+ public GranularInteger ReadGranularInteger(int size)
+ {
+ byte[] data = ReadBytes(size);
+ GranularInteger result = data;
+
+ return result;
+ }
+
public StreamId ReadStreamId()
{
byte[] streamId = ReadBytes(8);
diff --git a/QuickNet.Utilities/GranularInteger.cs b/QuickNet.Utilities/GranularInteger.cs
index 22a3ef1..7c9e41f 100644
--- a/QuickNet.Utilities/GranularInteger.cs
+++ b/QuickNet.Utilities/GranularInteger.cs
@@ -19,6 +19,11 @@ public GranularInteger(UInt64 integer)
_integer = integer;
}
+ public byte[] ToByteArray()
+ {
+ return Encode(this._integer);
+ }
+
public static implicit operator byte[] (GranularInteger integer)
{
return Encode(integer._integer);
diff --git a/QuickNet.Utilities/StreamId.cs b/QuickNet.Utilities/StreamId.cs
index 67c734d..3301b18 100644
--- a/QuickNet.Utilities/StreamId.cs
+++ b/QuickNet.Utilities/StreamId.cs
@@ -42,6 +42,11 @@ public static implicit operator UInt64(StreamId streamId)
return streamId.Id;
}
+ public static implicit operator StreamId(VariableInteger integer)
+ {
+ return Decode(ByteUtilities.GetBytes(integer.Value));
+ }
+
public static byte[] Encode(UInt64 id, StreamType type)
{
UInt64 identifier = id << 2 | (UInt64)type;
diff --git a/QuickNet.Utilities/VariableInteger.cs b/QuickNet.Utilities/VariableInteger.cs
index ffd019b..2e8c4f7 100644
--- a/QuickNet.Utilities/VariableInteger.cs
+++ b/QuickNet.Utilities/VariableInteger.cs
@@ -38,6 +38,11 @@ public static implicit operator UInt64(VariableInteger integer)
return integer._integer;
}
+ public static implicit operator VariableInteger(StreamId streamId)
+ {
+ return new VariableInteger(streamId.IntegerValue);
+ }
+
public static int Size(byte firstByte)
{
int result = (int)Math.Pow(2, (firstByte >> 6));
@@ -45,6 +50,11 @@ public static int Size(byte firstByte)
return result;
}
+ public byte[] ToByteArray()
+ {
+ return Encode(this._integer);
+ }
+
public static byte[] Encode(UInt64 integer)
{
int requiredBytes = 0;