forked from dotnet/Docker.DotNet
-
-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathDockerHandlerFactory.cs
More file actions
90 lines (68 loc) · 3.13 KB
/
DockerHandlerFactory.cs
File metadata and controls
90 lines (68 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
namespace Docker.DotNet.NPipe;
public sealed class DockerHandlerFactory : IDockerHandlerFactory<NPipeTransportOptions>
{
private DockerHandlerFactory()
{
}
public static IDockerHandlerFactory<NPipeTransportOptions> Instance { get; }
= new DockerHandlerFactory();
public ResolvedTransport CreateHandler(ClientOptions clientOptions, ILogger logger)
{
var transportOptions = new NPipeTransportOptions();
Validate(transportOptions, clientOptions);
return CreateHandler(transportOptions, clientOptions, logger);
}
public ResolvedTransport CreateHandler(NPipeTransportOptions transportOptions, ClientOptions clientOptions, ILogger logger)
{
Validate(transportOptions, clientOptions);
if (clientOptions.AuthProvider.TlsEnabled)
{
throw new NotSupportedException("TLS is not supported over npipe.");
}
var uri = clientOptions.Endpoint;
var segments = uri.Segments;
if (segments.Length != 3 || !"pipe/".Equals(segments[1], StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The endpoint is not a npipe URI.");
}
var pipeName = uri.Segments[2];
var serverName = "localhost".Equals(uri.Host, StringComparison.OrdinalIgnoreCase) ? "." : uri.Host;
uri = new UriBuilder(Uri.UriSchemeHttp, pipeName).Uri;
var streamOpener = new ManagedHandler.StreamOpener(async (_, _, cancellationToken) =>
{
var clientStream = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
var dockerStream = new DockerPipeStream(clientStream);
#if NET
var namedPipeConnectTimeout = transportOptions.ConnectTimeout;
#else
var namedPipeConnectTimeout = (int)transportOptions.ConnectTimeout.TotalMilliseconds;
#endif
await clientStream.ConnectAsync(namedPipeConnectTimeout, cancellationToken)
.ConfigureAwait(false);
return dockerStream;
});
var handler = new ManagedHandler(streamOpener, logger);
transportOptions.ConfigureHandler(handler);
return new ResolvedTransport(handler, uri);
}
public Task<WriteClosableStream> HijackStreamAsync(HttpContent content)
{
if (content is not HttpConnectionResponseContent hijackable)
{
throw new NotSupportedException("The content type is not supported for stream hijacking.");
}
return Task.FromResult(hijackable.HijackStream());
}
private static void Validate(NPipeTransportOptions _, ClientOptions clientOptions)
{
if (clientOptions.Endpoint is null)
{
throw new ArgumentNullException(nameof(clientOptions), "ClientOptions.Endpoint must be set.");
}
var scheme = clientOptions.Endpoint.Scheme;
if (!string.Equals(scheme, "npipe", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException($"The selected '{nameof(NPipeTransportOptions)}' can only be used with endpoint scheme 'npipe', but '{scheme}' was provided.");
}
}
}