Runtime: Error when unix socket is used with SocketsHttpConnectionFactory

Created on 5 Aug 2020  路  9Comments  路  Source: dotnet/runtime

I'm trying to use the new SocketsHttpConnectionFactory with a unix socket. I'm inheriting from the factory:

public class UnixDomainSocketsConnectionFactory : SocketsHttpConnectionFactory
{
    private readonly UnixDomainSocketEndPoint _endPoint;

    public UnixDomainSocketsConnectionFactory(UnixDomainSocketEndPoint endPoint)
    {
        _endPoint = endPoint;
    }

    public override Socket CreateSocket(HttpRequestMessage message, EndPoint? endPoint, IConnectionProperties options)
    {
        return new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
    }

    public override async ValueTask<Connection> EstablishConnectionAsync(HttpRequestMessage message, EndPoint? endPoint, IConnectionProperties options, CancellationToken cancellationToken)
    {
        var connection = await base.EstablishConnectionAsync(message, _endPoint, options, cancellationToken);

        return connection;
    }
}

An error is thrown when establishing the connection: SocketException: An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call.

This happens when Socket.NoDelay is set to true in EstablishConnectionAsync - https://github.com/dotnet/runtime/blob/a1339cc3e41cee79bfbeafde9a7462523f70cef4/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpConnectionFactory.cs#L79

Right now the built-in factory can't be used with UDS. To skip that one line I would need to copy at least EstablishConnectionAsync, SocketConnection (it is internal), SocketConnectionNetworkStream and TaskSocketAsyncEventArgs into my own implementation.

Is there a way to detect whether that flag is supported? Or eat the exception if SocketException with an error code of Protocol is thrown?

area-System.Net.Http bug

Most helpful comment

As I previously noted offline to @scalablecory, the setting of NoDelay should be in the factory's CreateSocket, not in SocketsHttpHandler; otherwise the setting can't be overridden. This issue is one more example in support of that.

All 9 comments

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

That's interesting.

Not sure whether or not SocketsHttpConnectionFactory is intended to work with UDS -- @scalablecory?

As a workaround, you can just create your own ConnectionFactory implementation, it's not that much code. And we want that to be straightfoward to do, so if it's not, that would be good to know, too...

I assumed it is because CreateSocket is an override extension point.

Alternative fix idea: Move NoDelay = true to SocketsHttpConnectionFactory.CreateSocket. If your socket protocol doesn't support NoDelay then don't set it when you override the method.

Alternative fix idea: Move NoDelay = true to SocketsHttpConnectionFactory.CreateSocket.

That seems like a good fix to me. That's sorta what CreateSocket is for...

I thought HttpClient over domain sockets was a key scenario. I certainly have been waiting for 5.0 for this feature. According to @geoffkizer it still should be possible but may be more work. I suppose that's fine, but it'd be nice if it's as easy as the pasted code in the OP.

Feels like this should be supported OOTB TBH, the default implementation should just support UDS. I'd bet it's a pretty small change to make.

I agree, we should make this scenario work.

As I previously noted offline to @scalablecory, the setting of NoDelay should be in the factory's CreateSocket, not in SocketsHttpHandler; otherwise the setting can't be overridden. This issue is one more example in support of that.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GitAntoinee picture GitAntoinee  路  3Comments

matty-hall picture matty-hall  路  3Comments

Timovzl picture Timovzl  路  3Comments

yahorsi picture yahorsi  路  3Comments

iCodeWebApps picture iCodeWebApps  路  3Comments