def read_message(self):
        """
        Return the next text or binary message from the socket.

        This is an internal method as calling this will not cleanup correctly
        if an exception is called. Use `receive` instead.
        """
        opcode = None
        message = None
        while True:
            header, payload = self.read_frame()
            f_opcode = header.opcode
            if f_opcode in (self.OPCODE_TEXT, self.OPCODE_BINARY):
                # a new frame
                if opcode:
                    raise WebSocketError("The opcode in non-fin frame is expected to be zero, got {0!r}".format(f_opcode))
                # Start reading a new message, reset the validator
                self.utf8validator.reset()
                self.utf8validate_last = (True, True, 0, 0)
                opcode = f_opcode
            elif f_opcode == self.OPCODE_CONTINUATION:
                if not opcode:
                    raise WebSocketError("Unexpected frame with opcode=0")
            elif f_opcode == self.OPCODE_PING:
                self.handle_ping(header, payload)
                continue
            elif f_opcode == self.OPCODE_PONG:
                self.handle_pong(header, payload)
                continue
            elif f_opcode == self.OPCODE_CLOSE:
                self.handle_close(header, payload)
                return
            else:
                raise WebSocketError("Unexpected opcode={0!r}".format(f_opcode))
            if opcode == self.OPCODE_TEXT:
                self.validate_utf8(payload)
                if six.PY3:
                    payload = payload.decode()
            if message is None:
                message = six.text_type() if opcode == self.OPCODE_TEXT else six.binary_type()
            message += payload
            if header.fin:
                break
        if opcode == self.OPCODE_TEXT:
            if six.PY2:
                self.validate_utf8(message)
            else:
                self.validate_utf8(message.encode())
            return message
        else:
            return bytearray(message)
Return the next text or binary message from the socket.

        This is an internal method as calling this will not cleanup correctly
        if an exception is called. Use `receive` instead.