'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.'

def read_message(self):

    opcode = None
    message = bytearray()
    while True:
        (header, payload) = self.read_frame()
        f_opcode = header.opcode
        if (f_opcode in (self.OPCODE_TEXT, self.OPCODE_BINARY)):
            if opcode:
                raise ProtocolError('The    opcode    in    non-fin    frame    is    expected    to    be    zero,    got    {0!r}'.format(f_opcode))
            self.utf8validator.reset()
            self.utf8validate_last = (True, True, 0, 0)
            opcode = f_opcode
        elif (f_opcode == self.OPCODE_CONTINUATION):
            if (not opcode):
                raise ProtocolError('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 ProtocolError('Unexpected    opcode={0!r}'.format(f_opcode))
        if (opcode == self.OPCODE_TEXT):
            self.validate_utf8(payload)
        message += payload
        if header.fin:
            break
    if (opcode == self.OPCODE_TEXT):
        self.validate_utf8(message)
        return self._decode_bytes(message)
    else:
        return message
