/// <summary>
        /// Builds a <see cref="ClientChannel"/> instance and establish the session using the builder options.
        /// </summary>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public async Task <IClientChannel> BuildAndEstablishAsync(CancellationToken cancellationToken)
        {
            var clientChannel = await ChannelBuilder
                                .BuildAsync(cancellationToken)
                                .ConfigureAwait(false);

            try
            {
                Session session;

                using (var cancellationTokenSource = new CancellationTokenSource(EstablishmentTimeout))
                {
                    using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, cancellationToken))
                    {
                        session = await clientChannel.EstablishSessionAsync(
                            _compressionSelector,
                            _encryptionSelector,
                            Identity,
                            _authenticator,
                            Instance,
                            linkedCts.Token)
                                  .ConfigureAwait(false);
                    }
                }

                if (session.State != SessionState.Established)
                {
                    var reason = session.Reason ?? new Reason()
                    {
                        Code        = ReasonCodes.GENERAL_ERROR,
                        Description = "Could not establish the session for an unknown reason"
                    };

                    throw new LimeException(reason);
                }

                foreach (var handler in _establishedHandlers.ToList())
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    await handler(clientChannel, cancellationToken).ConfigureAwait(false);
                }
            }
            catch
            {
                clientChannel.DisposeIfDisposable();
                throw;
            }

            return(clientChannel);
        }