2 * epan working child API
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Copyright (c) 2013 by Luis Ontanon <luis@ontanon.org>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include "ws_symbol_export.h"
36 #define ECHLD_VERSION "0.0"
37 #define ECHLD_MAJOR_VERSION 0 /* increases when existing things change */
38 /* if this changes an old client may or may not work */
40 #define ECHLD_MINOR_VERSION 0 /* increases when new things are added */
41 /* if just this one changes an old client will still work */
44 * You should take a look to doc/README.epan_child before reading this
48 typedef enum _echld_msg_type_t echld_msg_type_t
;
51 typedef enum _echld_error echld_error_t
;
54 /* 0 is ok, everything else is ko, or timeout where applicable. */
55 typedef int echld_state_t
;
57 #define ECHLD_TIMEOUT -222
59 /* id for child working processes, a negative value is an error */
60 typedef int echld_chld_id_t
;
62 /* id of requests, a negative value is an error */
63 typedef int echld_reqh_id_t
;
65 /* id of message handlers, a negative value is an error */
66 typedef int echld_msgh_id_t
;
68 /* enc_msg_t is an obscure object for an encoded message (a GbyteArray for now)*/
69 typedef struct _GByteArray enc_msg_t
;
71 /* sets the codec set by name */
72 typedef enum _echld_encoding
{
73 ECHLD_ENCODING_TEXT
= 'T',
74 ECHLD_ENCODING_XML
= 'X',
75 ECHLD_ENCODING_JSON
= 'J'
78 typedef int echld_bool_t
;
80 /* typedef for a timeval so that sys/time.h is not required in the client */
81 typedef struct timeval tv_t
;
83 typedef void (*cleanup_cb_t
)(void*);
84 typedef int (*main_t
)(int, char**); /* a pointer to main() */
86 /* these are called after a new child is created.
87 * chld_id = -1 on error/timeout
89 typedef void (*echld_new_cb_t
)(void* child_data
, const char* err
);
91 /* I will be passed to echld_initialize() */
92 typedef struct _echld_init
{
93 echld_encoding_t encoding
; /* only JSON for now */
95 char* argv0
; /* the value of argv[0] */
98 echld_new_cb_t dispatcher_hello_cb
; /* child_data will be a pointer to this echld_init_t */
100 cleanup_cb_t after_fork_cb
; /* to be called by dispatcher just after fork to free
101 the child processes from entities of the parent */
102 void* after_fork_cb_data
;
104 cleanup_cb_t at_term_cb
; /* to be called after echld_terminate() is done */
105 void* at_term_cb_data
;
107 void* user_data
; /* free for you to use */
110 /* will initialize echld forking the dispatcher and registering protocols and taps */
111 WS_DLL_PUBLIC
void echld_initialize(echld_init_t
*);
113 /* cleans up echld and kills the server process(es) */
114 WS_DLL_PUBLIC echld_state_t
echld_terminate(void);
118 * returning ECHLD_NO_ERROR means there has being no error
120 * errstr_ptr is a ptr to the error message string, will give NULL if no error
121 * usable only after the last API call, doesn't have to be freed.
123 * for managing asyncronous errors use a msgh for ECHLD_ERROR
124 * the response cb of reqh might be a ECHLD_ERROR message
126 WS_DLL_PUBLIC echld_error_t
echld_get_error(const char** errstr_ptr
);
130 * prototype of message callbacks passed to echld_reqh() and echld_msgh()
132 * type: for reqh it might be ECHLD_ERROR, ECHLD_TIMEOUT or what you expect,
133 * in msgh it's always the message for which it was set
134 * msg_buff: the encoded message
135 * cb_data: arbitrary data passed by the user in echld_reqh() or echld_msgh()
137 * returns TRUE if other potential handlers are to be run, false otherwise
139 typedef echld_bool_t (*echld_msg_cb_t
)(echld_msg_type_t type
, enc_msg_t
* msg_buff
, void* cb_data
);
142 /* encoding and decoding */
147 * the enc_msg_t will be destroyed internally by the req handler
148 * the resulting enc_msg_t can be used in a reqh just once.
151 typedef struct _parent_out
{
152 enc_msg_t
* (*error
)(int err
, const char* text
);
153 enc_msg_t
* (*get_param
)(const char* param
);
154 enc_msg_t
* (*set_param
)(const char* param
, const char* value
);
155 enc_msg_t
* (*close_child
)(int mode
);
156 enc_msg_t
* (*open_file
)(const char* filename
);
157 enc_msg_t
* (*open_interface
)(const char* intf_name
, const char* params
);
158 enc_msg_t
* (*get_sum
)(const char* range
);
159 enc_msg_t
* (*get_tree
)(const char* range
);
160 enc_msg_t
* (*get_bufer
)(const char* name
);
161 enc_msg_t
* (*add_note
)(int packet_number
, const char* note
);
162 enc_msg_t
* (*apply_filter
)(const char* filter
);
163 enc_msg_t
* (*save_file
)(const char* filename
, const char* params
);
164 } echld_parent_encoder_t
;
167 WS_DLL_PUBLIC echld_parent_encoder_t
* echld_get_encoder(void);
172 * it returns an allocated string with the decoded response of the message, you free it.
173 * it destroys the enc_msg_t as well.
175 WS_DLL_PUBLIC
char* echld_decode(echld_msg_type_t
, enc_msg_t
*);
178 * Children Management Operations
181 WS_DLL_PUBLIC enc_msg_t
* echld_new_child_params(void);
185 /* takes the em, and param=value pairs of strings, NULL to end.
186 echld_new_child_params_add_params(em,param1_str,val1_str,param2_str,val2_str,NULL); */
187 WS_DLL_PUBLIC
void echld_new_child_params_add_params(enc_msg_t
*, ...);
189 WS_DLL_PUBLIC enc_msg_t
* echld_new_child_params_merge(enc_msg_t
*, enc_msg_t
*);
191 #define ECHLD_NC_PARAMS_FMT " %s='%s',\n" /* param='value' */
192 /* truncate takes off last N chars from the last item's fmt or prefix on empty */
193 WS_DLL_PUBLIC
char* echld_new_child_params_str(enc_msg_t
* em
, const char* prefix
, const char* postfix
, int truncate
, const char* fmt
);
196 /* create a new worker process */
197 WS_DLL_PUBLIC echld_chld_id_t
echld_new(enc_msg_t
* new_child_parameters
, echld_new_cb_t cb
, void* child_data
);
199 /* will return NULL on error, if NULL is also ok for you use echld_get_error() */
200 WS_DLL_PUBLIC
void* echld_get_data(echld_chld_id_t
);
202 WS_DLL_PUBLIC echld_state_t
echld_set_data(echld_chld_id_t id
, void* child_data
);
204 /* for each child call cb(id,child_data,cb_data) */
205 typedef echld_bool_t (*echld_iter_cb_t
)(echld_chld_id_t
, void* child_data
, void* cb_data
);
206 WS_DLL_PUBLIC
void echld_foreach_child(echld_iter_cb_t cb
, void* cb_data
);
213 /* send a request with an optional response handler
215 * ba is a enc_msg_t that contains the encoded message
216 * resp_cb is the callback and cb_data the data it is going to be passed if executed
218 * returns the reqh id */
219 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*);
221 /* get callback data for a live request */
222 WS_DLL_PUBLIC
void* echld_reqh_get_data(echld_chld_id_t
, echld_reqh_id_t
);
224 /* get the total timeout time for a live request, -1 is err */
225 WS_DLL_PUBLIC
int echld_reqh_get_to(echld_chld_id_t
, echld_reqh_id_t
);
227 /* get the remaining timeout time for a live request, -1 is err */
228 WS_DLL_PUBLIC
int echld_reqh_get_remaining_to(echld_chld_id_t
, echld_reqh_id_t
);
230 /* get the callback for a live request */
231 WS_DLL_PUBLIC echld_msg_cb_t
echld_reqh_get_cb(echld_chld_id_t
, echld_reqh_id_t
);
233 /* set callback data for a live request */
234 WS_DLL_PUBLIC echld_state_t
echld_reqh_set_data(echld_chld_id_t
, echld_reqh_id_t
, void* );
236 /* get the callback for a live request */
237 WS_DLL_PUBLIC echld_state_t
echld_reqh_set_cb(echld_chld_id_t
, echld_reqh_id_t
, echld_msg_cb_t
);
239 /* stop receiving a live request */
240 WS_DLL_PUBLIC echld_state_t
echld_reqh_detach(echld_chld_id_t
, echld_reqh_id_t
);
248 /* start a message handler */
249 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
);
252 WS_DLL_PUBLIC echld_state_t
echld_msgh_detach(echld_chld_id_t
, echld_msgh_id_t
);
254 /* get a msgh's data */
255 WS_DLL_PUBLIC
void* echld_msgh_get_data(echld_chld_id_t
, echld_msgh_id_t
);
257 /* get a msgh's cb */
258 WS_DLL_PUBLIC echld_msg_cb_t
echld_msgh_get_cb(echld_chld_id_t
, echld_msgh_id_t
);
260 /* get a msgh's type */
261 WS_DLL_PUBLIC echld_msg_type_t
echld_msgh_get_type(echld_chld_id_t
, echld_msgh_id_t
);
263 /* get it all from a msgh */
264 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**);
266 /* set a msgh's data */
267 WS_DLL_PUBLIC echld_state_t
echld_msgh_set_data(echld_chld_id_t
, int msgh_id
, void* );
269 /* set a msgh's cb */
270 WS_DLL_PUBLIC echld_state_t
echld_msgh_set_cb(echld_chld_id_t
, int msgh_id
, echld_msg_cb_t
);
272 /* set a msgh's type */
273 WS_DLL_PUBLIC echld_state_t
echld_msgh_set_type(echld_chld_id_t
, int msgh_id
, echld_msg_type_t
);
275 /* set all elements of a msgh */
276 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*);
286 * waits until something gets done
288 * returns ECHLD_TIMEOUT or ECHLD_OK if something was done
290 WS_DLL_PUBLIC echld_state_t
echld_wait(tv_t
* timeout
);
292 #define ECHLD_WAIT() do { struct timeval tv; int rfds, efds; \
293 echld_select(echld_fdset(&rfds, &efds),&rfds, NULL, &efds, NULL) \
294 && echld_fd_read(&rfds, &efds); } while(0)
297 to be used in place of select() in the main loop of the parent code
298 it will serve the children pipes and return as if select() was called.
300 WS_DLL_PUBLIC
int echld_select(int nfds
, fd_set
* rfds
, fd_set
* wfds
, fd_set
* efds
, tv_t
* timeout
);
302 /* or fit these two in your select loop */
304 /* returns nfds set */
305 WS_DLL_PUBLIC
int echld_fdset(fd_set
* rfds
, fd_set
* efds
);
307 WS_DLL_PUBLIC
int echld_fd_read(fd_set
* rfds
, fd_set
* efds
);
309 WS_DLL_PUBLIC
void echld_set_parent_dbg_level(int lvl
);
312 #define ECHLD_MAX_CHILDREN 32
314 enum _echld_msg_type_t
{
315 /* in = child to parent */
316 /* out = parent to child */
318 ECHLD_NULL
='\0', /* To terminate array */
319 ECHLD_ERROR
= '!', /* in: an error has occurred,
320 * this can be a response to most messages
321 * some errors are sent asyncronously (some are handled internally, some are then passed)
323 ECHLD_TIMED_OUT
='/', /* in: A reqh has timed out (TO from now on)
324 * this can be a response to some messages
325 * some TOs are sent asyncronously (some are handled internally, some are then passed)
328 ECHLD_NEW_CHILD
= '*', /* out: creates a new working child (handled internally) */
329 ECHLD_HELLO
= '@', /* in: the working child has being created (handled internally, then passed to msgh) */
331 ECHLD_CHILD_DEAD
= '#', /* in: a child has dead (handled internally, then passed to msgh) */
333 ECHLD_CLOSE_CHILD
= 'Q', /* out: close the child */
334 ECHLD_CLOSING
= 'q', /* in: the child is closing, error otherwise */
335 /* this handled internally as msgh, if your reqh_cb uses it make sure to return TRUE */
337 ECHLD_SET_PARAM
= '>', /* out: set a parameter of a child */
338 ECHLD_GET_PARAM
= '<', /* out: set a parameter of a child */
339 ECHLD_PARAM
= 'p', /* in: the parameter's new/current value, error otherwise */
341 /* capture_filter string RO: set at open_capture */
342 /* monitor_mode string RW: use monitor mode if possible, error otherwise */
343 /* inc_pkt_ntfy_timeout number_string RW: timeout in usec after which notification is sent if no maxpackets have arrived yet */
344 /* inc_pkt_ntfy_maxpackets number_string RW: number of packets after which send a notification */
345 /* auto_sum RW: get summaries automatically (without a reqh, as msgh) */
346 /* auto_tree RW: get trees automatically (without a reqh, as msgh) */
347 /* auto_buffer RW: get buffers automatically (without a reqh, as msgh) */
348 /* cwd RW: the current working directory */
349 /* list_files WO: a file listing of the current dir */
350 /* interfaces RO: the interface listing */
351 /* dfilter RW: initial display filter*/
352 /* dfilter_chk WO: check a display filter */
355 ECHLD_PING
= '}', /* out: ping the child */
356 ECHLD_PONG
= '{', /* out: ping's response, error or TO otherwise */
358 ECHLD_OPEN_FILE
= 'O', /* out: open a file */
359 ECHLD_FILE_OPENED
= 'o', /* in: the file has being open, error otherwise */
361 ECHLD_OPEN_INTERFACE
= 'C', /* out: request an interface to be open (get ready for capture) */
362 ECHLD_INTERFACE_OPENED
= 'c', /* in: ready to start_capture, error otherwise */
364 ECHLD_START_CAPTURE
= 'R', /* out: start capturing */
365 ECHLD_CAPTURE_STARTED
= 'r', /* in: the capture has started, error otherwise */
367 ECHLD_NOTIFY
= '%', /* in: many things can be notified by the child:
368 number of packets captured/read
369 other events in the future (?)
372 ECHLD_GET_SUM
= 'S', /* out: get the summaries of a range of packets (even before they are notify'd) */
373 ECHLD_PACKET_SUM
= 's', /* in: a packet's summary (when it arrives for a reqh) (in msgh if auto_sum )*/
374 /* no timeout, the request hangs until the packets in the range are available */
375 /* error at EOF or CAPTURE_STOPPED if the request is still hanging */
377 ECHLD_GET_TREE
= 'G', /* out: get the decoded version of the packet */
378 ECHLD_TREE
= 't', /* Child -> Parent */
379 /* no timeout, the request hangs until the packets in the range are available */
380 /* error at EOF or CAPTURE_STOPPED if the request is still hanging */
383 ECHLD_GET_BUFFER
= 'B', /* out: get the decoded version of the packet */
384 ECHLD_BUFFER
= 'b', /* in: get a buffer (or what we have of it... or the next part... same reqh_id) */
385 /* no timeout, the request hangs until the packets in the range are available */
386 /* error at EOF or CAPTURE_STOPPED if the request is still hanging */
388 ECHLD_EOF
= 'z', /* in: will be delivered when a file has being read and all pendin ntfy,sums,trees and buffs have being passed
389 or after capture has stopped and all pending stuff is done */
391 ECHLD_STOP_CAPTURE
= 'X', /* out: stop capturing */
392 ECHLD_CAPTURE_STOPPED
= 'x', /* in: capture has stopped, error otherwise */
394 ECHLD_ADD_NOTE
= 'N', /* out: add a note to the capture */
395 ECHLD_NOTE_ADDED
= 'n', /* in: a note has being added */
397 ECHLD_APPLY_FILTER
= 'A', /* in: apply a filter on the open file/capture */
398 ECHLD_PACKET_LIST
= 'l', /* out: a packet list, or error or timeout */
399 /*(or what we have of it... or the next part... same reqh_id) */
401 ECHLD_SAVE_FILE
= 'W', /* out: save the open file/capture */
402 ECHLD_FILE_SAVED
= 'w', /* in: the file was saved */
405 EC_ACTUAL_ERROR
= 0 /* this is not used in the protocol,
406 it is returned for an error in calls returning a message type */
411 ECHLD_ERR_UNIMPLEMENTED
,
413 ECHLD_ERR_NO_SUCH_CHILD
,
414 ECHLD_ERR_CHILD_EXISTS
,
415 ECHLD_ERR_UNKNOWN_PID
,
416 ECHLD_ERR_CANNOT_FORK
,
417 ECHLD_ERR_SET_FILTER
,
418 ECHLD_ERR_CANNOT_OPEN_FILE
,
419 ECHLD_ERR_CANNOT_OPEN_INTERFACE
,
420 ECHLD_ERR_CANNOT_START_CAPTURE
,
421 ECHLD_ERR_CANNOT_LIST_INTERFACES
,
422 ECHLD_CANNOT_SET_PARAM
,
423 ECHLD_CANNOT_GET_PARAM
,
424 ECHLD_ERR_CRASHED_CHILD
,