public override long Parse(byte[] data, uint offset, uint ends)
    {
        try
        {
            long needed = 2;
            var  length = (ends - offset);
            if (length < needed)
            {
                //Console.WriteLine("stage 1 " + needed);
                return(length - needed);
            }

            uint oOffset = offset;
            FIN           = ((data[offset] & 0x80) == 0x80);
            RSV1          = ((data[offset] & 0x40) == 0x40);
            RSV2          = ((data[offset] & 0x20) == 0x20);
            RSV3          = ((data[offset] & 0x10) == 0x10);
            Opcode        = (WSOpcode)(data[offset++] & 0xF);
            Mask          = ((data[offset] & 0x80) == 0x80);
            PayloadLength = (long)(data[offset++] & 0x7F);

            if (Mask)
            {
                needed += 4;
            }

            if (PayloadLength == 126)
            {
                needed += 2;
                if (length < needed)
                {
                    //Console.WriteLine("stage 2 " + needed);
                    return(length - needed);
                }
                PayloadLength = data.GetUInt16(offset, Endian.Big);
                offset       += 2;
            }
            else if (PayloadLength == 127)
            {
                needed += 8;
                if (length < needed)
                {
                    //Console.WriteLine("stage 3 " + needed);
                    return(length - needed);
                }

                PayloadLength = data.GetInt64(offset, Endian.Big);
                offset       += 8;
            }

            /*
             * if (Mask)
             * {
             *                  MaskKey = new byte[4];
             *  MaskKey[0] = data[offset++];
             *  MaskKey[1] = data[offset++];
             *  MaskKey[2] = data[offset++];
             *  MaskKey[3] = data[offset++];
             *
             *  //MaskKey = DC.GetUInt32(data, offset);
             *  //offset += 4;
             * }
             */

            needed += PayloadLength;
            if (length < needed)
            {
                //Console.WriteLine("stage 4");
                return(length - needed);
            }
            else
            {
                if (Mask)
                {
                    MaskKey    = new byte[4];
                    MaskKey[0] = data[offset++];
                    MaskKey[1] = data[offset++];
                    MaskKey[2] = data[offset++];
                    MaskKey[3] = data[offset++];

                    Message = DC.Clip(data, offset, (uint)PayloadLength);

                    //var aMask = BitConverter.GetBytes(MaskKey);
                    for (int i = 0; i < Message.Length; i++)
                    {
                        Message[i] = (byte)(Message[i] ^ MaskKey[i % 4]);
                    }
                }
                else
                {
                    Message = DC.Clip(data, offset, (uint)PayloadLength);
                }


                return((offset - oOffset) + (int)PayloadLength);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.WriteLine(offset + "::" + DC.ToHex(data));
            throw ex;
        }
    }