| | 1 | | // Copyright (c) ZeroC, Inc. |
| | 2 | |
|
| | 3 | | using IceRpc.Internal; |
| | 4 | | using IceRpc.Transports; |
| | 5 | | using Microsoft.Extensions.Logging; |
| | 6 | | using Microsoft.Extensions.Logging.Abstractions; |
| | 7 | | using System.Net.Security; |
| | 8 | |
|
| | 9 | | namespace IceRpc; |
| | 10 | |
|
| | 11 | | /// <summary>Default implementation of <see cref="IClientProtocolConnectionFactory" />.</summary> |
| | 12 | | public sealed class ClientProtocolConnectionFactory : IClientProtocolConnectionFactory |
| | 13 | | { |
| | 14 | | private readonly SslClientAuthenticationOptions? _clientAuthenticationOptions; |
| | 15 | | private readonly ConnectionOptions _connectionOptions; |
| | 16 | | private readonly IDuplexClientTransport _duplexClientTransport; |
| | 17 | | private readonly DuplexConnectionOptions _duplexConnectionOptions; |
| | 18 | | private readonly ILogger _logger; |
| | 19 | | private readonly IMultiplexedClientTransport _multiplexedClientTransport; |
| | 20 | | private readonly MultiplexedConnectionOptions _multiplexedConnectionOptions; |
| | 21 | |
|
| | 22 | | /// <summary>Constructs a client protocol connection factory.</summary> |
| | 23 | | /// <param name="connectionOptions">The connection options.</param> |
| | 24 | | /// <param name="clientAuthenticationOptions">The client authentication options.</param> |
| | 25 | | /// <param name="duplexClientTransport">The duplex client transport. <see langword="null" /> is equivalent to <see |
| | 26 | | /// cref="IDuplexClientTransport.Default" />.</param> |
| | 27 | | /// <param name="multiplexedClientTransport">The multiplexed client transport. <see langword="null" /> is equivalent |
| | 28 | | /// to <see cref="IMultiplexedClientTransport.Default" />.</param> |
| | 29 | | /// <param name="logger">The logger. <see langword="null" /> is equivalent to <see cref="NullLogger.Instance" />.</p |
| 155 | 30 | | public ClientProtocolConnectionFactory( |
| 155 | 31 | | ConnectionOptions connectionOptions, |
| 155 | 32 | | SslClientAuthenticationOptions? clientAuthenticationOptions = null, |
| 155 | 33 | | IDuplexClientTransport? duplexClientTransport = null, |
| 155 | 34 | | IMultiplexedClientTransport? multiplexedClientTransport = null, |
| 155 | 35 | | ILogger? logger = null) |
| 155 | 36 | | { |
| 155 | 37 | | _clientAuthenticationOptions = clientAuthenticationOptions; |
| 155 | 38 | | _connectionOptions = connectionOptions; |
| | 39 | |
|
| 155 | 40 | | _duplexClientTransport = duplexClientTransport ?? IDuplexClientTransport.Default; |
| 155 | 41 | | _duplexConnectionOptions = new DuplexConnectionOptions |
| 155 | 42 | | { |
| 155 | 43 | | Pool = connectionOptions.Pool, |
| 155 | 44 | | MinSegmentSize = connectionOptions.MinSegmentSize, |
| 155 | 45 | | }; |
| | 46 | |
|
| 155 | 47 | | _multiplexedClientTransport = multiplexedClientTransport ?? IMultiplexedClientTransport.Default; |
| | 48 | |
|
| | 49 | | // If the dispatcher is null, we don't allow the peer to open streams for incoming requests. The only stream |
| | 50 | | // which is accepted locally is the control stream created by the peer. |
| 155 | 51 | | _multiplexedConnectionOptions = new MultiplexedConnectionOptions |
| 155 | 52 | | { |
| 155 | 53 | | MaxBidirectionalStreams = connectionOptions.Dispatcher is null ? 0 : |
| 155 | 54 | | connectionOptions.MaxIceRpcBidirectionalStreams, |
| 155 | 55 | |
|
| 155 | 56 | | // Add an additional stream for the icerpc protocol control stream. |
| 155 | 57 | | MaxUnidirectionalStreams = connectionOptions.Dispatcher is null ? 1 : |
| 155 | 58 | | connectionOptions.MaxIceRpcUnidirectionalStreams + 1, |
| 155 | 59 | |
|
| 155 | 60 | | Pool = connectionOptions.Pool, |
| 155 | 61 | | MinSegmentSize = connectionOptions.MinSegmentSize, |
| 155 | 62 | | }; |
| | 63 | |
|
| 155 | 64 | | _logger = logger ?? NullLogger.Instance; |
| 155 | 65 | | } |
| | 66 | |
|
| | 67 | | /// <summary>Creates a protocol connection to the specified server address.</summary> |
| | 68 | | /// <param name="serverAddress">The address of the server.</param> |
| | 69 | | /// <returns>The new protocol connection.</returns> |
| | 70 | | /// <remarks>The protocol connection returned by this factory method is not connected. The caller must call |
| | 71 | | /// <see cref="IProtocolConnection.ConnectAsync" /> exactly once on this connection before calling |
| | 72 | | /// <see cref="IInvoker.InvokeAsync" />.</remarks> |
| | 73 | | public IProtocolConnection CreateConnection(ServerAddress serverAddress) |
| 164 | 74 | | { |
| 164 | 75 | | IProtocolConnection connection = |
| 164 | 76 | | serverAddress.Protocol == Protocol.Ice ? |
| 164 | 77 | | new IceProtocolConnection( |
| 164 | 78 | | _duplexClientTransport.CreateConnection( |
| 164 | 79 | | serverAddress, |
| 164 | 80 | | _duplexConnectionOptions, |
| 164 | 81 | | _clientAuthenticationOptions), |
| 164 | 82 | | transportConnectionInformation: null, |
| 164 | 83 | | _connectionOptions) : |
| 164 | 84 | | new IceRpcProtocolConnection( |
| 164 | 85 | | _multiplexedClientTransport.CreateConnection( |
| 164 | 86 | | serverAddress, |
| 164 | 87 | | _multiplexedConnectionOptions, |
| 164 | 88 | | _clientAuthenticationOptions), |
| 164 | 89 | | transportConnectionInformation: null, |
| 164 | 90 | | _connectionOptions, |
| 164 | 91 | | taskExceptionObserver: _logger == NullLogger.Instance ? null : |
| 164 | 92 | | new LogTaskExceptionObserver(_logger)); |
| | 93 | |
|
| 164 | 94 | | connection = new MetricsProtocolConnectionDecorator(connection, Metrics.ClientMetrics, connectStarted: false); |
| | 95 | |
|
| 164 | 96 | | return _logger == NullLogger.Instance ? connection : |
| 164 | 97 | | new LogProtocolConnectionDecorator(connection, serverAddress, remoteNetworkAddress: null, _logger); |
| 164 | 98 | | } |
| | 99 | | } |