feat: add ERP agent pet bridge and startup guide
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
using System.Buffers.Binary;
|
||||
|
||||
namespace Lskj.AgentPet.Host.Core.ErpBridge;
|
||||
|
||||
public static class BridgeFrameCodec
|
||||
{
|
||||
public const int MaxMessageBytes = 1024 * 1024;
|
||||
|
||||
public static async Task WriteAsync(
|
||||
Stream stream,
|
||||
ReadOnlyMemory<byte> body,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(stream);
|
||||
if (body.Length is <= 0 or > MaxMessageBytes)
|
||||
throw new HostError("bridge_protocol_error", "ERP 桥请求长度无效或超过 1 MB。");
|
||||
byte[] header = new byte[4];
|
||||
BinaryPrimitives.WriteInt32LittleEndian(header, body.Length);
|
||||
await stream.WriteAsync(header, cancellationToken).ConfigureAwait(false);
|
||||
await stream.WriteAsync(body, cancellationToken).ConfigureAwait(false);
|
||||
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static async Task<byte[]> ReadAsync(
|
||||
Stream stream,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(stream);
|
||||
byte[] header = new byte[4];
|
||||
await ReadExactlyAsync(stream, header, cancellationToken).ConfigureAwait(false);
|
||||
int length = BinaryPrimitives.ReadInt32LittleEndian(header);
|
||||
if (length is <= 0 or > MaxMessageBytes)
|
||||
throw new HostError("bridge_protocol_error", "ERP 桥响应长度无效或超过 1 MB。");
|
||||
byte[] body = new byte[length];
|
||||
await ReadExactlyAsync(stream, body, cancellationToken).ConfigureAwait(false);
|
||||
return body;
|
||||
}
|
||||
|
||||
private static async Task ReadExactlyAsync(
|
||||
Stream stream,
|
||||
Memory<byte> target,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
int offset = 0;
|
||||
while (offset < target.Length)
|
||||
{
|
||||
int count = await stream.ReadAsync(target[offset..], cancellationToken).ConfigureAwait(false);
|
||||
if (count == 0)
|
||||
throw new HostError("bridge_disconnected", "ERP 桥在完整消息到达前关闭。");
|
||||
offset += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user