- Implemented tests for RouterConfig, RoutingOptions, StaticInstanceConfig, and RouterConfigOptions to ensure default values are set correctly. - Added tests for RouterConfigProvider to validate configurations and ensure defaults are returned when no file is specified. - Created tests for ConfigValidationResult to check success and error scenarios. - Developed tests for ServiceCollectionExtensions to verify service registration for RouterConfig. - Introduced UdpTransportTests to validate serialization, connection, request-response, and error handling in UDP transport. - Added scripts for signing authority gaps and hashing DevPortal SDK snippets.
80 lines
2.5 KiB
C#
80 lines
2.5 KiB
C#
using StellaOps.Router.Common.Enums;
|
|
using StellaOps.Router.Common.Models;
|
|
|
|
namespace StellaOps.Router.Transport.Udp;
|
|
|
|
/// <summary>
|
|
/// Handles serialization and deserialization of frames for UDP transport.
|
|
/// Frame format: [1-byte frame type][16-byte correlation GUID][remaining data]
|
|
/// </summary>
|
|
public static class UdpFrameProtocol
|
|
{
|
|
private const int FrameTypeSize = 1;
|
|
private const int CorrelationIdSize = 16;
|
|
private const int HeaderSize = FrameTypeSize + CorrelationIdSize;
|
|
|
|
/// <summary>
|
|
/// Parses a frame from a datagram.
|
|
/// </summary>
|
|
/// <param name="data">The datagram data.</param>
|
|
/// <returns>The parsed frame.</returns>
|
|
/// <exception cref="InvalidOperationException">Thrown when the datagram is too small.</exception>
|
|
public static Frame ParseFrame(ReadOnlySpan<byte> data)
|
|
{
|
|
if (data.Length < HeaderSize)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Datagram too small: {data.Length} bytes, minimum is {HeaderSize}");
|
|
}
|
|
|
|
var frameType = (FrameType)data[0];
|
|
var correlationId = new Guid(data.Slice(FrameTypeSize, CorrelationIdSize));
|
|
var payload = data.Length > HeaderSize
|
|
? data[HeaderSize..].ToArray()
|
|
: Array.Empty<byte>();
|
|
|
|
return new Frame
|
|
{
|
|
Type = frameType,
|
|
CorrelationId = correlationId.ToString("N"),
|
|
Payload = payload
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializes a frame to a datagram.
|
|
/// </summary>
|
|
/// <param name="frame">The frame to serialize.</param>
|
|
/// <returns>The serialized datagram bytes.</returns>
|
|
public static byte[] SerializeFrame(Frame frame)
|
|
{
|
|
// Parse or generate correlation ID
|
|
var correlationGuid = frame.CorrelationId is not null &&
|
|
Guid.TryParse(frame.CorrelationId, out var parsed)
|
|
? parsed
|
|
: Guid.NewGuid();
|
|
|
|
var payloadLength = frame.Payload.Length;
|
|
var buffer = new byte[HeaderSize + payloadLength];
|
|
|
|
// Write frame type
|
|
buffer[0] = (byte)frame.Type;
|
|
|
|
// Write correlation ID
|
|
correlationGuid.TryWriteBytes(buffer.AsSpan(FrameTypeSize, CorrelationIdSize));
|
|
|
|
// Write payload
|
|
if (payloadLength > 0)
|
|
{
|
|
frame.Payload.Span.CopyTo(buffer.AsSpan(HeaderSize));
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the header size for UDP frames.
|
|
/// </summary>
|
|
public static int GetHeaderSize() => HeaderSize;
|
|
}
|