Statistics
| Branch: | Revision:

root / json-streamer.c @ a22f123c

History | View | Annotate | Download (3.2 kB)

1 d7ff3acb Anthony Liguori
/*
2 d7ff3acb Anthony Liguori
 * JSON streaming support
3 d7ff3acb Anthony Liguori
 *
4 d7ff3acb Anthony Liguori
 * Copyright IBM, Corp. 2009
5 d7ff3acb Anthony Liguori
 *
6 d7ff3acb Anthony Liguori
 * Authors:
7 d7ff3acb Anthony Liguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 d7ff3acb Anthony Liguori
 *
9 d7ff3acb Anthony Liguori
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 d7ff3acb Anthony Liguori
 * See the COPYING.LIB file in the top-level directory.
11 d7ff3acb Anthony Liguori
 *
12 d7ff3acb Anthony Liguori
 */
13 d7ff3acb Anthony Liguori
14 d7ff3acb Anthony Liguori
#include "qlist.h"
15 d7ff3acb Anthony Liguori
#include "qint.h"
16 d7ff3acb Anthony Liguori
#include "qdict.h"
17 d7ff3acb Anthony Liguori
#include "qemu-common.h"
18 d7ff3acb Anthony Liguori
#include "json-lexer.h"
19 d7ff3acb Anthony Liguori
#include "json-streamer.h"
20 d7ff3acb Anthony Liguori
21 29c75ddd Anthony Liguori
#define MAX_TOKEN_SIZE (64ULL << 20)
22 29c75ddd Anthony Liguori
#define MAX_NESTING (1ULL << 10)
23 29c75ddd Anthony Liguori
24 d7ff3acb Anthony Liguori
static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y)
25 d7ff3acb Anthony Liguori
{
26 d7ff3acb Anthony Liguori
    JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
27 d7ff3acb Anthony Liguori
    QDict *dict;
28 d7ff3acb Anthony Liguori
29 d7ff3acb Anthony Liguori
    if (type == JSON_OPERATOR) {
30 d7ff3acb Anthony Liguori
        switch (qstring_get_str(token)[0]) {
31 d7ff3acb Anthony Liguori
        case '{':
32 d7ff3acb Anthony Liguori
            parser->brace_count++;
33 d7ff3acb Anthony Liguori
            break;
34 d7ff3acb Anthony Liguori
        case '}':
35 d7ff3acb Anthony Liguori
            parser->brace_count--;
36 d7ff3acb Anthony Liguori
            break;
37 d7ff3acb Anthony Liguori
        case '[':
38 d7ff3acb Anthony Liguori
            parser->bracket_count++;
39 d7ff3acb Anthony Liguori
            break;
40 d7ff3acb Anthony Liguori
        case ']':
41 d7ff3acb Anthony Liguori
            parser->bracket_count--;
42 d7ff3acb Anthony Liguori
            break;
43 d7ff3acb Anthony Liguori
        default:
44 d7ff3acb Anthony Liguori
            break;
45 d7ff3acb Anthony Liguori
        }
46 d7ff3acb Anthony Liguori
    }
47 d7ff3acb Anthony Liguori
48 d7ff3acb Anthony Liguori
    dict = qdict_new();
49 2e89c068 Luiz Capitulino
    qdict_put(dict, "type", qint_from_int(type));
50 d7ff3acb Anthony Liguori
    QINCREF(token);
51 2e89c068 Luiz Capitulino
    qdict_put(dict, "token", token);
52 2e89c068 Luiz Capitulino
    qdict_put(dict, "x", qint_from_int(x));
53 2e89c068 Luiz Capitulino
    qdict_put(dict, "y", qint_from_int(y));
54 d7ff3acb Anthony Liguori
55 29c75ddd Anthony Liguori
    parser->token_size += token->length;
56 29c75ddd Anthony Liguori
57 d7ff3acb Anthony Liguori
    qlist_append(parser->tokens, dict);
58 d7ff3acb Anthony Liguori
59 5e2dafeb Michael Roth
    if (type == JSON_ERROR) {
60 5e2dafeb Michael Roth
        goto out_emit_bad;
61 5e2dafeb Michael Roth
    } else if (parser->brace_count < 0 ||
62 55f8301f Anthony Liguori
        parser->bracket_count < 0 ||
63 55f8301f Anthony Liguori
        (parser->brace_count == 0 &&
64 55f8301f Anthony Liguori
         parser->bracket_count == 0)) {
65 5e2dafeb Michael Roth
        goto out_emit;
66 29c75ddd Anthony Liguori
    } else if (parser->token_size > MAX_TOKEN_SIZE ||
67 29c75ddd Anthony Liguori
               parser->bracket_count > MAX_NESTING ||
68 29c75ddd Anthony Liguori
               parser->brace_count > MAX_NESTING) {
69 29c75ddd Anthony Liguori
        /* Security consideration, we limit total memory allocated per object
70 29c75ddd Anthony Liguori
         * and the maximum recursion depth that a message can force.
71 29c75ddd Anthony Liguori
         */
72 5e2dafeb Michael Roth
        goto out_emit;
73 5e2dafeb Michael Roth
    }
74 5e2dafeb Michael Roth
75 5e2dafeb Michael Roth
    return;
76 5e2dafeb Michael Roth
77 5e2dafeb Michael Roth
out_emit_bad:
78 5e2dafeb Michael Roth
    /* clear out token list and tell the parser to emit and error
79 5e2dafeb Michael Roth
     * indication by passing it a NULL list
80 5e2dafeb Michael Roth
     */
81 5e2dafeb Michael Roth
    QDECREF(parser->tokens);
82 5e2dafeb Michael Roth
    parser->tokens = NULL;
83 5e2dafeb Michael Roth
out_emit:
84 5e2dafeb Michael Roth
    /* send current list of tokens to parser and reset tokenizer */
85 5e2dafeb Michael Roth
    parser->brace_count = 0;
86 5e2dafeb Michael Roth
    parser->bracket_count = 0;
87 5e2dafeb Michael Roth
    parser->emit(parser, parser->tokens);
88 5e2dafeb Michael Roth
    if (parser->tokens) {
89 29c75ddd Anthony Liguori
        QDECREF(parser->tokens);
90 d7ff3acb Anthony Liguori
    }
91 5e2dafeb Michael Roth
    parser->tokens = qlist_new();
92 5e2dafeb Michael Roth
    parser->token_size = 0;
93 d7ff3acb Anthony Liguori
}
94 d7ff3acb Anthony Liguori
95 d7ff3acb Anthony Liguori
void json_message_parser_init(JSONMessageParser *parser,
96 d7ff3acb Anthony Liguori
                              void (*func)(JSONMessageParser *, QList *))
