1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup vici_message vici_message
* @{ @ingroup vici_dispatcher
*/
#ifndef VICI_MESSAGE_H_
#define VICI_MESSAGE_H_
#include <library.h>
typedef struct vici_message_t vici_message_t;
typedef struct vici_parse_context_t vici_parse_context_t;
typedef enum vici_type_t vici_type_t;
/**
* Vici message encoding types
*/
enum vici_type_t {
/** never used in an argument list, needed by dump as initial value */
VICI_START = 0,
/** begin of new section, argument is section name as char* */
VICI_SECTION_START = 1,
/** end of current section, no arguments */
VICI_SECTION_END = 2,
/** key/value, arguments are key as char*, value as chunk_t */
VICI_KEY_VALUE = 3,
/** list start, argument is list name as char* */
VICI_LIST_START = 4,
/** list item, argument is item value as chunk_t */
VICI_LIST_ITEM = 5,
/** end of list, no arguments */
VICI_LIST_END = 6,
/** end of argument list, no arguments (never encoded) */
VICI_END = 7
};
/**
* Callback function for key/value and list items, invoked by parse().
*
* @param user user data, as passed to parse()
* @param message message currently parsing
* @param name name of key or list
* @param value parsed value
* @return TRUE if parsed successfully
*/
typedef bool (*vici_value_cb_t)(void *user, vici_message_t *message,
char *name, chunk_t value);
/**
* Callback function for sections, invoked by parse().
*
* @param user user data, as passed to parse()
* @param message message currently parsing
* @param ctx parse context, to pass to recursive parse() invocations.
* @param name name of the section
* @return TRUE if parsed successfully
*/
typedef bool (*vici_section_cb_t)(void *user, vici_message_t *message,
vici_parse_context_t *ctx, char *name);
/**
* Names for vici encoding types
*/
extern enum_name_t *vici_type_names;
/**
* Vici message representation, encoding/decoding routines.
*/
struct vici_message_t {
/**
* Create an enumerator over message contents.
*
* The enumerator takes a fixed list of arguments, but depending on the
* type may set not all of them. It returns VICI_END as last argument
* to indicate the message end, and returns FALSE if parsing the message
* failed.
*
* @return enumerator over (vici_type_t, char*, chunk_t)
*/
enumerator_t* (*create_enumerator)(vici_message_t *this);
/**
* Get the value of a key/value pair as a string.
*
* @param def default value if not found
* @param fmt printf style format string for key, with sections
* @param ... arguments to fmt string
* @return string
*/
char* (*get_str)(vici_message_t *this, char *def, char *fmt, ...);
/**
* Get the value of a key/value pair as a string, va_list variant.
*
* @param def default value if not found
* @param fmt printf style format string for key, with sections
* @param args arguments to fmt string
* @return string
*/
char* (*vget_str)(vici_message_t *this, char *def, char *fmt, va_list args);
/**
* Get the value of a key/value pair as integer.
*
* @param def default value if not found
* @param fmt printf style format string for key, with sections
* @param ... arguments to fmt string
* @return value
*/
int (*get_int)(vici_message_t *this, int def, char *fmt, ...);
/**
* Get the value of a key/value pair as integer, va_list variant
*
* @param def default value if not found
* @param fmt printf style format string for key, with sections
* @param args arguments to fmt string
* @return value
*/
int (*vget_int)(vici_message_t *this, int def, char *fmt, va_list args);
/**
* Get the raw value of a key/value pair.
*
* @param def default value if not found
* @param fmt printf style format string for key, with sections
* @param ... arguments to fmt string
* @return value
*/
chunk_t (*get_value)(vici_message_t *this, chunk_t def, char *fmt, ...);
/**
* Get the raw value of a key/value pair, va_list variant.
*
* @param def default value if not found
* @param fmt printf style format string for key, with sections
* @param args arguments to fmt string
* @return value
*/
chunk_t (*vget_value)(vici_message_t *this, chunk_t def,
char *fmt, va_list args);
/**
* Get encoded message.
*
* @return message data, points to internal data
*/
chunk_t (*get_encoding)(vici_message_t *this);
/**
* Parse a message using callback functions.
*
* Any of the callbacks may be NULL to skip this kind of item. Callbacks are
* invoked for the current section level only. To descent into sections,
* call parse() from within a section callback using the provided parse
* context.
*
* @param ctx parse context, NULL for root level
* @param section callback invoked for each section
* @param kv callback invoked for key/value pairs
* @param li callback invoked for list items
* @param user user data to pass to callbacks
* @return TRUE if parsed successfully
*/
bool (*parse)(vici_message_t *this, vici_parse_context_t *ctx,
vici_section_cb_t section, vici_value_cb_t kv,
vici_value_cb_t li, void *user);
/**
* Dump a message text representation to a FILE stream.
*
* @param label label to print for message
* @param pretty use pretty print with indentation
* @param out FILE stream to dump to
* @return TRUE if message valid
*/
bool (*dump)(vici_message_t *this, char *label, bool pretty, FILE *out);
/**
* Destroy a vici_message_t.
*/
void (*destroy)(vici_message_t *this);
};
/**
* Create a vici_message from encoded data.
*
* @param data message encoding
* @param cleanup TRUE to free data during
* @return message representation
*/
vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup);
/**
* Create a vici_message from an enumerator.
*
* The enumerator uses the same signature as the enumerator returned
* by create_enumerator(), and gets destroyed by this function. It should
* return VICI_END to close the message, return FALSE to indicate a failure.
*
* @param enumerator enumerator over (vici_type_t, char*, chunk_t)
* @return message representation, NULL on error
*/
vici_message_t *vici_message_create_from_enumerator(enumerator_t *enumerator);
/**
* Create vici message from a variable argument list.
*
* @param type first type beginning message
* @param ... vici_type_t and args, terminated by VICI_END
* @return message representation, NULL on error
*/
vici_message_t *vici_message_create_from_args(vici_type_t type, ...);
/**
* Check if a chunk has a printable string, and print it to buf.
*
* @param chunk chunk containing potential string
* @param buf buffer to write string to
* @param size size of buf
* @return TRUE if printable and string written to buf
*/
bool vici_stringify(chunk_t chunk, char *buf, size_t size);
/**
* Verify the occurrence of a given type for given section/list nesting
*/
bool vici_verify_type(vici_type_t type, u_int section, bool list);
#endif /** VICI_MESSAGE_H_ @}*/
|