/// <summary>
        /// Implements IOutboundTransport.UnsubscribeClient
        /// </summary>
        public void UnsubscribeClient(string clientId)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (string.IsNullOrEmpty(clientId))
            {
                throw new ArgumentNullException("clientId");
            }

            TlsClient client = null;

            _listLock.AcquireReaderLock(DEFAULT_JOIN_TIMEOUT);
            try
            {
                if (!_clients.ContainsKey(clientId))
                {
                    throw new TransportException("Client not subscribed to transport");
                }
                client = _clients[clientId];

                //Remove
                LockCookie ck = _listLock.UpgradeToWriterLock(DEFAULT_JOIN_TIMEOUT);
                try
                {
                    _clients.Remove(clientId);
                }
                finally
                {
                    _listLock.DowngradeFromWriterLock(ref ck);
                }
            }
            finally
            {
                _listLock.ReleaseReaderLock();
                if (client != null)
                {
                    try
                    {
                        client.Stream.Flush();
                    }
                    catch
                    {
                    }
                    finally
                    {
                        client.Dispose();
                    }
                }
            }
        }
        private void CleanupClients(object state)
        {
            List <string> toRemove = new List <string>();

            /* Scan for dead clients
             * According to MSDN, a client will be detected to be dead
             * only after a failed I/O.
             * If no messages run on channel, lots of dead clients won't be
             * discovered. This is why we force flushing the stream: if client
             * is dead, IOException is triggered and Connected is set to false
             */
            _listLock.AcquireReaderLock(DEFAULT_JOIN_TIMEOUT);
            try
            {
                foreach (KeyValuePair <string, TlsClient> kvp in _clients)
                {
                    try
                    {
                        kvp.Value.Stream.Flush();
                    }
                    catch (IOException)
                    {
                    } //Flush did its real job

                    if (!kvp.Value.Client.Connected)
                    {
                        toRemove.Add(kvp.Key);
                    }
                }

                if (toRemove.Count > 0)
                {
                    LockCookie ck = _listLock.UpgradeToWriterLock(DEFAULT_JOIN_TIMEOUT);
                    try
                    {
                        foreach (string id in toRemove)
                        {
                            try
                            {
                                TlsClient client = _clients[id];
                                _clients.Remove(id);
                                client.Dispose();
                            }
                            catch (KeyNotFoundException ex)
                            {
                                //Strange
                                Log.Debug("Error occurred when purging dead TLS client: {0}", ex.Message);
                            }
                        }
                    }
                    finally
                    {
                        _listLock.DowngradeFromWriterLock(ref ck);
                    }
                }
            }
            finally
            {
                _listLock.ReleaseReaderLock();
            }
            if (toRemove.Count > 0)
            {
                Log.Notice("TLS transport {0} cleaned up {1} dead clients", GetHashCode(), toRemove.Count);
            }
        }