コード例 #1
0
 public void Close()
 {
     SynchronizeWhenNot(WebSocketClientState.None, () => {
         _state = WebSocketClientState.Disconnecting;
         _websocket.Close(CloseStatusCode.Normal, "User invoked close");
     });
 }
コード例 #2
0
        internal WebSocketClient(NetMQSocket streamSocket, byte[] identity)
        {
            m_state = WebSocketClientState.Closed;
            m_streamSocket = streamSocket;
            m_outgoingMessage = null;

            Identity = identity;
        }
コード例 #3
0
        internal WebSocketClient(NetMQSocket streamSocket, byte[] identity)
        {
            m_state           = WebSocketClientState.Closed;
            m_streamSocket    = streamSocket;
            m_outgoingMessage = null;

            Identity = identity;
        }
コード例 #4
0
        public void Close()
        {
            // TODO: send close message
            m_streamSocket.Send(Identity, Identity.Length, true, true);
            m_streamSocket.Send("");

            m_state = WebSocketClientState.Closed;
        }
コード例 #5
0
        public bool Send(byte[] message, bool dontWait, bool more)
        {
            int frameSize         = 2 + 1 + message.Length;
            int payloadStartIndex = 2;
            int payloadLength     = message.Length + 1;

            if (payloadLength > 125)
            {
                frameSize         += 2;
                payloadStartIndex += 2;

                if (payloadLength > ushort.MaxValue)
                {
                    frameSize         += 6;
                    payloadStartIndex += 6;
                }
            }

            byte[] frame = new byte[frameSize];

            frame[0] = (byte)0x81; // Text and Final

            // No mask
            frame[1] = 0x00;

            if (payloadLength <= 125)
            {
                frame[1] |= (byte)(payloadLength & 127);
            }
            else
            {
                // TODO: implement
            }

            // more byte
            frame[payloadStartIndex] = (byte)(more ? '1' : '0');
            payloadStartIndex++;

            // payload
            Buffer.BlockCopy(message, 0, frame, payloadStartIndex, message.Length);

            try
            {
                m_streamSocket.SendMore(Identity, Identity.Length, dontWait);
                m_streamSocket.Send(frame, frame.Length, dontWait);

                return(true);
            }
            catch (AgainException againException)
            {
                return(false);
            }
            catch (NetMQException exception)
            {
                m_state = WebSocketClientState.Closed;
                throw exception;
            }
        }
コード例 #6
0
        public void Close()
        {
            // TODO: send close message
            if (m_streamSocket.TrySendFrame(Identity, Identity.Length, true))
            {
                m_streamSocket.TrySendFrame("");
            }

            m_state = WebSocketClientState.Closed;
        }
コード例 #7
0
        private async Task OnMessage(WebSocketClientState state, string wsMessage)
        {
            if (string.IsNullOrWhiteSpace(wsMessage) || wsMessage.Length < 1)
            {
                return;
            }

            Message msg = Message.Deserialize(wsMessage.Substring(0, wsMessage.Length - 1));

            await this.Dispatcher.HandleMessageAsync(state, msg);
        }
コード例 #8
0
 public void Open()
 {
     SynchronizeWhen(WebSocketClientState.None, () => {
         _websocket            = new WebSocket(_hostUri.ToString());
         _websocket.OnOpen    += OnOpen;
         _websocket.OnClose   += OnClose;
         _websocket.OnMessage += OnMessage;
         _websocket.OnError   += OnError;
         _state = WebSocketClientState.Connecting;
         _websocket.ConnectAsync();
     });
 }
