Files
webhook-server/src/WebhookServer.Core/Ipc/PipeFraming.cs
T
justin 8ecfe84540 Initial WebhookServer implementation
Add the .NET 8 solution scaffolded against PLAN.md. Three projects share
WebhookServer.Core (models, auth, execution, storage, IPC, callbacks)
and WebhookServer.Service hosts an embedded Kestrel listener plus the
named-pipe admin server. WebhookServer.Gui is a thin MVVM client over
the pipe. Includes 25 unit tests covering HMAC verification, bearer
auth, IP allowlist parsing, arg-template rendering, DPAPI round-trip,
and the encrypt-on-save config store.

Install/uninstall PowerShell scripts default to LocalSystem and accept
a domain user or gMSA via -ServiceAccount.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:04:52 -04:00

30 lines
1.1 KiB
C#

using System.Text;
using System.Text.Json;
namespace WebhookServer.Core.Ipc;
/// <summary>
/// Line-delimited JSON over a stream. One JSON object per line, terminated by '\n'.
/// </summary>
public static class PipeFraming
{
public static async Task WriteAsync<T>(Stream stream, T payload, CancellationToken ct)
{
var bytes = JsonSerializer.SerializeToUtf8Bytes(payload, AdminProtocol.JsonOptions);
await stream.WriteAsync(bytes, ct).ConfigureAwait(false);
await stream.WriteAsync(new byte[] { (byte)'\n' }, ct).ConfigureAwait(false);
await stream.FlushAsync(ct).ConfigureAwait(false);
}
public static async Task<T?> ReadAsync<T>(StreamReader reader, CancellationToken ct)
{
var line = await reader.ReadLineAsync(ct).ConfigureAwait(false);
if (line is null) return default;
if (string.IsNullOrWhiteSpace(line)) return default;
return JsonSerializer.Deserialize<T>(line, AdminProtocol.JsonOptions);
}
public static StreamReader CreateReader(Stream stream) =>
new(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 4096, leaveOpen: true);
}