Esempio n. 1
0
        public void Close(WebSocketCloseCode closeCode, string closeReason)
        {
            if (State == WebSocketState.Closed || State == WebSocketState.None)
            {
                return;
            }

            var priorState = Interlocked.Exchange(ref _state, _closing);

            switch (priorState)
            {
            case _connected:
            {
                var closingHandshake = new CloseFrame(closeCode, closeReason).ToArray(_frameBuilder);
                try
                {
                    if (_stream.CanWrite)
                    {
                        StartClosingTimer();
                        var ar = _stream.BeginWrite(closingHandshake, 0, closingHandshake.Length, null, _stream);
                        if (!ar.AsyncWaitHandle.WaitOne(ConnectTimeout))
                        {
                            InternalClose(true);
                            throw new TimeoutException(string.Format(
                                                           "Closing handshake with remote [{0}] timeout [{1}].", RemoteEndPoint, ConnectTimeout));
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (ShouldThrow(ex))
                    {
                        throw;
                    }
                }
                return;
            }

            case _connecting:
            case _closing:
            {
                InternalClose(true);
                return;
            }

            case _disposed:
            case _none:
            default:
                return;
            }
        }
Esempio n. 2
0
        public async Task Close(WebSocketCloseCode closeCode, string closeReason)
        {
            if (State == WebSocketState.Closed || State == WebSocketState.None)
            {
                return;
            }

            var priorState = Interlocked.Exchange(ref _state, _closing);

            switch (priorState)
            {
            case _connected:
            {
                var closingHandshake = new CloseFrame(closeCode, closeReason, false).ToArray(_frameBuilder);
                try
                {
                    if (_stream.CanWrite)
                    {
                        await _stream.WriteAsync(closingHandshake, 0, closingHandshake.Length);

                        StartClosingTimer();
#if DEBUG
                        _log.DebugFormat("Session [{0}] sends server side close frame [{1}] [{2}].", this, closeCode, closeReason);
#endif
                    }
                }
                catch (Exception ex) when(!ShouldThrow(ex))
                {
                }
                return;
            }

            case _connecting:
            case _closing:
            {
                await Close();

                return;
            }

            case _disposed:
            case _none:
            default:
                return;
            }
        }
Esempio n. 3
0
        public byte[] EncodeFrame(CloseFrame frame)
        {
            // The Close frame MAY contain a body (the "Application data" portion of
            // the frame) that indicates a reason for closing, such as an endpoint
            // shutting down, an endpoint having received a frame too large, or an
            // endpoint having received a frame that does not conform to the format
            // expected by the endpoint.  If there is a body, the first two bytes of
            // the body MUST be a 2-byte unsigned integer (in network byte order)
            // representing a status code with value /code/ defined in Section 7.4.
            // Following the 2-byte integer, the body MAY contain UTF-8-encoded data
            // with value /reason/, the interpretation of which is not defined by
            // this specification.  This data is not necessarily human readable but
            // may be useful for debugging or passing information relevant to the
            // script that opened the connection.  As the data is not guaranteed to
            // be human readable, clients MUST NOT show it to end users.
            int payloadLength = (string.IsNullOrEmpty(frame.CloseReason) ? 0 : Encoding.UTF8.GetMaxByteCount(frame.CloseReason.Length)) + 2;

            if (payloadLength > 125)
            {
                throw new WebSocketException("All control frames must have a payload length of 125 bytes or less.");
            }

            byte[] payload = new byte[payloadLength];

            int higherByte = (int)frame.CloseCode / 256;
            int lowerByte  = (int)frame.CloseCode % 256;

            payload[0] = (byte)higherByte;
            payload[1] = (byte)lowerByte;

            if (!string.IsNullOrEmpty(frame.CloseReason))
            {
                int count = Encoding.UTF8.GetBytes(frame.CloseReason, 0, frame.CloseReason.Length, payload, 2);
                return(Encode(frame.OpCode, payload, 0, 2 + count, isMasked: frame.IsMasked));
            }
            else
            {
                return(Encode(frame.OpCode, payload, 0, payload.Length, isMasked: frame.IsMasked));
            }
        }
Esempio n. 4
0
        public byte[] EncodeFrame(CloseFrame frame)
        {
            // The Close frame MAY contain a body (the "Application data" portion of
            // the frame) that indicates a reason for closing, such as an endpoint
            // shutting down, an endpoint having received a frame too large, or an
            // endpoint having received a frame that does not conform to the format
            // expected by the endpoint.  If there is a body, the first two bytes of
            // the body MUST be a 2-byte unsigned integer (in network byte order)
            // representing a status code with value /code/ defined in Section 7.4.
            // Following the 2-byte integer, the body MAY contain UTF-8-encoded data
            // with value /reason/, the interpretation of which is not defined by
            // this specification.  This data is not necessarily human readable but
            // may be useful for debugging or passing information relevant to the
            // script that opened the connection.  As the data is not guaranteed to
            // be human readable, clients MUST NOT show it to end users.
            int payloadLength = (string.IsNullOrEmpty(frame.CloseReason) ? 0 : Encoding.UTF8.GetMaxByteCount(frame.CloseReason.Length)) + 2;
            if (payloadLength > 125)
                throw new WebSocketException("All control frames must have a payload length of 125 bytes or less.");

            byte[] payload = new byte[payloadLength];

            int higherByte = (int)frame.CloseCode / 256;
            int lowerByte = (int)frame.CloseCode % 256;

            payload[0] = (byte)higherByte;
            payload[1] = (byte)lowerByte;

            if (!string.IsNullOrEmpty(frame.CloseReason))
            {
                int count = Encoding.UTF8.GetBytes(frame.CloseReason, 0, frame.CloseReason.Length, payload, 2);
                return Encode(frame.OpCode, payload, 0, 2 + count, isMasked: frame.IsMasked);
            }
            else
            {
                return Encode(frame.OpCode, payload, 0, payload.Length, isMasked: frame.IsMasked);
            }
        }
Esempio n. 5
0
        public async Task Close(WebSocketCloseCode closeCode, string closeReason)
        {
            if (State == WebSocketState.Closed || State == WebSocketState.None)
                return;

            var priorState = Interlocked.Exchange(ref _state, _closing);
            switch (priorState)
            {
                case _connected:
                    {
                        var closingHandshake = new CloseFrame(closeCode, closeReason, false).ToArray(_frameBuilder);
                        try
                        {
                            if (_stream.CanWrite)
                            {
                                await _stream.WriteAsync(closingHandshake, 0, closingHandshake.Length);
                                StartClosingTimer();
#if DEBUG
                                _log.DebugFormat("Session [{0}] sends server side close frame [{1}] [{2}].", this, closeCode, closeReason);
#endif
                            }
                        }
                        catch (Exception ex) when (!ShouldThrow(ex)) { }
                        return;
                    }
                case _connecting:
                case _closing:
                    {
                        await Close();
                        return;
                    }
                case _disposed:
                case _none:
                default:
                    return;
            }
        }
Esempio n. 6
0
        public async Task Close(WebSocketCloseCode closeCode, string closeReason)
        {
            if (State == WebSocketState.Closed || State == WebSocketState.None)
                return;

            var priorState = Interlocked.Exchange(ref _state, _closing);
            switch (priorState)
            {
                case _connected:
                    {
                        var closingHandshake = new CloseFrame(closeCode, closeReason).ToArray(_frameBuilder);
                        try
                        {
                            if (_stream.CanWrite)
                            {
                                StartClosingTimer();
#if DEBUG
                                _log.DebugFormat("Send client side close frame [{0}] [{1}].", closeCode, closeReason);
#endif
                                var awaiter = _stream.WriteAsync(closingHandshake, 0, closingHandshake.Length);
                                if (!awaiter.Wait(ConnectTimeout))
                                {
                                    await InternalClose(true);
                                    throw new TimeoutException(string.Format(
                                        "Closing handshake with [{0}] timeout [{1}].", _remoteEndPoint, ConnectTimeout));
                                }
                            }
                        }
                        catch (Exception ex) when (!ShouldThrow(ex)) { }
                        return;
                    }
                case _connecting:
                case _closing:
                    {
                        await InternalClose(true);
                        return;
                    }
                case _disposed:
                case _none:
                default:
                    return;
            }
        }
Esempio n. 7
0
        public void Close(WebSocketCloseCode closeCode, string closeReason)
        {
            if (State == WebSocketState.Closed || State == WebSocketState.None)
                return;

            var priorState = Interlocked.Exchange(ref _state, _closing);
            switch (priorState)
            {
                case _connected:
                    {
                        var closingHandshake = new CloseFrame(closeCode, closeReason).ToArray(_frameBuilder);
                        try
                        {
                            if (_stream.CanWrite)
                            {
                                StartClosingTimer();
                                var ar = _stream.BeginWrite(closingHandshake, 0, closingHandshake.Length, null, _stream);
                                if (!ar.AsyncWaitHandle.WaitOne(ConnectTimeout))
                                {
                                    InternalClose(true);
                                    throw new TimeoutException(string.Format(
                                        "Closing handshake with remote [{0}] timeout [{1}].", RemoteEndPoint, ConnectTimeout));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ShouldThrow(ex))
                                throw;
                        }
                        return;
                    }
                case _connecting:
                case _closing:
                    {
                        InternalClose(true);
                        return;
                    }
                case _disposed:
                case _none:
                default:
                    return;
            }
        }