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" */
+ int usec = (int)strtol(val, &p, 10); /* now usecs 2DO: "10ms" or "500us" or "1s" */
if (p<=val) {
*err = g_strdup("not an integer");
}
static void set_dumpcap_pid(int pid) {
+
dispatcher->dumpcap_pid = pid;
}
static void preinit_epan(char* argv0, int (*main)(int, char **)) {
- char *gpf_path, *pf_path;
+ // 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 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;
/* disabled protocols as per configuration file */
set_disabled_protos_list();
- initialize_funnel_ops();
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
+ DISP_DBG((1,"---5"));
read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno, &dp_path, &dp_open_errno, &dp_read_errno);
- // check 4 errors
+
+ DISP_DBG((1,"---6"));
cap_file_init(&stuff.cfile);
+ DISP_DBG((1,"---7"));
+ DISP_DBG((1,"---8"));
timestamp_set_precision(TS_PREC_AUTO_USEC);
+ // sleep(10);
+
+ // initialize_funnel_ops();
+ // stuff.prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path, &pf_open_errno, &pf_read_errno, &pf_path);
+ // check 4 errors
+
+
DISP_DBG((2,"epan preinit done"));
}
preinit_epan(argv0,main);
+ DISP_WRITE(dispatcher->parent_out, NULL, 0, ECHLD_HELLO, 0);
exit(dispatcher_loop());
}
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;
- cleanup_cb_t after_fork_cb; /* to be called after fork to free the
- child processes from entities of the parent */
+
+ 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 enc_msg_t* echld_new_child_params(void);
-/* takes the em, and param=value pairs of strings, NULL to end.
+
+
+/* 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);
+
/* create a new worker process */
-WS_DLL_PUBLIC echld_chld_id_t echld_new(enc_msg_t* new_child_parameters, void* child_data);
+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);
-/* echld_dispatcher.c
+/* parent.c
* epan working child API internals
- * Parent process routines and definitions ()
+ * Parent process routines and definitions
*
* $Id$
*
typedef struct _echld_child {
int chld_id;
void* data;
+ echld_new_cb_t cb;
child_state_t state;
GArray* handlers;
GArray* reqs;
int pid;
int status;
- if (sig != SIGCHLD) {
+ if (sig == SIGCHLD) {
PARENT_FATAL((3333,"Must be SIGCHLD!"));
}
if (! parent.closing) {
/* crashed */
+ sleep(120);
PARENT_FATAL((DISPATCHER_DEAD,"Dispatcher process dead"));
}
return;
}
+static echld_bool_t hello_cb(echld_msg_type_t type, enc_msg_t* msg_buff, void* ud) {
+ echld_init_t* init = (echld_init_t*)ud;
+ char* err = NULL;
+ int errnum = 0;
+
+ if (init && init->dispatcher_hello_cb) {
+ switch(type) {
+ case ECHLD_ERROR:
+ parent.dec->error(msg_buff, &errnum ,&err);
+ break;
+ case ECHLD_TIMEOUT:
+ err = g_strdup("timedout");
+ break;
+ default:
+ err = g_strdup_printf("Wrong MSG 'HELLO' expected, got '%s",TY(type));
+ break;
+ case ECHLD_HELLO:
+ break;
+ }
+
+ init->dispatcher_hello_cb(ud,err);
+ if (err) g_free(err);
+ }
+
+ return TRUE;
+}
+
+
+
/* will initialize epan registering protocols and taps */
void echld_initialize(echld_init_t* init) {
int from_disp[2];
signal(SIGCHLD,parent_reaper);
//close(to_disp[0]);
//close(from_disp[1]);
+ if (init->dispatcher_hello_cb) echld_msgh(0, ECHLD_HELLO, hello_cb, init);
+
PARENT_DBG((3,"Ready"));
}
}
return 0;
}
-static echld_bool_t parent_get_hello(echld_msg_type_t type, enc_msg_t* ba _U_, void* data) {
+static echld_bool_t parent_get_hello(echld_msg_type_t type, enc_msg_t* ba, void* data) {
echld_t* c = (echld_t*)data;
+ int err_id;
+ char* err = NULL;
switch (type) {
case ECHLD_HELLO:
PARENT_DBG((1,"Child[%d]: =>IDLE",c->chld_id));
c->state = IDLE;
- return TRUE;
+ break;
case ECHLD_ERROR:
- case ECHLD_TIMED_OUT:
+ parent.dec->error(ba,&err_id,&err);
+ break;
+ case ECHLD_TIMEOUT:
+ err = g_strdup("timedout");
+ break;
default:
- return FALSE;
+ err = g_strdup_printf("Wrong MSG 'HELLO' expected, got '%s",TY(type));
+ break;
}
+
+ if (c->cb)
+ c->cb(c->data,err);
+
+ if (err) g_free(err);
+
+ return TRUE;
}
static int next_chld_id = 1;
-extern int echld_new(enc_msg_t* new_child_em, void* child_data) {
+extern int echld_new(enc_msg_t* new_child_em, echld_new_cb_t cb, void* child_data) {
echld_t* c = get_child(-1);
if (!c) return -1;
c->chld_id = (next_chld_id++);
c->data = child_data;
c->state = CREATING;
+ c->cb = cb;
PARENT_DBG((1,"Child[%d]: =>CREATING",c->chld_id));
static hdlr_t* get_next_hdlr_for_type(echld_t* c, echld_msg_type_t t, int* cookie) {
int imax = c->handlers->len;
+ hdlr_t* r = NULL;
- for (;*cookie<imax;(*cookie)++) {
- if (((hdlr_t*)(c->handlers->data))[*cookie].type == t)
- return &( ((hdlr_t*)(c->handlers->data))[*cookie] ) ;
+ for (;(*cookie)<imax;(*cookie)++) {
+ if (((hdlr_t*)(c->handlers->data))[*cookie].type == t) {
+ r = &( ((hdlr_t*)(c->handlers->data))[*cookie] );
+ (*cookie)++;
+ break;
+ }
}
- return NULL;
+ return r;
}
static long parent_read_frame(guint8* b, size_t len, echld_chld_id_t chld_id, echld_msg_type_t t, echld_reqh_id_t reqh_id, void* data _U_) {
if (c) {
reqh_t* r = get_req(c, reqh_id);
- int i = 0;
+ int i;
hdlr_t* h;
gboolean go_ahead = TRUE;
r->tv.tv_sec = 0;
r->tv.tv_usec = 0;
- PARENT_DBG((2,"hanlded by reqh_id=%d msg='%s'",reqh_id,go_ahead?"retrying":"done"));
+ PARENT_DBG((2,"handled by reqh_id=%d msg='%s'",reqh_id,go_ahead?"retrying":"done"));
}
+ i=0;
while(go_ahead && ( h = get_next_hdlr_for_type(c,t,&i))) {
if (h->cb)
go_ahead = h->cb(t,ba,h->cb_data);
- PARENT_DBG((2,"hanlded by t='%c' msgh_id=%d msg='%s'",h->type, h->id,go_ahead?"retrying":"done"));
+ PARENT_DBG((2,"handled by t='%s' msgh_id=%d msg='%s'",TY(h->type), h->id,go_ahead?"retrying":"done"));
}
} else {
PARENT_DBG((1,"parent_read_frame: No such child"));
}
if (FD_ISSET(parent.reader.fd,rfds)) {
- PARENT_DBG((1,"reading from dispatcher"));
+ PARENT_DBG((3,"reading from dispatcher"));
echld_read_frame(&(parent.reader),parent_read_frame,&(parent));
}
echld_fdset(rfds,efds);
- PARENT_DBG((2,"Select()"));
+ PARENT_DBG((5,"Select()"));
r_nfds = select(FD_SETSIZE, rfds, wfds, efds, timeout);
echld_fd_read(rfds,efds);
return (enc_msg_t*)ba;
}
-WS_DLL_PUBLIC void echld_new_child_params_add_params(enc_msg_t* em, ...) {
+char* echld_new_child_params_str(enc_msg_t* em, const char* prefix, const char* postfix, int trunc_n, const char* fmt) {
+ GByteArray* ba = (GByteArray*)em;
+ GString* str = g_string_new(prefix);
+ 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) {
+ g_string_free(str,TRUE);
+ return NULL;
+ }
+
+ value_len = strlen(value)+1;
+
+ rem -= value_len;
+ p = value + value_len;
+
+ if (rem < 0) {
+ g_string_free(str,TRUE);
+ return NULL;
+ }
+
+ g_string_append_printf(str,fmt,param,value);
+ }
+ g_string_truncate(str, str->len - trunc_n);
+ g_string_append(str,postfix);
+ p = str->str;
+ g_string_free(str,FALSE);
+ return p;
+}
+
+void echld_new_child_params_add_params(enc_msg_t* em, ...) {
GByteArray* ba = (GByteArray*) em;
va_list ap;
va_end(ap);
}
+
+