docs: def __read_frame(self):
          """*Attempt* to read a frame. If we get an EAGAIN on the frame header, 
          it'll raise to our caller. If we get it *after* we already got the 
          header, wait-out the rest of the frame.
          """
  
          if self.__frame_header_cache is None:
              _logger.debug("Reading frame header.")
              (length, frame_type) = struct.unpack('!II', self.__read(8))
              self.__frame_header_cache = (length, frame_type)
          else:
              (length, frame_type) = self.__frame_header_cache
  
          try:
              data = self.__read(length - 4)
          except errno.EAGAIN:
              self.__frame_header_cache = (length, frame_type)
              raise
  
          self.__frame_header_cache = None
          self.__process_message(frame_type, data)