Esempio n. 1
0
static int send_response(GAState *s, QObject *payload)
{
    const char *buf;
    QString *payload_qstr, *response_qstr;
    GIOStatus status;

    g_assert(payload && s->channel);

    payload_qstr = qobject_to_json(payload);
    if (!payload_qstr) {
        return -EINVAL;
    }

    if (s->delimit_response) {
        s->delimit_response = false;
        response_qstr = qstring_new();
        qstring_append_chr(response_qstr, QGA_SENTINEL_BYTE);
        qstring_append(response_qstr, qstring_get_str(payload_qstr));
        QDECREF(payload_qstr);
    } else {
        response_qstr = payload_qstr;
    }

    qstring_append_chr(response_qstr, '\n');
    buf = qstring_get_str(response_qstr);
    status = ga_channel_write_all(s->channel, buf, strlen(buf));
    QDECREF(response_qstr);
    if (status != G_IO_STATUS_NORMAL) {
        return -EIO;
    }

    return 0;
}
Esempio n. 2
0
void json_prop_str(QJSON *json, const char *name, const char *str)
{
    json_emit_element(json, name);
    qstring_append_chr(json->str, '"');
    qstring_append(json->str, str);
    qstring_append_chr(json->str, '"');
}
Esempio n. 3
0
static int conn_channel_send_payload(GIOChannel *channel, QObject *payload)
{
    int ret = 0;
    const char *buf;
    QString *payload_qstr;
    GError *err = NULL;

    g_assert(payload && channel);

    payload_qstr = qobject_to_json(payload);
    if (!payload_qstr) {
        return -EINVAL;
    }

    qstring_append_chr(payload_qstr, '\n');
    buf = qstring_get_str(payload_qstr);
    ret = conn_channel_send_buf(channel, buf, strlen(buf));
    if (ret) {
        goto out_free;
    }

    g_io_channel_flush(channel, &err);
    if (err != NULL) {
        g_warning("error flushing payload: %s", err->message);
        ret = err->code;
        goto out_free;
    }

out_free:
    QDECREF(payload_qstr);
    if (err) {
        g_error_free(err);
    }
    return ret;
}
Esempio n. 4
0
/**
 * qerror_human(): Format QError data into human-readable string.
 *
 * Formats according to member 'desc' of the specified QError object.
 */
QString *qerror_human(const QError *qerror)
{
    const char *p;
    QString *qstring;

    assert(qerror->entry != NULL);

    qstring = qstring_new();

    for (p = qerror->entry->desc; *p != '\0';) {
        if (*p != '%') {
            qstring_append_chr(qstring, *p++);
        } else if (*(p + 1) == '%') {
            qstring_append_chr(qstring, '%');
            p += 2;
        } else {
            p = append_field(qstring, qerror, p);
        }
    }

    return qstring;
}
Esempio n. 5
0
static QString *qerror_format_desc(QDict *error,
                                   const QErrorStringTable *entry)
{
    QString *qstring;
    const char *p;

    assert(entry != NULL);

    qstring = qstring_new();

    for (p = entry->desc; *p != '\0';) {
        if (*p != '%') {
            qstring_append_chr(qstring, *p++);
        } else if (*(p + 1) == '%') {
            qstring_append_chr(qstring, '%');
            p += 2;
        } else {
            p = append_field(error, qstring, entry, p);
        }
    }

    return qstring;
}
Esempio n. 6
0
static int json_lexer_feed_char(JSONLexer *lexer, char ch)
{
    int char_consumed, new_state;

    lexer->x++;
    if (ch == '\n') {
        lexer->x = 0;
        lexer->y++;
    }

    do {
        new_state = json_lexer[lexer->state][(uint8_t)ch];
        char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
        if (char_consumed) {
            qstring_append_chr(lexer->token, ch);
        }

        switch (new_state) {
        case JSON_OPERATOR:
        case JSON_ESCAPE:
        case JSON_INTEGER:
        case JSON_FLOAT:
        case JSON_KEYWORD:
        case JSON_STRING:
            lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y);
        case JSON_SKIP:
            QDECREF(lexer->token);
            lexer->token = qstring_new();
            new_state = IN_START;
            break;
        case IN_ERROR:
            return -EINVAL;
        default:
            break;
        }
        lexer->state = new_state;
    } while (!char_consumed);
    return 0;
}
Esempio n. 7
0
static void qobject_is_equal_string_test(void)
{
    QString *str_base, *str_whitespace_0, *str_whitespace_1, *str_whitespace_2;
    QString *str_whitespace_3, *str_case, *str_built;

    str_base = qstring_from_str("foo");
    str_whitespace_0 = qstring_from_str(" foo");
    str_whitespace_1 = qstring_from_str("foo ");
    str_whitespace_2 = qstring_from_str("foo\b");
    str_whitespace_3 = qstring_from_str("fooo\b");
    str_case = qstring_from_str("Foo");

    /* Should yield "foo" */
    str_built = qstring_from_substr("form", 0, 1);
    qstring_append_chr(str_built, 'o');

    check_unequal(str_base, str_whitespace_0, str_whitespace_1,
                  str_whitespace_2, str_whitespace_3, str_case);

    check_equal(str_base, str_built);

    free_all(str_base, str_whitespace_0, str_whitespace_1, str_whitespace_2,
             str_whitespace_3, str_case, str_built);
}
Esempio n. 8
0
static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
{
    int char_consumed, new_state;

    lexer->x++;
    if (ch == '\n') {
        lexer->x = 0;
        lexer->y++;
    }

    do {
        new_state = json_lexer[lexer->state][(uint8_t)ch];
        char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
        if (char_consumed) {
            qstring_append_chr(lexer->token, ch);
        }

        switch (new_state) {
        case JSON_OPERATOR:
        case JSON_ESCAPE:
        case JSON_INTEGER:
        case JSON_FLOAT:
        case JSON_KEYWORD:
        case JSON_STRING:
            lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y);
            /* fall through */
        case JSON_SKIP:
            QDECREF(lexer->token);
            lexer->token = qstring_new();
            new_state = IN_START;
            break;
        case IN_ERROR:
            /* XXX: To avoid having previous bad input leaving the parser in an
             * unresponsive state where we consume unpredictable amounts of
             * subsequent "good" input, percolate this error state up to the
             * tokenizer/parser by forcing a NULL object to be emitted, then
             * reset state.
             *
             * Also note that this handling is required for reliable channel
             * negotiation between QMP and the guest agent, since chr(0xFF)
             * is placed at the beginning of certain events to ensure proper
             * delivery when the channel is in an unknown state. chr(0xFF) is
             * never a valid ASCII/UTF-8 sequence, so this should reliably
             * induce an error/flush state.
             */
            lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y);
            QDECREF(lexer->token);
            lexer->token = qstring_new();
            new_state = IN_START;
            lexer->state = new_state;
            return 0;
        default:
            break;
        }
        lexer->state = new_state;
    } while (!char_consumed && !flush);

    /* Do not let a single token grow to an arbitrarily large size,
     * this is a security consideration.
     */
    if (lexer->token->length > MAX_TOKEN_SIZE) {
        lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y);
        QDECREF(lexer->token);
        lexer->token = qstring_new();
        lexer->state = IN_START;
    }

    return 0;
}