aboutsummaryrefslogtreecommitdiffstats
path: root/echld/echld.h
blob: 50b541439ba53098850fef2ba8a984c62b628b9e (plain)
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
/* echld.h
 *  epan working child API
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * Copyright (c) 2013 by Luis Ontanon <luis@ontanon.org>
 *
 * 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef __ECHLD_H
#define __ECHLD_H

#ifdef __cplusplus
extern "C" {
#endif

#include "ws_symbol_export.h"

#define ECHLD_VERSION "0.0"
#define ECHLD_MAJOR_VERSION 0 /* increases when existing things change */
							  /* if this changes an old client may or may not work */

#define ECHLD_MINOR_VERSION 0 /* increases when new things are added */
							  /* if just this one changes an old client will still work */

/*
 * You should take a look to doc/README.epan_child before reading this
 */

/* message types */
typedef enum _echld_msg_type_t echld_msg_type_t;

/* error types */
typedef enum _echld_error echld_error_t;

/* return codes */
 /* 0 is ok, everything else is ko, or timeout where applicable. */
typedef int echld_state_t;
#define ECHLD_OK 0
#define ECHLD_TIMEOUT -222

/* id for child working processes, a negative value is an error */
typedef int echld_chld_id_t;

/* id of requests, a negative value is an error */
typedef int echld_reqh_id_t;

/* id of message handlers, a negative value is an error */
typedef int echld_msgh_id_t;

/* enc_msg_t is an obscure object for an encoded message (a GbyteArray for now)*/
typedef struct _GByteArray enc_msg_t;

/* sets the codec set by name */
typedef enum _echld_encoding {
	ECHLD_ENCODING_TEXT = 'T',
	ECHLD_ENCODING_XML  = 'X',
	ECHLD_ENCODING_JSON = 'J'
} echld_encoding_t;

typedef int echld_bool_t;

/* typedef for a timeval so that sys/time.h is not required in the client */
typedef struct timeval tv_t;

typedef void (*cleanup_cb_t)(void*);
typedef int (*main_t)(int, char**); /* a pointer to main() */

/* these are called after a new child is created.
 * chld_id = -1 on error/timeout
 */
typedef void (*echld_new_cb_t)(void* child_data, const char* err);

/* I will be passed to echld_initialize() */
typedef struct _echld_init {
	echld_encoding_t encoding; /* only JSON for now */

	char* argv0; /* the value of argv[0] */
	main_t main;

	echld_new_cb_t dispatcher_hello_cb; /* child_data will be a pointer to this echld_init_t */

	cleanup_cb_t after_fork_cb; /* to be called by dispatcher just after fork to free
								   the child processes from entities of the parent */
	void* after_fork_cb_data;

	cleanup_cb_t at_term_cb; /* to be called after echld_terminate() is done */
	void* at_term_cb_data;

	void* user_data; /* free for you to use */
} echld_init_t;

/* will initialize echld forking the dispatcher and registering protocols and taps */
WS_DLL_PUBLIC void echld_initialize(echld_init_t*);

/* cleans up echld and kills the server process(es) */
WS_DLL_PUBLIC echld_state_t echld_terminate(void);


/*
 * returning ECHLD_NO_ERROR means there has being no error
 *
 * errstr_ptr is a ptr to  the error message string, will give NULL if no error
 *    usable only after the last API call, doesn't have to be freed.
 *
 * for managing asyncronous errors use a msgh for ECHLD_ERROR
 * the response cb of reqh might be a ECHLD_ERROR message
 */
WS_DLL_PUBLIC echld_error_t echld_get_error(const char** errstr_ptr);


/*
 * prototype of message callbacks passed to echld_reqh() and echld_msgh()
 *
 * type: for reqh it might be ECHLD_ERROR, ECHLD_TIMEOUT or what you expect,
 *        in msgh it's always the message for which it was set
 * msg_buff: the encoded message
 * cb_data: arbitrary data passed by the user in echld_reqh() or echld_msgh()
 *
 * returns TRUE if other potential handlers are to be run, false otherwise
 */
typedef echld_bool_t (*echld_msg_cb_t)(echld_msg_type_t type, enc_msg_t* msg_buff, void* cb_data);


/* encoding and decoding */


/*
 * encoder
 * the enc_msg_t will be destroyed internally by the req handler
 * the resulting enc_msg_t can be used in a reqh just once.
 */

