public async Task PerformClientHandshake(CancellationToken token)
        {
            if (this._isHandshaking)
            {
                throw new InvalidOperationException("Handshake already in progress");
            }

            if (this._isAuthenticated)
            {
                throw new InvalidOperationException("Renegotiation not supported");
            }

            // Create record protocol handler
            this._recordHandler = new RecordHandler(this._securityParameters.MinimumVersion, isClient: true);

            // Create handshake protocol sub handler
            this._handshakeSession = new ClientHandshakeSession(this._securityParameters);
            this._isHandshaking = true;

            await this.SendClientHello(token);
            await this.ReceiveServerHello(token);
            await this.SendClientKeyExchange(token);

            await this.ReceiveAlert(token);

            await this.SendClientChangeCipherSpec(token);
            await this.SendClientFinished(token);
            await this.ReceiveChangeCipherSpecAndFinished(token);

            this._isHandshaking = false;
            this._isAuthenticated = true;
        }
        public async Task PerformServerHandshake(X509Certificate serverCertificate, CancellationToken token)
        {
            if (this._isHandshaking)
            {
                throw new InvalidOperationException("Handshake already in progress");
            }

            if (this._isAuthenticated)
            {
                throw new InvalidOperationException("Renegotiation not supported");
            }

            this._recordHandler = new RecordHandler(this._securityParameters.MinimumVersion, isClient: false);
            this._handshakeSession = new ServerHandshakeSession(this._securityParameters, this.logger);
            this._isHandshaking = true;

            var timoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
            var cts = CancellationTokenSource.CreateLinkedTokenSource(token, timoutCts.Token);

            await this.ReceiveClientHello(cts.Token);
            await this.SendServerHello(cts.Token);
            await this.ReceiveClientKeyExchangeChangeCipherSpecAndFinished(cts.Token);
            await this.SendServerChangeCipherSpec(cts.Token);
            await this.SendServerFinished(cts.Token);

            this._isHandshaking = false;
            this._isAuthenticated = true;
        }