/// <summary>
      /// Get a whole basic close frame, completely built.
      /// </summary>
      /// <returns>The close frame.</returns>
      public static WebSocketFrame GetCloseFrame()
      {
         WebSocketHeader header = new WebSocketHeader();
         header.Fin = true;
         header.Masked = false;
         header.Opcode = HeaderOpcode.CloseConnectionFrame;
         header.PayloadSize = 0;

         return new WebSocketFrame(header, new byte[0]);
      }
      /// <summary>
      /// Generate a websocket frame for the given text payload
      /// </summary>
      /// <returns>The text frame.</returns>
      /// <param name="payload">Payload.</param>
      public static WebSocketFrame GetTextFrame(byte[] payload)
      {
         WebSocketHeader header = new WebSocketHeader();
         header.Fin = true;
         header.Masked = false;
         header.Opcode = HeaderOpcode.TextFrame;
         header.PayloadSize = payload.Length;

         return new WebSocketFrame(header, payload);
      }
      /// <summary>
      /// Initializes a new instance of the <see cref="MyWebSocket.WebSocketFrame"/> class.
      /// </summary>
      /// <param name="header">A preparsed header object</param>
      /// <param name="frameOrPayload">Full frame data or just the payload (leave masked)</param>
      public WebSocketFrame(WebSocketHeader header, byte[] frameOrPayload)
      {
         Header = header;

         //Set the payload data bytes based on the length of the given byte array.
         if (frameOrPayload.Length == header.PayloadSize)
            PayloadData = frameOrPayload;
         else if (frameOrPayload.Length == header.FrameSize)
            PayloadData = frameOrPayload.Skip(header.HeaderSize).Take(header.PayloadSize).ToArray();
         else
            PayloadData = new byte[1];

         //Now let's just unmask the data and finally get the hell outta dodge.
         if (Header.Masked)
            ToggleMask();
      }
 /// <summary>
 /// Initialize an empty (invalid) frame.
 /// </summary>
 public WebSocketFrame()
 {
    Header = new WebSocketHeader();
    PayloadData = new byte[1];
 }
      /// <summary>
      /// Attempt to parse a series of ordered bytes into a WebSocketHeader. Bytes should be taken directly
      /// from whatever network stream you're using.
      /// </summary>
      /// <returns><c>true</c>, if parsed correctly, <c>false</c> otherwise.</returns>
      /// <param name="bytes">Header bytes</param>
      /// <param name="result">Parsed header information</param>
      public static bool TryParse(byte[] bytes, out WebSocketHeader result)
      {
         result = new WebSocketHeader();
         int headerSize = FullHeaderSize(bytes);

         if (headerSize > bytes.Length)
            return false;

         //First byte encoding
         result.Fin = (bytes[0] & 128) > 0;
         result.RSV = (bytes[0] & 112) >> 4;
         result.OpcodeRaw = (bytes[0] & 15);

         //Second byte encoding
         result.Masked = (bytes[1] & 128) > 0;
         result.PayloadSize = (bytes[1] & 127);

         int maskByte = 2;

         //Get all the bytes of the payload
         if (result.PayloadSize == 126)
         {
            result.PayloadSize = bytes.Skip(2).Take(2).ParseInt();
            maskByte += 2;
         }
         else if (result.PayloadSize == 127)
         {
            result.PayloadSize = bytes.Skip(2).Take(8).ParseInt();
            maskByte += 8;
         }

         //Get all the bytes of the mask
         if (result.Masked)
            result.Mask = bytes.Skip(maskByte).Take(4).ToArray();

         return true;
      }
      /// <summary>
      /// Attempts to read an entire frame. Returns the frame if one was successfully read.
      /// </summary>
      /// <returns>The status of the read operation</returns>
      /// <param name="frame">The parsed frame (on success)</param>
      public DataStatus TryReadFrame(out WebSocketFrame frame)
      {
         frame = new WebSocketFrame();

         //Pull a chunk of data (as much as we can) from the stream and store it in our internal buffer.
         DataStatus readStatus = GenericRead();

         //If there was an error (anything other than "completion" or waiting), return the error.
         if (readStatus != DataStatus.Complete)
            return readStatus;

         //We MAY have read more than one frame at a time! Wowie...
//         while (messageBufferSize > 0)
//         {
            //We need at least 2 bytes to complete the header.
            if (messageBufferSize < 2)
               return DataStatus.WaitingOnData;

            byte[] message = messageBuffer.Take(messageBufferSize).ToArray();

            //If the complete header hasn't been read yet, we're still waiting for it.
            if (messageBufferSize < WebSocketHeader.FullHeaderSize(message))
               return DataStatus.WaitingOnData;

            WebSocketHeader header = new WebSocketHeader();

            //If we can't parse the header at this point, we have some serious issues.
            if (!WebSocketHeader.TryParse(message, out header))
               return DataStatus.InternalError;
         
            //Too much data
            if (header.FrameSize > MaxReceiveSize)
            {
               return DataStatus.OversizeError;
            }
         
            //We have the whole header, but do we have the whole message? if not, we're still waiting on data.
            if (messageBufferSize < header.FrameSize)
               return DataStatus.WaitingOnData;

            //Oh, we have the whole message. Uhh ok then, let's make sure the header fields are correct
            //before continuing. RSV needs to be 0 (may change later) and all client messages must be masked.
            if (!header.Masked || header.RSV != 0)
               return DataStatus.DataFormatError;

            //Oh is this... a binary frame? Dawg... don't gimme that crap.
            if (header.Opcode == HeaderOpcode.BinaryFrame)
               return DataStatus.UnsupportedError;

            //Initialize a frame with our newly parsed data
            frame = new WebSocketFrame(header, messageBuffer.Take(header.FrameSize).ToArray());

            //Remove the message data from the buffer
            MessageBufferPop(header.FrameSize);
//            messageBuffer.TruncateBeginning(header.FrameSize, messageBufferSize);
//            messageBufferSize -= header.FrameSize;
         //}

         return DataStatus.Complete;
      }