Esempio n. 1
0
        private async Task <bool> OpenHandshake()
        {
            bool handshakeResult = false;

            try
            {
                int terminatorIndex = -1;
                while (!WebSocketHelpers.FindHeaderTerminator(_receiveBuffer, _receiveBufferOffset, out terminatorIndex))
                {
                    int receiveCount = await _stream.ReadAsync(_receiveBuffer, _receiveBufferOffset, _receiveBuffer.Length - _receiveBufferOffset);

                    if (receiveCount == 0)
                    {
                        throw new WebSocketHandshakeException(string.Format(
                                                                  "Handshake with remote [{0}] failed due to receive zero bytes.", RemoteEndPoint));
                    }

                    BufferDeflector.ReplaceBuffer(_bufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount);

                    if (_receiveBufferOffset > 2048)
                    {
                        throw new WebSocketHandshakeException(string.Format(
                                                                  "Handshake with remote [{0}] failed due to receive weird stream.", RemoteEndPoint));
                    }
                }

                string secWebSocketKey = string.Empty;
                string path            = string.Empty;
                string query           = string.Empty;
                handshakeResult = WebSocketServerHandshaker.HandleOpenningHandshakeRequest(this,
                                                                                           _receiveBuffer, 0, terminatorIndex + Consts.HeaderTerminator.Length,
                                                                                           out secWebSocketKey, out path, out query);

                _module = _routeResolver.Resolve(path, query);
                if (_module == null)
                {
                    throw new WebSocketHandshakeException(string.Format(
                                                              "Handshake with remote [{0}] failed due to cannot identify the resource name [{1}{2}].", RemoteEndPoint, path, query));
                }

                if (handshakeResult)
                {
                    var responseBuffer = WebSocketServerHandshaker.CreateOpenningHandshakeResponse(this, secWebSocketKey);
                    await _stream.WriteAsync(responseBuffer, 0, responseBuffer.Length);
                }

                BufferDeflector.ShiftBuffer(_bufferManager, terminatorIndex + Consts.HeaderTerminator.Length, ref _receiveBuffer, ref _receiveBufferOffset);
            }
            catch (ArgumentOutOfRangeException)
            {
                handshakeResult = false;
            }
            catch (WebSocketHandshakeException ex)
            {
                _log.Error(string.Format("Session [{0}] exception occurred, [{1}].", this, ex.Message), ex);
                handshakeResult = false;
            }

            return(handshakeResult);
        }
Esempio n. 2
0
        internal async Task Start()
        {
            int origin = Interlocked.CompareExchange(ref _state, _connecting, _none);

            if (origin == _disposed)
            {
                throw new ObjectDisposedException("This websocket session has been disposed when connecting.");
            }
            else if (origin != _none)
            {
                throw new InvalidOperationException("This websocket session is in invalid state when connecting.");
            }

            try
            {
                ResetKeepAlive();
                ConfigureClient();

                var negotiator = NegotiateStream(_tcpClient.GetStream());
                if (!negotiator.Wait(ConnectTimeout))
                {
                    await Close(WebSocketCloseCode.TlsHandshakeFailed, "SSL/TLS handshake timeout.");

                    throw new TimeoutException(string.Format(
                                                   "Negotiate SSL/TSL with remote [{0}] timeout [{1}].", this.RemoteEndPoint, ConnectTimeout));
                }
                _stream = negotiator.Result;

                _receiveBuffer       = _bufferManager.BorrowBuffer();
                _receiveBufferOffset = 0;

                var handshaker = OpenHandshake();
                if (!handshaker.Wait(ConnectTimeout))
                {
                    throw new TimeoutException(string.Format(
                                                   "Handshake with remote [{0}] timeout [{1}].", this.RemoteEndPoint, ConnectTimeout));
                }
                if (!handshaker.Result)
                {
                    var responseBuffer = WebSocketServerHandshaker.CreateOpenningHandshakeBadRequestResponse(this);
                    await _stream.WriteAsync(responseBuffer, 0, responseBuffer.Length);

                    throw new WebSocketException(string.Format(
                                                     "Handshake with remote [{0}] failed.", this.RemoteEndPoint));
                }

                if (Interlocked.CompareExchange(ref _state, _connected, _connecting) != _connecting)
                {
                    await InternalClose(false); // connected with wrong state

                    throw new ObjectDisposedException("This websocket session has been disposed after connected.");
                }

                _log.DebugFormat("Session started for [{0}] on [{1}] in module [{2}] with session count [{3}].",
                                 this.RemoteEndPoint,
                                 this.StartTime.ToString(@"yyyy-MM-dd HH:mm:ss.fffffff"),
                                 _module.GetType().Name,
                                 this.Server.SessionCount);
                bool isErrorOccurredInUserSide = false;
                try
                {
                    await _module.OnSessionStarted(this);
                }
                catch (Exception ex)
                {
                    isErrorOccurredInUserSide = true;
                    await HandleUserSideError(ex);
                }

                if (!isErrorOccurredInUserSide)
                {
                    _keepAliveTracker.StartTimer();
                    await Process();
                }
                else
                {
                    await InternalClose(true); // user side handle tcp connection error occurred
                }
            }
            catch (Exception ex) when(ex is TimeoutException || ex is WebSocketException)
            {
                _log.Error(string.Format("Session [{0}] exception occurred, [{1}].", this, ex.Message), ex);
                await InternalClose(true); // handle tcp connection error occurred

                throw;
            }
        }