97 d7ff3acb Anthony Liguori
{
98 d7ff3acb Anthony Liguori
    parser->emit = func;
99 d7ff3acb Anthony Liguori
    parser->brace_count = 0;
100 d7ff3acb Anthony Liguori
    parser->bracket_count = 0;
101 d7ff3acb Anthony Liguori
    parser->tokens = qlist_new();
102 29c75ddd Anthony Liguori
    parser->token_size = 0;
103 d7ff3acb Anthony Liguori
104 d7ff3acb Anthony Liguori
    json_lexer_init(&parser->lexer, json_message_process_token);
105 d7ff3acb Anthony Liguori
}
106 d7ff3acb Anthony Liguori
107 d7ff3acb Anthony Liguori
int json_message_parser_feed(JSONMessageParser *parser,
108 d7ff3acb Anthony Liguori
                             const char *buffer, size_t size)
109 d7ff3acb Anthony Liguori
{
110 d7ff3acb Anthony Liguori
    return json_lexer_feed(&parser->lexer, buffer, size);
111 d7ff3acb Anthony Liguori
}
112 d7ff3acb Anthony Liguori
113 d7ff3acb Anthony Liguori
int json_message_parser_flush(JSONMessageParser *parser)
114 d7ff3acb Anthony Liguori
{
115 d7ff3acb Anthony Liguori
    return json_lexer_flush(&parser->lexer);
116 d7ff3acb Anthony Liguori
}
117 d7ff3acb Anthony Liguori
118 d7ff3acb Anthony Liguori
void json_message_parser_destroy(JSONMessageParser *parser)
119 d7ff3acb Anthony Liguori
{
120 d7ff3acb Anthony Liguori
    json_lexer_destroy(&parser->lexer);
121 d7ff3acb Anthony Liguori
    QDECREF(parser->tokens);
122 d7ff3acb Anthony Liguori
}