Statistics
| Branch: | Revision:

root / json-streamer.c @ eca7db46

History | View | Annotate | Download (3 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 55f8301f Anthony Liguori
    if (parser->brace_count < 0 ||
60 55f8301f Anthony Liguori
        parser->bracket_count < 0 ||
61 55f8301f Anthony Liguori
        (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 d7ff3acb Anthony Liguori
        parser->emit(parser, parser->tokens);
66 d7ff3acb Anthony Liguori
        QDECREF(parser->tokens);
67 d7ff3acb Anthony Liguori
        parser->tokens = qlist_new();
68 eca7db46 Anthony Liguori
        parser->token_size = 0;
69 29c75ddd Anthony Liguori
    } else if (parser->token_size > MAX_TOKEN_SIZE ||
70 29c75ddd Anthony Liguori
               parser->bracket_count > MAX_NESTING ||
71 29c75ddd Anthony Liguori
               parser->brace_count > MAX_NESTING) {
72 29c75ddd Anthony Liguori
        /* Security consideration, we limit total memory allocated per object
73 29c75ddd Anthony Liguori
         * and the maximum recursion depth that a message can force.
74 29c75ddd Anthony Liguori
         */
75 29c75ddd Anthony Liguori
        parser->brace_count = 0;
76 29c75ddd Anthony Liguori
        parser->bracket_count = 0;
77 29c75ddd Anthony Liguori
        parser->emit(parser, parser->tokens);
78 29c75ddd Anthony Liguori
        QDECREF(parser->tokens);
79 29c75ddd Anthony Liguori
        parser->tokens = qlist_new();
80 eca7db46 Anthony Liguori
        parser->token_size = 0;
81 d7ff3acb Anthony Liguori
    }
82 d7ff3acb Anthony Liguori
}
83 d7ff3acb Anthony Liguori
84 d7ff3acb Anthony Liguori
void json_message_parser_init(JSONMessageParser *parser,
85 d7ff3acb Anthony Liguori
                              void (*func)(JSONMessageParser *, QList *))
86 d7ff3acb Anthony Liguori
{
87 d7ff3acb Anthony Liguori
    parser->emit = func;
88 d7ff3acb Anthony Liguori
    parser->brace_count = 0;
89 d7ff3acb Anthony Liguori
    parser->bracket_count = 0;
90 d7ff3acb Anthony Liguori
    parser->tokens = qlist_new();
91 29c75ddd Anthony Liguori
    parser->token_size = 0;
92 d7ff3acb Anthony Liguori
93 d7ff3acb Anthony Liguori
    json_lexer_init(&parser->lexer, json_message_process_token);
94 d7ff3acb Anthony Liguori
}
95 d7ff3acb Anthony Liguori
96 d7ff3acb Anthony Liguori
int json_message_parser_feed(JSONMessageParser *parser,
97 d7ff3acb Anthony Liguori
                             const char *buffer, size_t size)
98 d7ff3acb Anthony Liguori
{
99 d7ff3acb Anthony Liguori
    return json_lexer_feed(&parser->lexer, buffer, size);
100 d7ff3acb Anthony Liguori
}
101 d7ff3acb Anthony Liguori
102 d7ff3acb Anthony Liguori
int json_message_parser_flush(JSONMessageParser *parser)
103 d7ff3acb Anthony Liguori
{
104 d7ff3acb Anthony Liguori
    return json_lexer_flush(&parser->lexer);
105 d7ff3acb Anthony Liguori
}
106 d7ff3acb Anthony Liguori
107 d7ff3acb Anthony Liguori
void json_message_parser_destroy(JSONMessageParser *parser)
108 d7ff3acb Anthony Liguori
{
109 d7ff3acb Anthony Liguori
    json_lexer_destroy(&parser->lexer);
110 d7ff3acb Anthony Liguori
    QDECREF(parser->tokens);
111 d7ff3acb Anthony Liguori
}