namespace Hazel.Dtls
{
///
/// DTLS version constants
///
public enum ProtocolVersion : ushort
{
///
/// Use to obfuscate DTLS as regular UDP packets
///
UDP = 0,
///
/// DTLS 1.2
///
DTLS1_2 = 0xFEFD,
}
///
/// DTLS record content type
///
public enum ContentType : byte
{
ChangeCipherSpec = 20,
Alert = 21,
Handshake = 22,
ApplicationData = 23,
}
///
/// Encode/decode DTLS record header
///
public struct Record
{
public ContentType ContentType;
public ProtocolVersion ProtocolVersion;
public ushort Epoch;
public ulong SequenceNumber;
public ushort Length;
public const int Size = 13;
///
/// Parse a DTLS record from wire format
///
/// True if we successfully parse the record header. Otherwise false
public static bool Parse(out Record record, ProtocolVersion? expectedProtocolVersion, ByteSpan span)
{
record = new Record();
if (span.Length < Size)
{
return false;
}
record.ContentType = (ContentType)span[0];
record.ProtocolVersion = (ProtocolVersion)span.ReadBigEndian16(1);
record.Epoch = span.ReadBigEndian16(3);
record.SequenceNumber = span.ReadBigEndian48(5);
record.Length = span.ReadBigEndian16(11);
if (expectedProtocolVersion.HasValue && record.ProtocolVersion != expectedProtocolVersion.Value)
{
return false;
}
return true;
}
///
/// Encode a DTLS record to wire format
///
public void Encode(ByteSpan span)
{
span[0] = (byte)this.ContentType;
span.WriteBigEndian16((ushort)this.ProtocolVersion, 1);
span.WriteBigEndian16(this.Epoch, 3);
span.WriteBigEndian48(this.SequenceNumber, 5);
span.WriteBigEndian16(this.Length, 11);
}
}
public struct ChangeCipherSpec
{
public const int Size = 1;
enum Value : byte
{
ChangeCipherSpec = 1,
}
///
/// Parse a ChangeCipherSpec record from wire format
///
///
/// True if we successfully parse the ChangeCipherSpec
/// record. Otherwise, false.
///
public static bool Parse(ByteSpan span)
{
if (span.Length != 1)
{
return false;
}
Value value = (Value)span[0];
if (value != Value.ChangeCipherSpec)
{
return false;
}
return true;
}
///
/// Encode a ChangeCipherSpec record to wire format
///
public static void Encode(ByteSpan span)
{
span[0] = (byte)Value.ChangeCipherSpec;
}
}
}