typedef struct _parent_out {
	enc_msg_t* (*error)(int err, const char* text);
	enc_msg_t* (*get_param)(const char* param);
	enc_msg_t* (*set_param)(const char* param,  const char* value);
	enc_msg_t* (*close_child)(int mode);
	enc_msg_t* (*open_file)(const char* filename);
	enc_msg_t* (*open_interface)(const char* intf_name, const char* params);
	enc_msg_t* (*get_sum)(const char* range);
	enc_msg_t* (*get_tree)(const char* range);
	enc_msg_t* (*get_bufer)(const char* name);
	enc_msg_t* (*add_note)(int packet_number, const char* note);
	enc_msg_t* (*apply_filter)(const char* filter);
	enc_msg_t* (*save_file)(const char* filename, const char* params);
} echld_parent_encoder_t;


WS_DLL_PUBLIC echld_parent_encoder_t* echld_get_encoder(void);


/*
 * decoder
 * it returns an allocated string with the decoded response of the message, you free it.
 * it destroys the enc_msg_t as well.
 */
WS_DLL_PUBLIC char* echld_decode(echld_msg_type_t, enc_msg_t*);

/*
 *  Children Management Operations
 */

WS_DLL_PUBLIC enc_msg_t* echld_new_child_params(void);



/* takes the em, and param=value pairs of strings, NULL to end.
    echld_new_child_params_add_params(em,param1_str,val1_str,param2_str,val2_str,NULL);  */
WS_DLL_PUBLIC void echld_new_child_params_add_params(enc_msg_t*, ...);

WS_DLL_PUBLIC enc_msg_t* echld_new_child_params_merge(enc_msg_t*, enc_msg_t*);

#define ECHLD_NC_PARAMS_FMT "  %s='%s',\n" /* param='value' */
/* truncate takes off last N chars from the last item's fmt or prefix on empty */
WS_DLL_PUBLIC char* echld_new_child_params_str(enc_msg_t* em,
	const char* prefix, const char* postfix, int truncate, const char* fmt)
	G_GNUC_PRINTF(5, 0);


/* create a new worker process */
WS_DLL_PUBLIC echld_chld_id_t echld_new(enc_msg_t* new_child_parameters, echld_new_cb_t cb, void* child_data);

/* will return NULL on error, if NULL is also ok for you use echld_get_error() */
WS_DLL_PUBLIC void* echld_get_data(echld_chld_id_t);

WS_DLL_PUBLIC echld_state_t echld_set_data(echld_chld_id_t id, void* child_data);

/* for each child call cb(id,child_data,cb_data) */
typedef echld_bool_t (*echld_iter_cb_t)(echld_chld_id_t, void* child_data, void* cb_data);
WS_DLL_PUBLIC void echld_foreach_child(echld_iter_cb_t cb, void* cb_data);

/*
 *  Request Handlers
 *
 */

/* send a request with an optional response handler
 *
 * ba is a enc_msg_t that contains the encoded message
 * resp_cb is the callback and cb_data the data it is going to be passed if executed
 *
 * returns the reqh id */
WS_DLL_PUBLIC echld_reqh_id_t echld_reqh(echld_chld_id_t, echld_msg_type_t, int usecs_timeout, enc_msg_t*, echld_msg_cb_t, void*);

/* get callback data for a live request */
WS_DLL_PUBLIC void* echld_reqh_get_data(echld_chld_id_t, echld_reqh_id_t);

/* get the total timeout time for a live request, -1 is err */
WS_DLL_PUBLIC int echld_reqh_get_to(echld_chld_id_t, echld_reqh_id_t);

/* get the remaining timeout time for a live request, -1 is err */
WS_DLL_PUBLIC int echld_reqh_get_remaining_to(echld_chld_id_t, echld_reqh_id_t);

/* get the callback for a live request */
WS_DLL_PUBLIC echld_msg_cb_t echld_reqh_get_cb(echld_chld_id_t, echld_reqh_id_t);

/* set callback data for a live request */
WS_DLL_PUBLIC echld_state_t echld_reqh_set_data(echld_chld_id_t, echld_reqh_id_t, void* );

/* get the callback for a live request */
WS_DLL_PUBLIC echld_state_t echld_reqh_set_cb(echld_chld_id_t, echld_reqh_id_t, echld_msg_cb_t);

/* stop receiving a live request */
WS_DLL_PUBLIC echld_state_t echld_reqh_detach(echld_chld_id_t, echld_reqh_id_t);


/*
 *  Message Handlers
 *
 */

/* start a message handler */
WS_DLL_PUBLIC echld_msgh_id_t echld_msgh(echld_chld_id_t, echld_msg_type_t, echld_msg_cb_t resp_cb, void* msg_data);

/* stop it */
WS_DLL_PUBLIC echld_state_t echld_msgh_detach(echld_chld_id_t, echld_msgh_id_t);

/* get a msgh's data */
WS_DLL_PUBLIC void* echld_msgh_get_data(echld_chld_id_t, echld_msgh_id_t);

/* get a msgh's cb */
WS_DLL_PUBLIC echld_msg_cb_t echld_msgh_get_cb(echld_chld_id_t, echld_msgh_id_t);

/* get a msgh's type */
WS_DLL_PUBLIC echld_msg_type_t echld_msgh_get_type(echld_chld_id_t, echld_msgh_id_t);

/* get it all from a msgh */
WS_DLL_PUBLIC echld_state_t echld_msgh_get_all(echld_chld_id_t, int msgh_id, echld_msg_type_t*, echld_msg_cb_t*, void**);

/* set a msgh's data */
WS_DLL_PUBLIC echld_state_t echld_msgh_set_data(echld_chld_id_t, int msgh_id, void* );

/* set a msgh's cb */
WS_DLL_PUBLIC echld_state_t echld_msgh_set_cb(echld_chld_id_t, int msgh_id, echld_msg_cb_t);

/* set a msgh's type */
WS_DLL_PUBLIC echld_state_t echld_msgh_set_type(echld_chld_id_t, int msgh_id, echld_msg_type_t);

/* set all elements of a msgh */
WS_DLL_PUBLIC echld_state_t echld_msgh_set_all(echld_chld_id_t, int msgh_id, echld_msg_type_t, echld_msg_cb_t, void*);




/*
 * Server routines
 */

/*
 * waits until something gets done
 *
 * returns ECHLD_TIMEOUT or ECHLD_OK if something was done
 */
WS_DLL_PUBLIC echld_state_t echld_wait(tv_t* timeout);

#define ECHLD_WAIT() do { struct timeval tv; int rfds,  efds; \
	echld_select(echld_fdset(&rfds, &efds),&rfds, NULL, &efds, NULL) \
	&& echld_fd_read(&rfds, &efds); } while(0)

/*
   to be used in place of select() in the main loop of the parent code
   it will serve the children pipes and return as if select() was called.
*/
WS_DLL_PUBLIC int echld_select(int nfds, fd_set* rfds, fd_set* wfds, fd_set* efds, tv_t* timeout);

/* or fit these two in your select loop */

/* returns nfds set */
WS_DLL_PUBLIC int echld_fdset(fd_set* rfds, fd_set* efds);

WS_DLL_PUBLIC int echld_fd_read(fd_set* rfds, fd_set* efds);

WS_DLL_PUBLIC void echld_set_parent_dbg_level(int lvl);


#define ECHLD_MAX_CHILDREN 32

enum _echld_msg_type_t {
	/*  in = child to parent */
	/* out = parent to child */

	ECHLD_NULL ='\0',  /* To terminate array */
	ECHLD_ERROR = '!', /* in: an error has occurred,
						*	this can be a response to most messages
						*   some errors are sent asyncronously (some are handled internally, some are then passed)
						*/
	ECHLD_TIMED_OUT='/', /* in: A reqh has timed out (TO from now on)
						*	this can be a response to some messages
						*   some TOs are sent asyncronously (some are handled internally, some are then passed)
						*/

	ECHLD_NEW_CHILD = '*', /* out: creates a new working child  (handled internally)  */
	ECHLD_HELLO = '@', /* in: the working child has being created (handled internally, then passed to msgh) */

	ECHLD_CHILD_DEAD = '#', /* in: a child has dead (handled internally, then passed to msgh) */

	ECHLD_CLOSE_CHILD = 'Q', /* out: close the child  */
	ECHLD_CLOSING = 'q', /* in: the child is closing, error otherwise  */
						 /* this handled internally as msgh, if your reqh_cb uses it make sure to return TRUE */

	ECHLD_SET_PARAM = '>', /* out: set a parameter of a child  */
	ECHLD_GET_PARAM = '<', /* out: set a parameter of a child  */
	ECHLD_PARAM = 'p', /* in: the parameter's new/current value, error otherwise  */

