File: System\ServiceModel\Channels\UnixDomainSocketChannelFactory.cs
Web Access
Project: src\src\System.ServiceModel.UnixDomainSocket\src\System.ServiceModel.UnixDomainSocket.csproj (System.ServiceModel.UnixDomainSocket)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
 
namespace System.ServiceModel.Channels
{
    internal sealed class UnixDomainSocketChannelFactory<TChannel> : NetFramingTransportChannelFactory<TChannel>, IConnectionPoolSettings
    {
        public UnixDomainSocketChannelFactory(UnixDomainSocketTransportBindingElement bindingElement, BindingContext context)
            : base(bindingElement, context,
            bindingElement.ConnectionPoolSettings.GroupName,
            bindingElement.ConnectionPoolSettings.IdleTimeout,
            bindingElement.ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint)
        {
            LeaseTimeout = bindingElement.ConnectionPoolSettings.LeaseTimeout;
        }
 
        public TimeSpan LeaseTimeout { get; }
 
        public override string Scheme
        {
            get { return "net.uds"; }
        }
 
        public override IConnectionInitiator GetConnectionInitiator()
        {
            return new SocketConnectionInitiator(ConnectionBufferSize);
        }
 
        ///TODO Check with Matt
        protected override string GetConnectionPoolKey(EndpointAddress address, Uri via)
        {
            return via.AbsolutePath;
        }
 
        protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
        {
            if(address.Identity == null)
            {
                var hostIdentity = new DnsEndpointIdentity(string.IsNullOrEmpty(address.Uri.Host) ? "localhost" : address.Uri.Host);
                var uriBuilder = new UriBuilder(address.Uri);
                uriBuilder.Host = null;
                address = new EndpointAddress(uriBuilder.Uri, hostIdentity,address.Headers.ToArray());
            }
 
            if(via !=null)
            {
                var uriBuilder = new UriBuilder(via);
                uriBuilder.Host = null;
                via = uriBuilder.Uri;
            }
 
            return base.OnCreateChannel(address,via);
        }
        public override T GetProperty<T>()
        {
            if (typeof(T) == typeof(IConnectionPoolSettings))
            {
                return (T)(object)this;
            }
 
            return base.GetProperty<T>();
        }
 
        T IConnectionPoolSettings.GetConnectionPoolSetting<T>(string settingName)
        {
            if (typeof(T) == typeof(TimeSpan))
            {
                TimeSpan temp;
                switch (settingName)
                {
                    case nameof(LeaseTimeout):
                        temp = LeaseTimeout;
                        break;
                    case nameof(IdleTimeout):
                        temp = IdleTimeout;
                        break;
                    case nameof(MaxOutputDelay):
                        temp = MaxOutputDelay;
                        break;
                    default:
                        return default(T);
                }
                return Unsafe.As<TimeSpan, T>(ref temp);
            }
 
            if (typeof(T) == typeof(int))
            {
                int temp;
                switch (settingName)
                {
                    case nameof(ConnectionBufferSize):
                        temp = ConnectionBufferSize;
                        break;
                    case nameof(MaxOutboundConnectionsPerEndpoint):
                        temp = MaxOutboundConnectionsPerEndpoint;
                        break;
                    default:
                        return default(T);
                }
                return Unsafe.As<int, T>(ref temp);
            }
 
            if (typeof(T) == typeof(string))
            {
                if (settingName == nameof(ConnectionPoolGroupName))
                    return (T)(object)ConnectionPoolGroupName;
            }
 
            return default(T);
        }
 
        bool IConnectionPoolSettings.IsCompatible(IConnectionPoolSettings other)
        {
            // Other must be a TcpChannelFactory
            if (other.GetType().IsConstructedGenericType)
            {
                if (other.GetType().GetGenericTypeDefinition() != typeof(UnixDomainSocketChannelFactory<>))
                {
                    return false;
                }
            }
             
            return (LeaseTimeout == other.GetConnectionPoolSetting<TimeSpan>(nameof(LeaseTimeout))) &&
                   (ConnectionPoolGroupName == other.GetConnectionPoolSetting<string>(nameof(ConnectionPoolGroupName))) &&
                   (ConnectionBufferSize == other.GetConnectionPoolSetting<int>(nameof(ConnectionBufferSize))) &&
                   (MaxOutboundConnectionsPerEndpoint == other.GetConnectionPoolSetting<int>(nameof(MaxOutboundConnectionsPerEndpoint))) &&
                   (IdleTimeout == other.GetConnectionPoolSetting<TimeSpan>(nameof(IdleTimeout))) &&
                   (MaxOutputDelay == other.GetConnectionPoolSetting<TimeSpan>(nameof(MaxOutputDelay)));
        }
    }
}