Ejemplo n.º 1
0
        /**
         * Async callback for data sent by client
         */
        private void ClientDataCallback(IAsyncResult state)
        {
            try {
                WsCallbackState cs     = (WsCallbackState)state.AsyncState;
                NetworkStream   stream = cs.client.GetStream();
                int             bytes  = stream.EndRead(state);
                if (bytes > 0)
                {
                    byte[] frames = new byte[bytes];
                    Array.Copy(cs.buffer, 0, frames, 0, bytes);
                    bool closed = false;
                    try {
                        // decode client message
                        WsDataFrame frame = FramesToMessage(frames);

                        if (frame.opcode == 0x8)   // close frame
                        {
                            int close_code = 0;
                            if (frame.payload.Length == 2)
                            {
                                close_code = ((frame.payload[0] & 0xff) << 8) + (frame.payload[1] & 0xff);
                            }
                            byte[] close_msg = WsDataFrame.CloseFrame(close_code);
                            stream.Write(close_msg, 0, close_msg.Length);
                            cs.client.Close();
                            _clients.Remove(cs.client);
                            closed = true;
                        }
                        else if (frame.opcode == 0x9)     // ping frame
                        {
                            byte[] pong_msg = WsDataFrame.PongFrame(frame.payload);
                            stream.Write(pong_msg, 0, pong_msg.Length);
                        }
                    } catch (WsFatalClientException ex) {
                        // client did something wrong. kill connection
                        if (_verbose > 0)
                        {
                            System.Console.WriteLine(ex);
                        }
                        cs.client.Close();
                        _clients.Remove(cs.client);
                        closed = true;
                    } catch (Exception ex) {
                        if (_verbose > 0)
                        {
                            System.Console.WriteLine(ex);
                        }
                    }

                    if (!closed)
                    {
                        MonitorClient(cs.client);
                    }
                }
                else     // zero-bytes read implies closed connection, I think
                {
                    cs.client.Close();
                    _clients.Remove(cs.client);
                }
            } catch (Exception) {
            }
        }
Ejemplo n.º 2
0
        private WsDataFrame FramesToMessage(byte[] frames)
        {
            if (frames.Length < 2)
            {
                throw new WsProtocolException("Invalid frame: too short (header)");
            }

            int  opcode        = frames[0] & 0xf;
            int  last_fragment = frames[0] & 0x80;
            int  masked        = frames[1] & 0x80;
            long length        = frames[1] & 0x7f;
            int  data_starts   = 6;

            if (masked == 0)
            {
                throw new WsFatalClientException("Client data not masked");
            }

            byte[] mask_key = new byte[4];
            if (length <= 125)
            {
                if (frames.Length < 6)
                {
                    throw new WsProtocolException("Invalid frame: too short (mask)");
                }
                Array.Copy(frames, 2, mask_key, 0, 4);
            }
            else if (length == 126)
            {
                if (frames.Length < 8)
                {
                    throw new WsProtocolException("Invalid frame: too short (mask)");
                }
                length = ((frames[2] << 8) & 0xff00) + (frames[3] & 0xff);
                Array.Copy(frames, 4, mask_key, 0, 4);
                data_starts = 8;
            }
            else if (length == 127)
            {
                if (frames.Length < 14)
                {
                    throw new WsProtocolException("Invalid frame: too short (mask)");
                }
                length = ((frames[2] & 0xff) << 56)
                         + ((frames[3] & 0xff) << 48)
                         + ((frames[4] & 0xff) << 40)
                         + ((frames[5] & 0xff) << 32)
                         + ((frames[6] & 0xff) << 24)
                         + ((frames[7] & 0xff) << 16)
                         + ((frames[8] & 0xff) << 8)
                         + (frames[9] & 0xff);
                Array.Copy(frames, 10, mask_key, 0, 4);
                data_starts = 14;
            }

            if (frames.Length < (data_starts + length))
            {
                throw new WsProtocolException("Invalid frame: too short (payload)");
            }

            byte[] payload = new byte[length];
            for (int i = 0; i < length; i++)
            {
                payload[i] = (byte)(frames[i + data_starts] ^ mask_key[i % 4]);
            }

            if (last_fragment == 0)
            {
                byte[] remainder = new byte[frames.Length - (data_starts + length)];
                Array.Copy(frames, data_starts + length, remainder, 0, remainder.Length);
                WsDataFrame others       = FramesToMessage(remainder);
                byte[]      full_payload = new byte[payload.Length + others.payload.Length];
                Array.Copy(payload, 0, full_payload, 0, payload.Length);
                Array.Copy(others.payload, 0, full_payload, payload.Length, others.payload.Length);

                return(new WsDataFrame(opcode, full_payload));
            }
            else
            {
                return(new WsDataFrame(opcode, payload));
            }
        }