コード例 #9
0
        private void OnMessage(object sender, MessageEventArgs e)
        {
            if (e.Opcode == OpcodeEnum.Close)
            {
                // send close command to the socket
                try
                {
                    if (m_streamSocket.TrySendFrame(Identity, Identity.Length, true))
                    {
                        m_streamSocket.TrySendFrame("");
                    }
                }
                catch (NetMQException)
                {
                }

                m_state = WebSocketClientState.Closed;
            }
            else if (e.Opcode == OpcodeEnum.Binary)
            {
                if (m_outgoingMessage == null)
                {
                    m_outgoingMessage = new NetMQMessage();
                }

                m_outgoingMessage.Append(e.Payload);

                if (!e.More)
                {
                    if (IncomingMessage != null)
                    {
                        IncomingMessage(this, new NetMQMessageEventArgs(Identity, m_outgoingMessage));
                    }
                    m_outgoingMessage = null;
                }
            }
            else if (e.Opcode == OpcodeEnum.Ping)
            {
                byte[] pong = new byte[2 + e.Payload.Length];
                pong[0] = 0x8A; // Pong and Final
                pong[1] = (byte)(e.Payload.Length & 127);
                Buffer.BlockCopy(e.Payload, 0, pong, 2, e.Payload.Length);

                if (m_streamSocket.TrySendFrame(Identity, Identity.Length, true))
                {
                    m_streamSocket.TrySendFrame(pong);
                }
            }
        }
コード例 #10
0
        private void Synchronize(Action action, Func <bool> predicate = null)
        {
            bool stateChanged;

            lock (_mutex) {
                WebSocketClientState state = _state;
                if (predicate == null || predicate())
                {
                    action();
                }
                stateChanged = _state != state;
            }
            // notify outside lock to avoid deadlock
            if (stateChanged)
            {
                _webSocketClientCallback.OnStateChanged();
            }
        }
コード例 #11
0
        internal override Task RunAsync()
        {
            this.Server.Start(socket =>
            {
                socket.OnOpen = () =>
                {
                    WebSocketClientState state = new WebSocketClientState(socket);
                    this.States.AddOrUpdate(socket.ConnectionInfo.Id, state, (_, __) => state);
                };

                socket.OnClose = () =>
                {
                    this.States.Remove(socket.ConnectionInfo.Id, out WebSocketClientState _);
                };

                socket.OnMessage = async wsMsg =>
                {
                    if (this.States.ContainsKey(socket.ConnectionInfo.Id))
                    {
                        await this.OnMessage(this.States[socket.ConnectionInfo.Id], wsMsg);
                    }
                };

                socket.OnPing = async wsBinaryMsg =>
                {
                    if (this.States.ContainsKey(socket.ConnectionInfo.Id))
                    {
                        WebSocketClientState state = this.States[socket.ConnectionInfo.Id];
                        if (state.IsRegistered)
                        {
                            await socket.SendPong(wsBinaryMsg);
                        }
                    }
                };
            });

            this.Logger.Nice("Web Socket Server", ConsoleColor.Magenta, $"Running on {this.Server.Location}");

            return(Task.CompletedTask);
        }
