From 880e19ac3d8e1b14448c3729af2ca2c62879a25f Mon Sep 17 00:00:00 2001 From: Luis Ontanon Date: Fri, 5 Jul 2013 23:57:07 +0000 Subject: Yet another iteration: - improve the parameter api - Add a parameter set message to the NEW child message to set parameters in bulk in the child - some more harvestig from tshark svn path=/trunk/; revision=50393 --- echld/child.c | 163 +++++++++++++++++++++++++----------------------- echld/common.c | 89 ++++++++++++++++++++++++++ echld/dispatcher.c | 180 +++++++++++++++++++++++++++++------------------------ echld/echld-int.h | 50 +++++++++++---- echld/echld.h | 75 +++++++++++++++------- echld/parent.c | 59 +++++++++++++++--- 6 files changed, 413 insertions(+), 203 deletions(-) (limited to 'echld') diff --git a/echld/child.c b/echld/child.c index daa9e7c8a4..3d83e6425b 100644 --- a/echld/child.c +++ b/echld/child.c @@ -61,6 +61,7 @@ typedef struct _child { } echld_child_t; +static echld_epan_stuff_t* stuff = NULL; static echld_child_t child; @@ -143,8 +144,8 @@ static void sig_term(int sig _U_) { exit(0); } - -void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id) { +extern void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id, echld_epan_stuff_t* es) { + stuff = es; close_sleep_time.tv_sec = CHILD_CLOSE_SLEEP_TIME / 1000000; close_sleep_time.tv_usec = CHILD_CLOSE_SLEEP_TIME % 1000000; @@ -298,11 +299,48 @@ static char* param_get_file_list(char** err) { return s; } +#ifdef PCAP_NG_DEFAULT +static int out_file_type = WTAP_FILE_PCAPNG; +#else +static int out_file_type = WTAP_FILE_PCAP; +#endif + +static echld_bool_t param_set_out_file_type(char* val, char** err) { + int oft = wtap_short_string_to_file_type(val); + + if (oft < 0) { + *err = g_strdup_printf("\"%s\" isn't a valid capture file type", val); + return FALSE; + } else { + out_file_type = oft; + return TRUE; + } +} + +static char* param_get_out_file_type(char** err _U_) { + return g_strdup_printf("%s(%d): %s", + wtap_file_type_short_string(out_file_type), + out_file_type, wtap_file_type_string(out_file_type)); +} + + +static echld_bool_t param_set_add_hosts_file(char* val, char** err) { + if (add_hosts_file(val)) { + return TRUE; + } else { + *err = g_strdup_printf("Can't read host entries from \"%s\"",val); + return FALSE; + } +} + PARAM_BOOL(quiet,FALSE); +PARAM_BOOL(start_capture,FALSE); +PARAM_BOOL(push_details,FALSE); +PARAM_BOOL(print_hex,FALSE); static char* param_get_params(char** err _U_); -static param_t params[] = { +static param_t child_params[] = { #ifdef DEBUG_CHILD PARAM(dbg_level,"Debug Level (0name;p++) { - g_string_append_printf(str,"%s(%s): %s\n", - p->name,((p->get && p->set)?"rw":(p->get?"ro":"wo")),p->desc); - } - - s = str->str; - g_string_free(str,FALSE); - return s; + return paramset_get_params_list(child_params,PARAM_LIST_FMT); } -static param_t* get_paramset(char* name) { - int i; - for (i = 0; params[i].name != NULL;i++) { - if (strcmp(name,params[i].name) == 0 ) return &(params[i]); - } - return NULL; -} - - - - - - static void child_open_file(char* filename) { CHILD_DBG((2,"CMD open file filename='%s'",filename)); child_err(ECHLD_ERR_UNIMPLEMENTED,child.reqh_id,"open file not implemented yet!"); @@ -402,6 +421,7 @@ static void child_save_file(char* filename, char* pars) { static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_msg_type_t type, echld_reqh_id_t reqh_id, void* data _U_) { GByteArray ba; GByteArray* gba; + char* err = NULL; child.reqh_id = reqh_id; @@ -415,15 +435,22 @@ static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_ return 0; } + ba.data = b; + ba.len = (guint)len; + switch(type) { case ECHLD_NEW_CHILD: { - child.state = IDLE; - CHILD_RESP(NULL,ECHLD_HELLO); + child.state = CREATING; + if ( !paramset_apply_em(child_params,(enc_msg_t*)&ba, &err) ) { + child_err(ECHLD_ERR_CRASHED_CHILD,reqh_id, + "Initial Paramset Error '%s'",err); + } else { + child.state = IDLE; + CHILD_RESP(NULL,ECHLD_HELLO); + } break; } case ECHLD_PING: - ba.data = b; - ba.len = (guint)len; CHILD_DBG((1,"PONG")); CHILD_RESP(&ba,ECHLD_PONG); break; @@ -432,23 +459,10 @@ static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_ char* value; if ( child.dec->set_param && child.dec->set_param(b,len,¶m,&value) ) { - param_t* p = get_paramset(param); - char* err; - - if (!p) { - child_err(ECHLD_CANNOT_SET_PARAM,reqh_id,"no such param='%s'",param); - break; - } - - if (!p->set) { - child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"reason='read only'"); - break; - } - - if (! p->set(value,&err) ) { - child_err(ECHLD_CANNOT_SET_PARAM,reqh_id,"reason='%s'",err); + if (! paramset_apply_set (child_params, param, value, &err) ) { + child_err(ECHLD_CANNOT_SET_PARAM,reqh_id,"%s",err); g_free(err); - break; + return 0; } gba = child.enc->param(param,value); @@ -464,27 +478,14 @@ static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_ case ECHLD_GET_PARAM: { char* param; if ( child.dec->get_param && child.dec->get_param(b,len,¶m) ) { - char* err; char* val; - param_t* p = get_paramset(param); - - if (!p) { - child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"no such param='%s'",param); - break; - } - - if (!p->get) { - child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"reason='write only'"); - break; - } - - if (!(val = p->get(&err))) { - child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"reason='%s'",err); + if (! (val = paramset_apply_get (child_params, param, &err)) ) { + child_err(ECHLD_CANNOT_GET_PARAM,reqh_id,"%s",err); g_free(err); - break; + return 0; } - + gba = child.enc->param(param,val); CHILD_RESP(gba,ECHLD_PARAM); g_byte_array_free(gba,TRUE); @@ -627,11 +628,16 @@ static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_ } -static void child_dumpcap_read(void) { +static int child_dumpcap_read(void) { // this folk manages the reading of dumpcap's pipe // it has to read interface descriptions when doing so // and managing capture during capture - CHILD_DBG((2,"child_dumpcap_read")); + CHILD_DBG((2,"child_dumpcap_read")); + return FALSE; +} + +static void child_file_read(void) { + } int echld_child_loop(void) { @@ -650,6 +656,7 @@ int echld_child_loop(void) { fd_set efds; struct timeval timeout; int nfds; + gboolean captured = FALSE; FD_ZERO(&rfds); FD_ZERO(&wfds); @@ -664,16 +671,15 @@ int echld_child_loop(void) { FD_SET(child.fds.pipe_from_dumpcap,&rfds); } - if (child.fds.file_being_read > 0) { - FD_SET(child.fds.file_being_read,&rfds); - } - #ifdef DEBUG_CHILD - if (step >= 100) CHILD_DBG((4,"child_loop: select()ing step=%d",step++)); + if (step <= 20) CHILD_DBG((4,"child_loop: select()ing step=%d",step++)); #endif + timeout.tv_sec = 0; + timeout.tv_usec = 999999; + nfds = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout); #ifdef DEBUG_CHILD - if (step >= 100) CHILD_DBG((4,"child_loop: select()ed nfds=%d",nfds)); + if (step <= 20) CHILD_DBG((4,"child_loop: select()ed nfds=%d",nfds)); #endif if ( FD_ISSET(disp_from,&efds) ) { @@ -691,11 +697,6 @@ int echld_child_loop(void) { break; } - if (child.fds.file_being_read > 0 && FD_ISSET(child.fds.file_being_read,&efds) ) { - CHILD_DBG((0,"Broken Readfile Pipe step=%d",step)); - break; - } - if (FD_ISSET(disp_from, &rfds)) { long st = echld_read_frame(&(child.parent), child_receive, &child); @@ -714,7 +715,11 @@ int echld_child_loop(void) { #ifdef DEBUG_CHILD step = 0; #endif - child_dumpcap_read(); + captured = child_dumpcap_read(); + } + + if ( child.state == READING || captured ) { + child_file_read(); } } while(1); diff --git a/echld/common.c b/echld/common.c index b69c876c00..afa7185688 100644 --- a/echld/common.c +++ b/echld/common.c @@ -338,7 +338,96 @@ long echld_write_frame(int fd, GByteArray* ba, guint16 chld_id, echld_msg_type_t return (long) writev(fd, iov, iov_cnt); } +/* paramset management */ +param_t* paramset_find (param_t* paramsets, char* name, char** err) { + int i; + for (i = 0; paramsets[i].name != NULL;i++) { + if (strcmp(name,paramsets[i].name) == 0 ) return &(paramsets[i]); + } + + *err = g_strdup_printf("Could not find param='%s'",name); + return NULL; +} + +echld_bool_t paramset_apply_set (param_t* paramsets, char* name, char* val, char** err) { + param_t* p = paramset_find(paramsets,name,err); + + if ( !p ) return FALSE; + if ( ! p->set ) { + *err = g_strdup_printf("Cannot set RO param='%s'",name); + return FALSE; + } + + return p->set(val,err); +} + +char* paramset_apply_get (param_t* paramsets, char* name, char** err) { + param_t* p = paramset_find(paramsets,name,err); + + if ( !p ) return NULL; + + if ( ! p->get ) { + *err = g_strdup_printf("Cannot get WO param='%s'",name); + return NULL; + } + + return p->get(err); +} + +echld_bool_t paramset_apply_em(param_t* paramset, enc_msg_t* em, char** err) { + GByteArray* ba = (GByteArray*)em; + char* p = (char*) ba->data; + int tot_len = ba->len; + long rem = tot_len; + p[rem-1] = '\0'; /* make sure last char is null */ + + while(rem > 2) { + char* param = p; + long param_len = strlen(param)+1; + char* value = p + param_len; + long value_len; + + rem -= param_len; + + if (rem < 0) { + *err = g_strdup_printf("Malformed msg param len invalid"); + return FALSE; + } + + value_len = strlen(value)+1; + + rem -= value_len; + p = value + value_len; + + if (rem < 0) { + *err = g_strdup_printf("Malformed msg value len invalid"); + return FALSE; + } + + if (! paramset_apply_set(paramset,param,value,err)) + return FALSE; + } + + return TRUE; +} + +char* paramset_get_params_list(param_t* paramsets,const char* fmt) { + param_t* p = paramsets; + GString* str = g_string_new(""); + char* s; + + for (;p->name;p++) { + g_string_append_printf(str,fmt, + p->name, + ((p->get && p->set)?"rw":(p->get?"ro":"wo")), + p->desc); + } + + s = str->str; + g_string_free(str,FALSE); + return s; +} /* encoders and decoders */ diff --git a/echld/dispatcher.c b/echld/dispatcher.c index 39bb8bc34b..714858d2fa 100644 --- a/echld/dispatcher.c +++ b/echld/dispatcher.c @@ -65,7 +65,6 @@ struct dispatcher { struct dispatcher* dispatcher; - #ifdef DEBUG_DISPATCHER static int debug_lvl = DEBUG_DISPATCHER; static FILE* debug_fp = NULL; @@ -135,6 +134,17 @@ static long dbg_r = 0; #define DISP_RESP(B,T) (DISP_WRITE( dispatcher->parent_out, (B), 0, (T), dispatcher->reqh_id)) + +static echld_epan_stuff_t stuff; + +static void init_stuff(void) { +#ifdef HAVE_LIBPCAP + capture_opts_init(&stuff.cap_opts); + capture_session_init(&stuff.cap_sess, (void *)&stuff.cfile); +#endif + +} + static void children_massacre(void) { int i; struct dispatcher_child* cc = dispatcher->children; @@ -314,7 +324,7 @@ static char* intflist2json(GList* if_list, char** if_cap_err) { return s; } -static char* intf_list; +static char* intf_list = NULL; static void get_interfaces(char** err) { int err_no = 0; @@ -342,11 +352,11 @@ static char* param_get_interfaces(char** err _U_) { static long disp_loop_timeout_usec = DISPATCHER_WAIT_INITIAL; -static char* param_get_loop_to(char** err _U_) { +static char* param_get_loop_timeout(char** err _U_) { return g_strdup_printf("%fs", (((float)disp_loop_timeout_usec)/1000000.0) ); } -static echld_bool_t param_set_loop_to(char* val , char** err ) { +static echld_bool_t param_set_loop_timeout(char* val , char** err ) { char* p; int usec = (int)strtol(val, &p, 10); /*XXX: "10ms" or "500us" or "1s" */ @@ -360,67 +370,79 @@ static echld_bool_t param_set_loop_to(char* val , char** err ) { return TRUE; } -GString *comp_info_str; -GString *runtime_info_str; +static GString *comp_info_str; +static GString *runtime_info_str; +static const char* version_str = "Echld " VERSION; +static char* version_long_str = NULL; + + +static char* param_get_long_version(char** err _U_) { + return g_strdup(version_long_str); +} static char* param_get_version(char** err _U_) { - char* str; + return g_strdup(version_str); +} + +static char* param_get_capture_types(char** err _U_) { + GString* str = g_string_new(""); + char* s; + int i; + + for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) { + if (wtap_dump_can_open(i)) { + g_string_append_printf(str,"%s: %s\n", + wtap_file_type_short_string(i), wtap_file_type_string(i)); + } + } - str = g_strdup_printf("Echld " VERSION "%s\n" - "\n" - "%s" - "\n" - "%s" - "\n" - "%s", - wireshark_svnversion, get_copyright_info(), comp_info_str->str, - runtime_info_str->str); + s = str->str; + g_string_free(str,FALSE); + return s; +} - g_string_free(runtime_info_str,TRUE); - g_string_free(comp_info_str,TRUE); +static echld_bool_t param_set_add_hosts_file(char* val, char** err) { + if (add_hosts_file(val)) { + return TRUE; + } else { + *err = g_strdup_printf("Can't read host entries from \"%s\"",val); + return FALSE; + } +} - return str; +static echld_bool_t param_set_x_opt(char* val, char** err) { + if (ex_opt_add(val)) { + return TRUE; + } else { + *err = g_strdup_printf("Cannot set X opt '%s'",val); + return FALSE; + } } + + + static char* param_get_params(char** err _U_); static param_t disp_params[] = { #ifdef DEBUG_DISPATCHER - {"dbg_level", param_get_dbg_level, param_set_dbg_level,"0>int>5"}, + PARAM(dbg_level,"0>int>5"), # endif - {"version",param_get_version,NULL,"version string"}, - {"loop_timeout",param_get_loop_to,param_set_loop_to,"main loop step timeout"}, - {"interfaces",param_get_interfaces,NULL,"interface information"}, - {"params",param_get_params,NULL,"this list"}, + RO_PARAM(long_version,"long version string"), + RO_PARAM(version,"version string"), + PARAM(loop_timeout,"main loop step timeout"), + RO_PARAM(interfaces,"interface information"), + RO_PARAM(capture_types,"the available capture types"), + WO_PARAM(add_hosts_file,"Add a hosts file"), + WO_PARAM(x_opt,"Set a -X option"), + RO_PARAM(params,"This List"), {NULL,NULL,NULL,NULL} }; static char* param_get_params(char** err _U_) { - param_t* p = disp_params; - GString* str = g_string_new(""); - char* s; - - for (;p->name;p++) { - g_string_append_printf(str,"%s(%s): %s\n", - p->name,((p->get && p->set)?"rw":(p->get?"ro":"wo")),p->desc); - } - - s = str->str; - g_string_free(str,FALSE); - return s; -} - - -static param_t* get_paramset(char* name) { - int i; - for (i = 0; disp_params[i].name != NULL;i++) { - if (strcmp(name,disp_params[i].name) == 0 ) return &(disp_params[i]); - } - return NULL; + return paramset_get_params_list(disp_params,PARAM_LIST_FMT); } - - static struct dispatcher_child* dispatcher_get_child(struct dispatcher* d, int chld_id) { int i; struct dispatcher_child* cc = d->children; @@ -451,6 +473,12 @@ static void set_dumpcap_pid(int pid) { } static void preinit_epan(char* argv0, int (*main)(int, char **)) { + char *gpf_path, *pf_path; + char *gdp_path, *dp_path; + int gpf_open_errno, gpf_read_errno; + int pf_open_errno, pf_read_errno; + int gdp_open_errno, gdp_read_errno; + int dp_open_errno, dp_read_errno; char* error; error = init_progfile_dir(argv0, main); @@ -461,7 +489,9 @@ static void preinit_epan(char* argv0, int (*main)(int, char **)) { runtime_info_str = g_string_new("Running "); get_runtime_version_info(runtime_info_str, NULL); - capture_opts_init(&dispatcher->capture_opts); + version_long_str = g_strdup_printf("%s%s\n%s\n%s\n%s", + version_str, wireshark_svnversion, get_copyright_info(), + comp_info_str->str, runtime_info_str->str); if (error) { DISP_FATAL((CANNOT_PREINIT_EPAN,"Failed epan_preinit: msg='%s'",error)); @@ -470,6 +500,8 @@ static void preinit_epan(char* argv0, int (*main)(int, char **)) { /* Add it to the information to be reported on a crash. */ ws_add_crash_info("Echld " VERSION "%s\n%s\n%s", wireshark_svnversion, comp_info_str->str, runtime_info_str->str); + + init_stuff(); capture_sync_set_fetch_dumpcap_pid_cb(set_dumpcap_pid); @@ -481,28 +513,38 @@ static void preinit_epan(char* argv0, int (*main)(int, char **)) { DISP_FATAL((CANNOT_PREINIT_EPAN,"Error getting interfaces: %s", error)); } - prefs_apply_all(); /* disabled protocols as per configuration file */ set_disabled_protos_list(); - /* Here we do initialization of parts of epan that will be the same for every child we fork */ + initialize_funnel_ops(); - DISP_DBG((2,"epan preinit done")); + setlocale(LC_ALL, ""); + + stuff.prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path, &pf_open_errno, &pf_read_errno, &pf_path); + // check 4 errors + + read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno); + // check 4 errors + cap_file_init(&stuff.cfile); + + timestamp_set_precision(TS_PREC_AUTO_USEC); + + DISP_DBG((2,"epan preinit done")); } static void dispatcher_clear(void) { DISP_DBG((2,"dispatcher_clear")); /* remove unnecessary stuff for the working child */ + /* remove signal handlers */ } void dispatcher_sig(int sig) { DISP_FATAL((TERMINATED,"SIG sig=%d",sig)); exit(1); - } void dispatcher_reaper(int sig) { @@ -701,7 +743,7 @@ static void detach_new_child(enc_msg_t* em, echld_chld_id_t chld_id) { close(pipe_to_child); close(pipe_from_child); - echld_child_initialize(chld_id, pipe_from_disp,pipe_to_disp,reqh_id); + echld_child_initialize(chld_id, pipe_from_disp,pipe_to_disp,reqh_id,&stuff); exit( echld_child_loop() ); @@ -768,20 +810,9 @@ static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, ec char* value; if ( dispatcher->dec.from_parent->set_param(b,len,¶m,&value) ) { GByteArray* ba; - param_t* p = get_paramset(param); char* err; - if (!p) { - dispatcher_err(ECHLD_CANNOT_SET_PARAM,"no such param='%s'",param); - return 0; - } - - if (! p->set ) { - dispatcher_err(ECHLD_CANNOT_SET_PARAM,"reason='read only'"); - return 0; - } - - if (! p->set(value,&err) ) { - dispatcher_err(ECHLD_CANNOT_SET_PARAM,"reason='%s'",err); + if (! paramset_apply_set (disp_params, param, value, &err) ) { + dispatcher_err(ECHLD_CANNOT_SET_PARAM,"%s",err); g_free(err); return 0; } @@ -804,20 +835,8 @@ static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, ec char* err; char* val; - param_t* p = get_paramset(param); - - if (!p) { - dispatcher_err(ECHLD_CANNOT_GET_PARAM,"no such param='%s'",param); - return 0; - } - - if (! p->get ) { - dispatcher_err(ECHLD_CANNOT_SET_PARAM,"reason='write only'"); - return 0; - } - - if (!(val = p->get(&err))) { - dispatcher_err(ECHLD_CANNOT_GET_PARAM,"reason='%s'",err); + if (! (val = paramset_apply_get (disp_params, param, &err)) ) { + dispatcher_err(ECHLD_CANNOT_GET_PARAM,"%s",err); g_free(err); return 0; } @@ -1021,7 +1040,6 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, in dispatcher = &d; - echld_init_reader(&(d.parent_in),in_pipe_fds[0],4096); d.parent_out = out_pipe_fds[1]; d.children = g_new0(struct dispatcher_child,ECHLD_MAX_CHILDREN); diff --git a/echld/echld-int.h b/echld/echld-int.h index 32fa26ed73..0c9b58d0a1 100644 --- a/echld/echld-int.h +++ b/echld/echld-int.h @@ -48,6 +48,7 @@ #include #include #include +#include #include @@ -62,11 +63,16 @@ #include "capture_ifinfo.h" #include "capture_sync.h" #include "version_info.h" +#include "cfile.h" #include "wsutil/crash_info.h" #include "wsutil/privileges.h" #include "epan/filesystem.h" #include "epan/epan.h" #include "epan/prefs.h" +#include "epan/ex-opt.h" +#include "epan/funnel.h" +#include "epan/prefs.h" +#include "epan/timestamp.h" #include "disabled_protos.h" #include "echld.h" @@ -149,6 +155,15 @@ typedef struct _param { const char* desc; } param_t; +extern param_t* paramset_find (param_t* paramsets, char* name, char** err); + +extern char* paramset_apply_get (param_t* paramsets, char* name, char** err); +extern echld_bool_t paramset_apply_set (param_t* paramsets, char* name, char* val, char** err); +extern echld_bool_t paramset_apply_em(param_t* paramset, enc_msg_t* em, char** err); + +#define PARAM_LIST_FMT "%s(%s): %s\n" /* name, rw|ro|wo, desc */ +char* paramset_get_params_list(param_t* paramsets,const char* fmt); + #define PARAM_STR(Name, Default) static char* param_ ## Name = Default; \ static char* param_get_ ## Name (char** err _U_ ) { return (param_ ## Name) ? g_strdup(param_ ## Name) : (*err = g_strdup( #Name " not set"), NULL); } \ static echld_bool_t param_set_ ## Name (char* val , char** err _U_) { if (param_ ## Name) g_free(param_ ## Name); param_ ## Name = g_strdup(val); return TRUE; } \ @@ -165,6 +180,15 @@ typedef struct _param { #define RO_PARAM(Name,Desc) {#Name, param_get_ ## Name, NULL, Desc} #define WO_PARAM(Name,Desc) {#Name, NULL, param_set_ ## Name, Desc} +typedef struct _echld_epan_stuff_t { +#ifdef HAVE_LIBPCAP + capture_session cap_sess; + capture_options cap_opts; + capture_file cfile; +#endif + e_prefs* prefs; +} echld_epan_stuff_t; + /* the call_back used by read_frame() */ typedef long (*read_cb_t)(guint8*, size_t, echld_chld_id_t, echld_msg_type_t, echld_reqh_id_t, void*); @@ -216,7 +240,7 @@ extern long echld_read_frame(echld_reader_t* r, read_cb_t cb, void* cb_data); extern long echld_write_frame(int fd, GByteArray* ba, guint16 chld_id, echld_msg_type_t type, guint16 reqh_id, void* data); -extern void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id); +extern void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id, echld_epan_stuff_t* es); extern int echld_child_loop(void); /* never returns*/ @@ -242,21 +266,25 @@ extern void echld_unused(void); #define DISP_KILLED_CHILD_WAIT 100000 /* 0.1s */ /* fatalities */ -#define BROKEN_PARENT_PIPE 123 -#define BROKEN_DUMPCAP_PIPE 124 -#define BROKEN_READFILE 125 -#define DISPATCHER_DEAD 126 -#define UNIMPLEMENTED 127 -#define CANNOT_FORK 128 -#define SHOULD_HAVE_EXITED_BEFORE 129 -#define DISPATCHER_PIPE_FAILED 130 -#define TERMINATED 140 -#define CANNOT_PREINIT_EPAN 141 +#define BROKEN_PARENT_PIPE 9 +#define BROKEN_DUMPCAP_PIPE 10 +#define BROKEN_READFILE 11 +#define DISPATCHER_DEAD 12 +#define UNIMPLEMENTED 13 +#define CANNOT_FORK 14 +#define SHOULD_HAVE_EXITED_BEFORE 15 +#define DISPATCHER_PIPE_FAILED 16 +#define TERMINATED 17 +#define CANNOT_PREINIT_EPAN 18 +#define NO_INITIALIZER 19 #ifndef DEBUG_BASE #define echld_common_set_dbg(a,b,c) #endif + + + #ifdef __cplusplus extern "C" { #endif diff --git a/echld/echld.h b/echld/echld.h index 551402cb15..2928757607 100644 --- a/echld/echld.h +++ b/echld/echld.h @@ -1,4 +1,4 @@ -/* echld_child.h +/* echld.h * epan working child API * * $Id$ @@ -65,6 +65,9 @@ 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', @@ -77,12 +80,29 @@ 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; -/* will initialize epan registering protocols and taps */ -WS_DLL_PUBLIC void echld_initialize(echld_encoding_t, char* argv0, int (*main)(int, char **)); +typedef void (*cleanup_cb_t)(void*); +typedef int (*main_t)(int, char**); /* a pointer to main() */ + +/* 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; + cleanup_cb_t after_fork_cb; /* to be called after fork to free the + child processes from entities of the parent */ + void* after_fork_cb_data; -/* cleans up (?) echld and kills the server process(es) */ + cleanup_cb_t at_term_cb; /* to be called after echld_terminate() is done */ + void* at_term_cb_data; +} 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 * @@ -94,25 +114,6 @@ WS_DLL_PUBLIC echld_state_t echld_terminate(void); */ WS_DLL_PUBLIC echld_error_t echld_get_error(const char** errstr_ptr); -/* - * Children Management Operations - */ - -/* create a new worker process */ -WS_DLL_PUBLIC echld_chld_id_t echld_new(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); - -/* enc_msg_t is an obscure object for an encoded message */ -typedef struct _GByteArray enc_msg_t; - /* * prototype of message callbacks passed to echld_reqh() and echld_msgh() @@ -127,7 +128,6 @@ typedef struct _GByteArray enc_msg_t; typedef echld_bool_t (*echld_msg_cb_t)(echld_msg_type_t type, enc_msg_t* msg_buff, void* cb_data); - /* encoding and decoding */ @@ -152,8 +152,10 @@ typedef struct _parent_out { 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. @@ -161,6 +163,31 @@ WS_DLL_PUBLIC echld_parent_encoder_t* echld_get_encoder(void); */ 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*); + + +/* create a new worker process */ +WS_DLL_PUBLIC echld_chld_id_t echld_new(enc_msg_t* new_child_parameters, 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 * diff --git a/echld/parent.c b/echld/parent.c index 6c518907dd..2dad6a691d 100644 --- a/echld/parent.c +++ b/echld/parent.c @@ -183,13 +183,16 @@ void parent_reaper(int sig) { } /* will initialize epan registering protocols and taps */ -void echld_initialize(echld_encoding_t enc, char* argv0, int (*main)(int, char **)) { +void echld_initialize(echld_init_t* init) { int from_disp[2]; int to_disp[2]; - PARENT_DBG((1,"Echld Starting")); - if (enc != ECHLD_ENCODING_JSON) { + if (!init) { + PARENT_FATAL((NO_INITIALIZER,"Missing Initializer")); + } + + if (init->encoding != ECHLD_ENCODING_JSON) { PARENT_FATAL((UNIMPLEMENTED,"Only JSON implemented")); } @@ -213,7 +216,12 @@ void echld_initialize(echld_encoding_t enc, char* argv0, int (*main)(int, char * #endif /* child code */ echld_cleanup(); - echld_dispatcher_start(to_disp,from_disp,argv0,main); + + if (init->after_fork_cb) + init->after_fork_cb(init->after_fork_cb_data); + + echld_dispatcher_start(to_disp,from_disp,init->argv0,init->main); + PARENT_FATAL((SHOULD_HAVE_EXITED_BEFORE,"This shoudln't happen")); } else { /* parent code */ @@ -468,7 +476,7 @@ static int msgh_attach(echld_t* c, echld_msg_type_t t, echld_msg_cb_t resp_cb, v static int next_chld_id = 1; -extern int echld_new(void* child_data) { +extern int echld_new(enc_msg_t* new_child_em, void* child_data) { echld_t* c = get_child(-1); if (!c) return -1; @@ -477,12 +485,10 @@ extern int echld_new(void* child_data) { c->data = child_data; c->state = CREATING; - g_byte_array_set_size(parent.snd,0); - PARENT_DBG((1,"Child[%d]: =>CREATING",c->chld_id)); msgh_attach(c,ECHLD_CHILD_DEAD, parent_dead_child , c); - reqh_snd(c, ECHLD_NEW_CHILD, parent.snd, parent_get_hello, c); + reqh_snd(c, ECHLD_NEW_CHILD, (GByteArray*)new_child_em, parent_get_hello, c); return c->chld_id; } @@ -806,3 +812,40 @@ extern echld_state_t echld_wait(struct timeval* timeout) { return ECHLD_OK; } } + +enc_msg_t* echld_new_child_params(void) { + return (enc_msg_t*)g_byte_array_new(); +} + +enc_msg_t* echld_new_child_params_merge(enc_msg_t* em1, enc_msg_t* em2) { + GByteArray* ba = g_byte_array_new(); + GByteArray* b1 = (GByteArray*)em1; + GByteArray* b2 = (GByteArray*)em2; + + g_byte_array_append(ba,b1->data,b1->len); + g_byte_array_append(ba,b2->data,b2->len); + + return (enc_msg_t*)ba; +} + +WS_DLL_PUBLIC void echld_new_child_params_add_params(enc_msg_t* em, ...) { + GByteArray* ba = (GByteArray*) em; + va_list ap; + + va_start(ap,em); + do { + char* param_str = va_arg(ap, char*); + + if (param_str) { + char* val_str = va_arg(ap, char*); + + g_byte_array_append(ba, (guint8*) param_str, (guint)strlen(param_str)+1); + g_byte_array_append(ba, (guint8*) val_str, (guint)strlen(val_str)+1); + continue; + } + + break; + } while(1); + va_end(ap); + +} -- cgit v1.2.3