grpc/grpc-dotnet

Connecting to gRPC Server over Unix Domain Socket

thegreatco opened this issue · 1 comments

Following the example in the docs, I tried to connect to a gRPC server listening on a Unix Domain Socket. I created a small program to test it

using System.Net;
using System.Net.Sockets;

using Grpc.Net.Client;

var socketPath = "/tmp/foo.sock";
var udsEndPoint = new UnixDomainSocketEndPoint(socketPath);
var connectionFactory = new UnixDomainSocketsConnectionFactory(udsEndPoint);
var socketsHttpHandler = new SocketsHttpHandler
{
    ConnectCallback = connectionFactory.ConnectAsync
};

var grpc = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
{
    HttpHandler = socketsHttpHandler
});

await grpc.ConnectAsync();

public class UnixDomainSocketsConnectionFactory
{
    private readonly EndPoint endPoint;

    public UnixDomainSocketsConnectionFactory(EndPoint endPoint)
    {
        this.endPoint = endPoint;
    }

    public async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext _,
                                                CancellationToken cancellationToken = default)
    {
        var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);

        try
        {
            await socket.ConnectAsync(this.endPoint, cancellationToken).ConfigureAwait(false);
            return new NetworkStream(socket, true);
        }
        catch
        {
            socket.Dispose();
            throw;
        }
    }
}

However, I am getting the following error:

Unhandled exception. System.InvalidOperationException: Channel is configured with an HTTP transport doesn't support client-side load balancing or connectivity state tracking. The underlying HTTP transport must be a SocketsHttpHandler with no SocketsHttpHandler.ConnectCallback configured. The HTTP transport must be configured on the channel using GrpcChannelOptions.HttpHandler.
   at Grpc.Net.Client.GrpcChannel.ValidateHttpHandlerSupportsConnectivity()
   at Grpc.Net.Client.GrpcChannel.ConnectAsync(CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in /mnt/d/Dropbox/dev/GitHub/viam-dotnet-sdk/examples/ConsoleApp1/Program.cs:line 20
   at Program.<Main>(String[] args)
Aborted

I'm guessing this behavior changed since 1-Jan-2024, but not sure what the solution is here.

ConnectAsync isn't supported when using unix domain sockets. Remove it and make gRPC calls as usual.