コード例 #12
0
        public void OnDataReady()
        {
            switch (m_state)
            {
            case WebSocketClientState.Closed:
                m_state = WebSocketClientState.Handshake;
                string clientHandshake = m_streamSocket.ReceiveFrameString();

                string[] lines = clientHandshake.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                string key;

                if (ValidateClientHandshake(lines, out key))
                {
                    string acceptKey = GenerateAcceptKey(key);

                    try
                    {
                        if (m_streamSocket.TrySendFrame(Identity, Identity.Length, true) &&
                            m_streamSocket.TrySendFrame("HTTP/1.1 101 Switching Protocols\r\n" +
                                                        "Upgrade: websocket\r\n" +
                                                        "Connection: Upgrade\r\n" +
                                                        "Sec-WebSocket-Accept: " + acceptKey + "\r\n" +
                                                        "Sec-WebSocket-Protocol: WSNetMQ\r\n\r\n"))
                        {
                            m_decoder          = new Decoder();
                            m_decoder.Message += OnMessage;
                            m_state            = WebSocketClientState.Ready;
                        }
                        else
                        {
                            m_state = WebSocketClientState.Closed;
                        }
                    }
                    catch (NetMQException)
                    {
                        m_state = WebSocketClientState.Closed;
                    }
                }
                else
                {
                    m_state = WebSocketClientState.Closed;

                    if (m_streamSocket.TrySendFrame(Identity, Identity.Length, true))
                    {
                        m_streamSocket.TrySendFrame("HTTP/1.1 400 Bad Request\r\nSec-WebSocket-Version: 13\r\n");
                    }

                    // invalid request, close the socket and raise closed event
                    if (m_streamSocket.TrySendFrame(Identity, Identity.Length, true))
                    {
                        m_streamSocket.TrySendFrame("");
                    }
                }

                break;

            case WebSocketClientState.Ready:
                byte[] message = m_streamSocket.ReceiveFrameBytes();
                m_decoder.Process(message);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
コード例 #13
0
        public void Disconnect()
        {
            if (client == null)
                return;

            Debug.Assert(state == WebSocketClientState.Open || state == WebSocketClientState.Handshaking);
            state = WebSocketClientState.Closing;
            context.UserContext.Send(DataFrame.CloseResponseFrame);
            Dispose();
            state = WebSocketClientState.Closed;
        }
コード例 #14
0
        /// <summary>
        /// Begin connecting to a WebSocket server. Upon returning from this method, the server
        /// will be in the Handshaking state. This means the client is waiting for the handshake
        /// response from the server. Messages may not be sent until the OnConnected event has fired.
        /// </summary>
        public void BeginConnect()
        {
            if (state != WebSocketClientState.Closed)
                throw new InvalidOperationException();

            try
            {
                state = WebSocketClientState.Connecting;

                client = new TcpClient();
                client.Connect(host, port);

                state = WebSocketClientState.Handshaking;

                context = CreateContext();
                StartContext(context);
            }
            catch (Exception e)
            {
                state = WebSocketClientState.Closed;
                throw e;
            }
        }
コード例 #15
0
        private void ProcessData(Context context)
        {
            if (state == WebSocketClientState.Handshaking)
            {
                // Assuming we've read the whole response, and that this response has no payload
                // Definitely not gaurenteed to be true
                var someBytes = new byte[context.ReceivedByteCount];
                Array.Copy(context.Buffer, someBytes, context.ReceivedByteCount);
                var authenticated = CheckAuthenticationResponse(someBytes);
                frameReader = new DataFrameReaderRfc6455();

                if (!authenticated)
                {
                    Disconnect();
                }
                else
                {
                    state = WebSocketClientState.Open;
                    context.UserContext.OnConnected();
                }
            }
            else
            {
                Debug.Assert(state == WebSocketClientState.Open);
                frameReader.Append(context.Buffer, context.ReceivedByteCount);
                foreach (var frameData in frameReader.ReadFrames())
                    context.UserContext.OnReceive(frameData);
            }
        }
コード例 #16
0
 private void OnSocketClose()
 {
     OnDisconnect(this.context.UserContext);
     state = WebSocketClientState.Closed;
     Dispose();
 }
コード例 #17
0
        // Event Handlers

        private void OnOpen(object sender, EventArgs e)
        {
            Synchronize(() => _state = WebSocketClientState.Connected);
            _webSocketClientCallback.OnOpen();
        }
コード例 #18
0
 private void OnClose(object sender, CloseEventArgs e)
 {
     Synchronize(() => _state = WebSocketClientState.Disconnected);
     _webSocketClientCallback.OnClose();
 }
コード例 #19
0
        private void OnMessage(object sender, MessageEventArgs e)
        {
            if (e.Opcode == OpcodeEnum.Close)
            {
                // send close command to the socket
                try
                {
                    m_streamSocket.SendMore(Identity, Identity.Length, true);
                    m_streamSocket.Send("");
                }
                catch (NetMQException)
                {
                }

                m_state = WebSocketClientState.Closed;
            }
            else if (e.Opcode == OpcodeEnum.Binary)
            {
                if (m_outgoingMessage == null)
                {
                    m_outgoingMessage = new NetMQMessage();
                }

                m_outgoingMessage.Append(e.Payload);

                if (!e.More)
                {
                    if (IncomingMessage != null)
                    {
                        IncomingMessage(this, new NetMQMessageEventArgs(Identity, m_outgoingMessage));
                    }
                    m_outgoingMessage = null;
                }
            }
            else if (e.Opcode == OpcodeEnum.Ping)
            {
                byte[] pong = new byte[2 + e.Payload.Length];
                pong[0] = 0x8A; // Pong and Final
                pong[1] = (byte)(e.Payload.Length & 127);
                Buffer.BlockCopy(e.Payload, 0, pong, 2, e.Payload.Length);

                m_streamSocket.SendMore(Identity, Identity.Length, true);
                m_streamSocket.Send(pong);
            }
        }
コード例 #20
0
        public bool Send(byte[] message, bool dontWait, bool more)
        {
            int frameSize = 2 + 1 + message.Length;
            int payloadStartIndex = 2;
            int payloadLength = message.Length + 1;

            if (payloadLength > 125)
            {
                frameSize += 2;
                payloadStartIndex += 2;

                if (payloadLength > ushort.MaxValue)
                {
                    frameSize += 6;
                    payloadStartIndex += 6;
                }
            }

            byte[] frame = new byte[frameSize];

            frame[0] = (byte)0x81; // Text and Final      

            // No mask
            frame[1] = 0x00;

            if (payloadLength <= 125)
            {
                frame[1] |= (byte)(payloadLength & 127);
            }
            else
            {
                // TODO: implement
            }

            // more byte
            frame[payloadStartIndex] = (byte)(more ? '1' : '0');
            payloadStartIndex++;

            // payload
            Buffer.BlockCopy(message, 0, frame, payloadStartIndex, message.Length);

            try
            {
                m_streamSocket.SendMore(Identity, Identity.Length, dontWait);
                m_streamSocket.Send(frame, frame.Length, dontWait);

                return true;
            }
            catch (AgainException againException)
            {
                return false;
            }
            catch (NetMQException exception)
            {
                m_state = WebSocketClientState.Closed;
                throw exception;
            }
        }
コード例 #21
0
 private void SynchronizeWhenNot(WebSocketClientState state, Action action) => Synchronize(action, () => _state != state);
コード例 #22
0
        public void Close()
        {
            // TODO: send close message     
            m_streamSocket.Send(Identity, Identity.Length, true, true);
            m_streamSocket.Send("");

            m_state = WebSocketClientState.Closed;
        }
コード例 #23
0
        public void OnDataReady()
        {
            switch (m_state)
            {
                case WebSocketClientState.Closed:
                    m_state = WebSocketClientState.Handshake;
                    string clientHandshake = m_streamSocket.ReceiveString();

                    string[] lines = clientHandshake.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                    string key;

                    if (ValidateClientHandshake(lines, out key))
                    {
                        string acceptKey = GenerateAcceptKey(key);

                        try
                        {
                            m_streamSocket.SendMore(Identity, Identity.Length, true);
                            m_streamSocket.Send("HTTP/1.1 101 Switching Protocols\r\n" +
                                                "Upgrade: websocket\r\n" +
                                                "Connection: Upgrade\r\n" +
                                                "Sec-WebSocket-Accept: " + acceptKey + "\r\n" +
                                                "Sec-WebSocket-Protocol: WSNetMQ\r\n\r\n");

                            m_decoder = new Decoder();
                            m_decoder.Message += OnMessage;
                            m_state = WebSocketClientState.Ready;
                        }
                        catch (NetMQException)
                        {
                            m_state = WebSocketClientState.Closed;
                        }
                    }
                    else
                    {
                        m_state = WebSocketClientState.Closed;

                        try
                        {
                            m_streamSocket.SendMore(Identity, Identity.Length, true);
                            m_streamSocket.Send("HTTP/1.1 400 Bad Request\r\nSec-WebSocket-Version: 13\r\n");

                            // invalid request, close the socket and raise closed event
                            m_streamSocket.SendMore(Identity, Identity.Length, true);
                            m_streamSocket.Send("");
                        }
                        catch (NetMQException ex)
                        {

                        }
                    }

                    break;
                case WebSocketClientState.Ready:
                    byte[] message = m_streamSocket.Receive();
                    m_decoder.Process(message);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }