Exemple #1
0
        /// <summary>
        /// Sends the handshake asynchronous.
        /// </summary>
        /// <param name="handshake">The handshake.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public async Task <WebSocketResponseHandshake> SendHandshakeAsync(WebSocketRequestHandshake handshake, CancellationToken cancellationToken)
        {
            var oldState = Interlocked.CompareExchange(ref _state, WebSocketState.Opening, WebSocketState.Connected);

            if (oldState != WebSocketState.Connected)
            {
                throw new InvalidOperationException(ErrorMessages.InvalidState + _state);
            }

            var data = handshake.ToString();

            await this.SendAsync(data, Encoding.UTF8, cancellationToken);

            var responseHeaders = new List <string>();
            var line            = await _tcp.ReadLineAsync(cancellationToken);

            while (!String.IsNullOrEmpty(line))
            {
                responseHeaders.Add(line);
                line = await _tcp.ReadLineAsync(cancellationToken);
            }

            var response = WebSocketResponseHandshake.Parse(responseHeaders);

            if (response.StatusCode != HttpStatusCode.SwitchingProtocols)
            {
                var versions = response.SecWebSocketVersion;
                if (versions != null && !versions.Intersect(Consts.SupportedClientVersions).Any())
                {
                    throw new WebSocketException(WebSocketErrorCode.HandshakeVersionNotSupported);
                }

                throw new WebSocketException(WebSocketErrorCode.HandshakeInvalidStatusCode);
            }

            var challenge        = Encoding.UTF8.GetBytes(handshake.SecWebSocketKey + Consts.ServerGuid);
            var hash             = Sha1Digest.ComputeHash(challenge);
            var calculatedAccept = Convert.ToBase64String(hash);

            if (response.SecWebSocketAccept != calculatedAccept)
            {
                throw new WebSocketException(WebSocketErrorCode.HandshakeInvalidSecWebSocketAccept);
            }

            response.RequestMessage = handshake;

            Interlocked.Exchange(ref _state, WebSocketState.Open);


            return(response);
        }