AssuanLibrary 1.0.2
dotnet add package AssuanLibrary --version 1.0.2
NuGet\Install-Package AssuanLibrary -Version 1.0.2
<PackageReference Include="AssuanLibrary" Version="1.0.2" />
<PackageVersion Include="AssuanLibrary" Version="1.0.2" />
<PackageReference Include="AssuanLibrary" />
paket add AssuanLibrary --version 1.0.2
#r "nuget: AssuanLibrary, 1.0.2"
#:package AssuanLibrary@1.0.2
#addin nuget:?package=AssuanLibrary&version=1.0.2
#tool nuget:?package=AssuanLibrary&version=1.0.2
Assuan Library (.NET)
AssuanLibrary is a modern, transport-agnostic .NET implementation of the Assuan protocol, designed to build clients and servers that speak Assuan over multiple transports such as TCP, Named Pipes (Windows), Unix Domain Sockets (Linux), and any other custom transport you implement.
The library focuses on:
- correctness of the Assuan protocol lifecycle
- clean separation between protocol, transport, and application logic
- explicit, hook-based session control
- minimal assumptions about authentication and policy
Features
- Assuan protocol encoder/decoder
- Client and server implementations
- Multi-transport support:
- TCP
- Named Pipes (Windows)
- Unix Domain Sockets (Linux)
- Custom command handlers
- INQUIRE support (sync and async)
- Explicit session lifecycle hooks
- No implicit protocol behavior
- Suitable for embedding or standalone servers
Design Principles
AssuanLibrary follows a few strict principles:
- Transport is not protocol
- Connections know how to read/write bytes, not how to speak Assuan.
- Protocol is explicit
- Nothing is sent automatically unless explicitly configured.
- Lifecycle is deterministic
- Authentication, banner handling, command dispatch, and shutdown all have a defined order.
- Hooks over magic
- Custom behavior is implemented via explicit hooks, not hidden logic.
Supported Transports
| Transport | Platform |
|---|---|
| TCP | Cross-platform |
| Named Pipes | Windows |
| Unix Domain Sockets | Linux / macOS¹ |
Transport selection is done via endpoints if not provided, not by hardcoding logic into the client or server.
PS¹: Unix Domain Sockets are supported on Linux. macOS has not been tested but should work similarly.
Installation
dotnet add package AssuanLibrary
Optional dependency injection helpers (recommended but not required):
dotnet add package AssuanLibrary.Extensions.DependencyInjection
Usage
GnuPG agent client example:
// ----- REQUIRED ONLY FOR TCP CLIENT ON WINDOWS THAT USES GNUPG AGENT -----
var options = new AssuanClientOptions
{
OnSessionAuthenticatingAsync = async (connection, ctx, ct) =>
{
if (ctx.TryGetValue("nonce", out var nonceObj) && nonceObj is byte[] nonce)
{
await connection.WriteAsync(nonce, ct); // Flushes automatically after writing
}
}
};
// ---------------------------------------------------
await using var client = new AssuanClient(options);
await client.ConnectAsync(AssuanEndpointKind.AGENT, ct); // Resolves automatically into the correct transport if not provided on AssuanClient
var command = new AssuanCommand("GETINFO") { "version" };
var responseCollection = await client.InvokeAsync(command, ct);
foreach (var response in responseCollection)
{
Console.WriteLine(response);
}
// ------------------ IF YOU ALREADY KNOWS THE ENDPOINT AND THE NONCE ON WINDOWS ------------------
var tcpEndpoint = new TcpClientEndpoint(IPAddress.Loopback, 12345);
var metadata = new Dictionary<string, object>
{
["nonce"] = System.Text.Encoding.UTF8.GetBytes("my-secret-nonce") // Replace with the actual nonce value
};
await using var client = new AssuanClient();
await client.ConnectAsync(tcpEndpoint, metadata, ct);
var command = new AssuanCommand("GETINFO") { "version" };
var responseCollection = await client.InvokeAsync(command, ct);
foreach (var response in responseCollection)
{
Console.WriteLine(response);
}
// -------------------------------------------------------------------------------------
// Expected output:
// D 2.2.27
// OK
Custom-Server client example:
var options = new AssuanClientOptions // Those options are not required, we are just adding them for demonstration
{
OnSessionStartedAsync = async (connection, ctx, ct) =>
{
if (ctx.TryGetValue("banner", out var bannerObj) && bannerObj is byte[] banner)
{
Console.WriteLine($"Server Banner: {System.Text.Encoding.UTF8.GetString(banner)}");
}
}
};
var serverEndpoint = new TcpClientEndpoint(IPAddress.Loopback, 23456);
await using var client = new AssuanClient(options);
await client.ConnectAsync(serverEndpoint, new Dictionary<string, object>(), ct);
var command = new AssuanCommand("SOME_COMMAND") { "some_argument" };
var responseCollection = await client.InvokeAsync(command, ct);
foreach (var response in responseCollection)
{
Console.WriteLine(response);
}
Custom Server example:
public sealed class GetInfoCommandHandler : CommandHandler
{
/// <inheritdoc />
public override string Name => "GETINFO";
/// <inheritdoc />
public override async Task HandleAsync(IReadOnlyAssuanCommand command, IServerContext serverContext) {
foreach (var arg in command.Arguments) {
switch (arg) {
case "version": {
var responseCollection = AssuanResponseCollection.Create(
AssuanResponse.Data(typeof(GetInfoCommandHandler).Assembly.GetName().Version?.ToString() ?? "unknown"),
AssuanResponse.Ok()
);
await serverContext.SendResponseAsync(responseCollection, serverContext.Session.CancellationToken);
break;
}
case "pid": {
var responseCollection = AssuanResponseCollection.Create(
AssuanResponse.Data(Environment.ProcessId.ToString()),
AssuanResponse.Ok()
);
await serverContext.SendResponseAsync(responseCollection, serverContext.Session.CancellationToken);
break;
}
default:
await serverContext.SendResponseAsync(AssuanResponse.Error(45, "Invalid argument"),
serverContext.Session.CancellationToken);
break;
}
}
}
}
var serverOptions = new AssuanServerOptions
{
Banner = "My Custom Assuan Server"
};
var server = new AssuanServer(serverOptions);
server.RegisterCommandHandler(new GetInfoCommandHandler());
// server.RegisterCommandHandler<GetInfoCommandHandler>();
var tcpEndpoint = new TcpServerEndpoint(IPAddress.Loopback, 23456);
await server.RunAsync(tcpEndpoint, ct);
Contributing
Contributions are welcome! Please refer to the CONTRIBUTING guide for more information.
License
This project is licensed under the MIT License. See the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.2)
- System.Collections.Immutable (>= 10.0.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on AssuanLibrary:
| Package | Downloads |
|---|---|
|
AssuanLibrary.Extensions.DependencyInjection
A .NET library for interacting with the Assuan protocol. |
GitHub repositories
This package is not used by any popular GitHub repositories.