						/* capture_filter string RO: set at open_capture */
						/* monitor_mode string RW: use monitor mode if possible, error otherwise */
						/* inc_pkt_ntfy_timeout number_string RW: timeout in usec after which notification is sent if no maxpackets have arrived yet */
						/* inc_pkt_ntfy_maxpackets number_string RW: number of packets after which send a notification */
						/* auto_sum RW: get summaries automatically (without a reqh, as msgh) */
						/* auto_tree RW: get trees automatically (without a reqh, as msgh)   */
						/* auto_buffer RW: get buffers automatically (without a reqh, as msgh) */
						/* cwd RW: the current working directory */
						/* list_files WO: a file listing of the current dir */
						/* interfaces RO: the interface listing */
						/* dfilter RW:  initial display filter*/
						/* dfilter_chk WO: check a display filter */
						/* ... */

	ECHLD_PING = '}', /* out: ping the child  */
	ECHLD_PONG = '{', /* out: ping's response, error or TO otherwise */

	ECHLD_OPEN_FILE = 'O', /* out: open a file  */
	ECHLD_FILE_OPENED = 'o', /* in: the file has being open, error otherwise */

	ECHLD_OPEN_INTERFACE = 'C',  /* out: request an interface to be open (get ready for capture)  */
	ECHLD_INTERFACE_OPENED = 'c', /* in: ready to start_capture, error otherwise */

	ECHLD_START_CAPTURE = 'R',  /* out: start capturing */
	ECHLD_CAPTURE_STARTED = 'r',  /* in: the capture has started, error otherwise */

	ECHLD_NOTIFY = '%', /* in: many things can be notified by the child:
	  						 	number of packets captured/read
								other events in the future (?)
	  						 	*/

	ECHLD_GET_SUM = 'S', /* out: get the summaries of a range of packets (even before they are notify'd) */
	ECHLD_PACKET_SUM = 's', /* in: a packet's summary (when it arrives for a reqh) (in msgh if auto_sum )*/
								/* no timeout, the request hangs until the packets in the range are available */
								/* error at EOF or CAPTURE_STOPPED if the request is still hanging */

	ECHLD_GET_TREE = 'G', /* out: get the decoded version of the packet  */
	ECHLD_TREE = 't', /* Child -> Parent */
								/* no timeout, the request hangs until the packets in the range are available */
								/* error at EOF or CAPTURE_STOPPED if the request is still hanging */


	ECHLD_GET_BUFFER = 'B', /* out: get the decoded version of the packet  */
	ECHLD_BUFFER = 'b', /* in: get a buffer (or what we have of it... or the next part... same reqh_id) */
								/* no timeout, the request hangs until the packets in the range are available */
								/* error at EOF or CAPTURE_STOPPED if the request is still hanging */

	ECHLD_EOF = 'z', /* in: will be delivered when a file has being read and all pendin ntfy,sums,trees and buffs have being passed
	 						or after capture has stopped and all pending stuff is done */

	ECHLD_STOP_CAPTURE = 'X',  /* out: stop capturing  */
	ECHLD_CAPTURE_STOPPED = 'x',  /* in: capture has stopped, error otherwise */

	ECHLD_ADD_NOTE = 'N', /* out: add a note to the capture  */
	ECHLD_NOTE_ADDED = 'n', /* in: a note has being added */

	ECHLD_APPLY_FILTER = 'A', /* in: apply a filter on the open file/capture */
	ECHLD_PACKET_LIST = 'l', /* out: a packet list, or error or timeout */
							/*(or what we have of it... or the next part... same reqh_id) */

	ECHLD_SAVE_FILE = 'W', /* out: save the open file/capture  */
	ECHLD_FILE_SAVED = 'w', /* in: the file was saved */


	EC_ACTUAL_ERROR = 0 /* this is not used in the protocol,
	                        it is returned for an error in calls returning a message type  */
};

enum _echld_error {
	ECHLD_NO_ERROR = 0,
	ECHLD_ERR_UNIMPLEMENTED,
	ECHLD_ERR_WRONG_MSG,
	ECHLD_ERR_NO_SUCH_CHILD,
	ECHLD_ERR_CHILD_EXISTS,
	ECHLD_ERR_UNKNOWN_PID,
	ECHLD_ERR_CANNOT_FORK,
	ECHLD_ERR_SET_FILTER,
	ECHLD_ERR_CANNOT_OPEN_FILE,
	ECHLD_ERR_CANNOT_OPEN_INTERFACE,
	ECHLD_ERR_CANNOT_START_CAPTURE,
	ECHLD_ERR_CANNOT_LIST_INTERFACES,
	ECHLD_CANNOT_SET_PARAM,
	ECHLD_CANNOT_GET_PARAM,
	ECHLD_ERR_CRASHED_CHILD,
	ECHLD_DECODE_ERROR,
	ECHLD_ERR_OTHER
};

#ifdef __cplusplus
};
#endif

#endif