using System; 
 | 
using System.Collections.Generic; 
 | 
using Taobao.Top.Link.Channel.WebSocket; 
 | 
using Top.Api; 
 | 
  
 | 
namespace Taobao.Top.Link.Channel 
 | 
{ 
 | 
    /// <summary>a channel pool that same uri sharing same channel 
 | 
    /// </summary> 
 | 
    public class ClientChannelSharedSelector : IClientChannelSelector 
 | 
    { 
 | 
        private static readonly int CONNECTTIMEOUT = 5000; 
 | 
        private ITopLogger _logger; 
 | 
        private Object _lockObject; 
 | 
        private IDictionary<string, IClientChannel> _channels; 
 | 
  
 | 
        /// <summary>get or set heartbeat interval time in milliseconds 
 | 
        /// </summary> 
 | 
        public int HeartbeatPeriod { get; set; } 
 | 
  
 | 
        public ClientChannelSharedSelector() : this(Log.Instance) { } 
 | 
        public ClientChannelSharedSelector(ITopLogger logger) 
 | 
        { 
 | 
            this._logger = logger; 
 | 
            this._lockObject = new object(); 
 | 
            this._channels = new Dictionary<string, IClientChannel>(); 
 | 
        } 
 | 
  
 | 
        public IClientChannel GetChannel(Uri uri) 
 | 
        { 
 | 
            if (!uri.Scheme.Equals("ws", StringComparison.InvariantCultureIgnoreCase)) 
 | 
                return null; 
 | 
  
 | 
            var url = uri.ToString(); 
 | 
  
 | 
            if (!this.HaveChannel(url)) 
 | 
                lock (this._lockObject) 
 | 
                    if (!this.HaveChannel(url)) 
 | 
                        this.AddChannel(url, this.WrapChannel(this.Connect(uri, CONNECTTIMEOUT))); 
 | 
  
 | 
            return _channels[url]; 
 | 
        } 
 | 
        public void ReturnChannel(IClientChannel channel) { } 
 | 
  
 | 
        protected virtual IClientChannel Connect(Uri uri, int timeout) 
 | 
        { 
 | 
            return WebSocketClient.Connect(this._logger, uri, timeout); 
 | 
        } 
 | 
        private IClientChannel WrapChannel(IClientChannel channel) 
 | 
        { 
 | 
            if (this.HeartbeatPeriod > 0) 
 | 
                channel.HeartbeatTimer = new ResetableTimer(this.HeartbeatPeriod); 
 | 
            return channel; 
 | 
        } 
 | 
        private bool HaveChannel(string url) 
 | 
        { 
 | 
            return this._channels.ContainsKey(url) && this._channels[url].IsConnected; 
 | 
        } 
 | 
        private void AddChannel(string url, IClientChannel channel) 
 | 
        { 
 | 
            if (this._channels.ContainsKey(url)) 
 | 
                this._channels[url] = channel; 
 | 
            else 
 | 
                this._channels.Add(url, channel); 
 | 
        } 
 | 
    } 
 | 
} 
 |