summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Ontanon <luis.ontanon@gmail.com>2013-07-01 01:49:34 +0000
committerLuis Ontanon <luis.ontanon@gmail.com>2013-07-01 01:49:34 +0000
commitbaee2e21f7020c77f41001bd759f8d41063eba3f (patch)
treed192ec49151c48a6862b1694b0aefba14fb8b158
parente03edbf713c9af37b452e1c3f1917f1e2c69ca72 (diff)
downloadwireshark-baee2e21f7020c77f41001bd759f8d41063eba3f.tar.gz
ANother iteration,
- started harvesting pieces from tshark. - fixed? signal handlers - interactive test program very hard to debug... set follow-on-fork doesn't seem to work on my mac. Need linux I guess... svn path=/trunk/; revision=50273
-rw-r--r--echld/Makefile.common1
-rw-r--r--echld/child.c111
-rw-r--r--echld/common.c1
-rw-r--r--echld/dispatcher.c91
-rw-r--r--echld/echld-int.h29
-rw-r--r--echld/echld-util.c55
-rw-r--r--echld/echld-util.h4
-rw-r--r--echld_test.c264
8 files changed, 420 insertions, 136 deletions
diff --git a/echld/Makefile.common b/echld/Makefile.common
index f80eef7c6b..cd19253c90 100644
--- a/echld/Makefile.common
+++ b/echld/Makefile.common
@@ -44,6 +44,7 @@ LIBECHLD_INCLUDES = \
LIBECHLD_MORE_SRC = \
../capture_opts.c \
../capture_stop_conditions.c \
+ ../capture-pcap-util-unix.c \
../cfutils.c \
../clopts_common.c \
../sync_pipe_write.c \
diff --git a/echld/child.c b/echld/child.c
index 19a04f40e4..db0f6e395d 100644
--- a/echld/child.c
+++ b/echld/child.c
@@ -51,6 +51,8 @@ typedef struct _child {
child_decoder_t* dec;
// epan stuff
+ //capture_file cfile;
+
} echld_child_t;
@@ -129,6 +131,13 @@ static long dbg_resp(GByteArray* em, echld_msg_type_t t) {
static struct timeval close_sleep_time;
+
+static void sig_term(int sig _U_) {
+ CHILD_DBG((3,"Terminated, Closing"));
+ exit(0);
+}
+
+
void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int pipe_to_parent, int reqh_id) {
close_sleep_time.tv_sec = CHILD_CLOSE_SLEEP_TIME / 1000000;
@@ -153,6 +162,14 @@ void echld_child_initialize(echld_chld_id_t chld_id, int pipe_from_parent, int p
CHILD_DBG_INIT();
CHILD_DBG((5,"Child Initialized ch=%d from=%d to=%d rq=%d",chld_id, pipe_from_parent, pipe_to_parent, reqh_id));
+ /*clear signal handlers */
+ signal(SIGALRM,SIG_DFL);
+ signal(SIGTERM,sig_term);
+ signal(SIGPIPE,SIG_DFL);
+ signal(SIGINT,SIG_DFL);
+ signal(SIGABRT,SIG_DFL);
+ signal(SIGHUP,SIG_DFL);
+
/* epan stuff */
}
@@ -195,32 +212,96 @@ static echld_bool_t param_set_cwd(char* val , char** err ) {
return TRUE;
}
-#define COOKIE_SIZE 1024
-static char* cookie = NULL;
-static char* param_get_cookie(char** err ) {
- if (cookie)
- return g_strdup(cookie);
+static unsigned packet_count = 0;
+static char* param_get_packet_count(char** err) {
- *err = g_strdup("cookie not set");
- return NULL;
+ if (child.state != CAPTURING || child.state != READING) {
+ *err = g_strdup("Must be reading or in-capture for packet_count");
+ return NULL;
+ }
+ return g_strdup_printf("%d",packet_count);
}
-static echld_bool_t param_set_cookie(char* val , char** err _U_) {
- if (cookie) g_free(cookie);
+static char* dfilter = NULL;
+dfilter_t *df = NULL;
- cookie = g_strdup(val);
- return TRUE;
+static echld_bool_t param_set_dfilter(char* val , char** err _U_) {
+ dfilter_t *dfn = NULL;
+ if ( dfilter_compile(val, &dfn) ) {
+ if (dfilter) g_free(dfilter);
+ if (df) dfilter_free(df);
+ df = dfn;
+ dfilter = g_strdup(val);
+ return TRUE;
+ } else {
+ *err = g_strdup(dfilter_error_msg);
+ return FALSE;
+ }
+}
+
+static char* param_get_dfilter(char** err _U_) { return g_strdup(dfilter ? dfilter : ""); }
+
+char* param_profile = NULL;
+
+static echld_bool_t param_set_profile(char* val , char** err ) {
+
+ if (child.state != IDLE) {
+ *err = g_strdup_printf("Cannot set Profile \"%s\", too late.", val);
+ return FALSE;
+ }
+
+ if (profile_exists (val, FALSE)) {
+ set_profile_name (val);
+ if (param_profile) g_free(param_profile);
+ param_profile = g_strdup(val);
+ return TRUE;
+ } else {
+ *err = g_strdup_printf("Configuration Profile \"%s\" does not exist", val);
+ return FALSE;
+ }
+}
+
+static char* param_get_profile(char** err _U_) { return g_strdup(param_profile ? param_profile : ""); }
+
+static char* param_get_file_list(char** err) {
+ GError* gerror = NULL;
+ GDir* dir = g_dir_open(".", 0, &gerror);
+ GString* str = g_string_new("{ what='file_list', files=[");
+ char* s;
+ const char* file;
+
+ if (gerror) {
+ *err = g_strdup_printf("Failed to open curr dir reason='%s'",gerror->message);
+ return NULL;
+ }
+
+ while(( file = g_dir_read_name(dir) )) {
+ g_string_append_printf(str,"{filename='%s'},\n",file);
+ }
+ g_dir_close(dir);
+
+ g_string_truncate(str, str->len-2); /* ',\n' */
+ g_string_append(str, "]}");
+
+ s=str->str;
+ g_string_free(str,FALSE);
+ return s;
}
+PARAM_BOOL(quiet,FALSE);
static param_t params[] = {
#ifdef DEBUG_CHILD
- {"dbg_level", param_get_dbg_level, param_set_dbg_level},
+ PARAM(dbg_level),
# endif
- {"cookie",param_get_cookie,param_set_cookie},
- {"cwd",param_get_cwd,param_set_cwd},
+ PARAM(profile),
+ PARAM(cwd),
+ PARAM(dfilter),
+ RO_PARAM(packet_count),
+ RO_PARAM(file_list),
+ PARAM(quiet),
{NULL,NULL,NULL}
};
@@ -510,7 +591,7 @@ static long child_receive(guint8* b, size_t len, echld_chld_id_t chld_id, echld_
misencoded:
// dump the misencoded message (b,blen)
- child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"misencoded msg msg_type='%s'",TY(type);
+ child_err(ECHLD_ERR_WRONG_MSG,reqh_id,"misencoded msg msg_type='%s'",TY(type));
return 0;
wrong_state:
diff --git a/echld/common.c b/echld/common.c
index 7eee1817a3..5670175cb1 100644
--- a/echld/common.c
+++ b/echld/common.c
@@ -73,6 +73,7 @@ static struct _st_map st_map[] = {
{ READING, "READING"},
{ CAPTURING, "CAPTURING"},
{ DONE, "DONE"},
+ { CLOSING, "CLOSING"},
{ CLOSED, "CLOSED"},
{ ERRORED, "ERRORED"},
{0,NULL}
diff --git a/echld/dispatcher.c b/echld/dispatcher.c
index e300c06c1d..910f54255c 100644
--- a/echld/dispatcher.c
+++ b/echld/dispatcher.c
@@ -36,6 +36,7 @@ struct dispatcher_child {
echld_reader_t reader;
int write_fd;
int pid;
+ int reqh_id;
gboolean closing;
};
@@ -290,10 +291,10 @@ static char* param_get_interfaces(char** err) {
return s;
}
-static struct timeval disp_loop_timeout;
+static long disp_loop_timeout_usec = DISPATCHER_WAIT_INITIAL;
static char* param_get_loop_to(char** err _U_) {
- return g_strdup_printf("%d.%06ds",(int)disp_loop_timeout.tv_sec, (int)disp_loop_timeout.tv_usec );
+ return g_strdup_printf("%fs", (((float)disp_loop_timeout_usec)/1000000.0) );
}
static echld_bool_t param_set_loop_to(char* val , char** err ) {
@@ -305,17 +306,39 @@ static echld_bool_t param_set_loop_to(char* val , char** err ) {
return FALSE;
}
- disp_loop_timeout.tv_sec = usec / 1000000;
- disp_loop_timeout.tv_usec = usec % 1000000;
+ disp_loop_timeout_usec = usec;
return TRUE;
}
+GString *comp_info_str;
+GString *runtime_info_str;
+
+static char* param_get_version(char** err _U_) {
+ char* str;
+
+ 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);
+
+ g_string_free(runtime_info_str,TRUE);
+ g_string_free(comp_info_str,TRUE);
+
+ return str;
+}
+
static param_t disp_params[] = {
#ifdef DEBUG_DISPATCHER
{"dbg_level", param_get_dbg_level, param_set_dbg_level},
# endif
+ {"version",param_get_version,NULL},
{"loop_timeout",param_get_loop_to,param_set_loop_to},
{"interfaces",param_get_interfaces,NULL},
{NULL,NULL,NULL} };
@@ -351,6 +374,7 @@ static void dispatcher_clear_child(struct dispatcher_child* c) {
c->reader.fd = -1;
c->write_fd = -1;
c->pid = -1;
+ c->reqh_id = -1;
c->closing = FALSE;
}
@@ -361,13 +385,34 @@ static void set_dumpcap_pid(int pid) {
static void preinit_epan(char* argv0, int (*main)(int, char **)) {
char* init_progfile_dir_error = init_progfile_dir(argv0, main);
+ comp_info_str = g_string_new("Compiled ");
+ get_compiled_version_info(comp_info_str, NULL, epan_get_compiled_version_info);
+
+ runtime_info_str = g_string_new("Running ");
+ get_runtime_version_info(runtime_info_str, NULL);
+
if (init_progfile_dir_error) {
DISP_FATAL((CANNOT_PREINIT_EPAN,"Failed epan_preinit: msg='%s'",init_progfile_dir_error));
}
+ /* 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);
+
capture_sync_set_fetch_dumpcap_pid_cb(set_dumpcap_pid);
+#ifdef _WIN32
+ arg_list_utf_16to8(argc, argv);
+ create_app_running_mutex();
+#if !GLIB_CHECK_VERSION(2,31,0)
+ g_thread_init(NULL);
+#endif
+#endif /* _WIN32 */
+
+
+ init_process_policies();
+
/* Here we do initialization of parts of epan that will be the same for every child we fork */
DISP_DBG((2,"epan preinit"));
@@ -392,7 +437,6 @@ void dispatcher_reaper(int sig) {
struct dispatcher_child* cc = dispatcher->children;
int max_children = dispatcher->max_children;
int pid = waitpid(-1, &status, WNOHANG);
- GByteArray* em;
int reqh_id_save = dispatcher->reqh_id;
dispatcher->reqh_id = 0;
@@ -409,9 +453,10 @@ void dispatcher_reaper(int sig) {
struct dispatcher_child* c = &(cc[i]);
if ( c->pid == pid ) {
if (c->closing || dispatcher->closing) {
- em = dispatcher->enc.to_parent->child_dead("OK");
+ DISP_WRITE(dispatcher->parent_out, NULL, c->chld_id, ECHLD_CLOSING, c->reqh_id);
} else {
char* s = NULL;
+ GByteArray* em;
if (WIFEXITED(status)) {
s = g_strdup_printf(
@@ -433,12 +478,12 @@ void dispatcher_reaper(int sig) {
em = dispatcher->enc.to_parent->child_dead(s);
dispatcher_err(ECHLD_ERR_CRASHED_CHILD, s);
if (s) g_free(s);
+ DISP_WRITE(dispatcher->parent_out, em, c->chld_id, ECHLD_CHILD_DEAD, 0);
+ if (em) g_byte_array_free(em,TRUE);
}
CHLD_SET_STATE(c,CLOSED);
- DISP_WRITE(dispatcher->parent_out, em, c->chld_id, ECHLD_CHILD_DEAD, 0);
dispatcher_clear_child(c);
- g_byte_array_free(em,TRUE);
dispatcher->reqh_id = reqh_id_save;
return;
}
@@ -474,8 +519,9 @@ static long dispatch_to_parent(guint8* b, size_t len, echld_chld_id_t chld_id, e
GByteArray in_ba;
struct dispatcher_child* c = (struct dispatcher_child*)data;
- dispatcher->reqh_id = reqh_id;
+ dispatcher->reqh_id = c->reqh_id = reqh_id;
+
in_ba.data = b;
in_ba.len = (guint)len;
@@ -487,7 +533,10 @@ static long dispatch_to_parent(guint8* b, size_t len, echld_chld_id_t chld_id, e
case ECHLD_ERROR: break;
case ECHLD_TIMED_OUT: break;
case ECHLD_HELLO: CHLD_SET_STATE(c,IDLE); break;
- case ECHLD_CLOSING: CHLD_SET_STATE(c,CLOSED); break;
+ case ECHLD_CLOSING:
+ c->closing = TRUE;
+ CHLD_SET_STATE(c,CLOSING);
+ break;
case ECHLD_PARAM: break;
case ECHLD_PONG: break;
case ECHLD_FILE_OPENED: CHLD_SET_STATE(c,READING); break;
@@ -771,12 +820,10 @@ static long dispatch_to_child(guint8* b, size_t len, echld_chld_id_t chld_id, ec
-
int dispatcher_loop(void) {
int parent_out = dispatcher->parent_out;
int parent_in = dispatcher->parent_in.fd;
struct dispatcher_child* children = dispatcher->children;
- volatile int pforce = 0;
DISP_DBG((5,"LOOP in_fd=%d out_fd=%d",parent_in, parent_out));
@@ -786,7 +833,7 @@ int dispatcher_loop(void) {
struct dispatcher_child* c;
int nfds;
int nchld = 0;
-
+ struct timeval disp_loop_timeout;
FD_ZERO(&rfds);
FD_ZERO(&efds);
@@ -803,16 +850,21 @@ int dispatcher_loop(void) {
}
}
- DISP_DBG((5,"Select()ing nchld=%d usecs=%d",nchld,disp_loop_timeout.tv_usec));
+ DISP_DBG((4,"Select()ing nchld=%d",nchld,disp_loop_timeout.tv_usec));
+
+ disp_loop_timeout.tv_sec = (int)(disp_loop_timeout_usec / 1000000);
+ disp_loop_timeout.tv_usec = (int)(disp_loop_timeout_usec % 1000000);
nfds = select(FD_SETSIZE, &rfds, NULL, &efds, &disp_loop_timeout);
+ DISP_DBG((5,"Select()ed nfds=%d",nchld,nfds));
+
if (nfds < 0) {
DISP_DBG((1,"select error='%s'",strerror(errno) ));
continue;
}
- if ( pforce || FD_ISSET(parent_in, &rfds)) {
+ if ( FD_ISSET(parent_in, &rfds)) {
long st = echld_read_frame(&(dispatcher->parent_in), dispatch_to_child, dispatcher);
if (st < 0) {
@@ -865,6 +917,9 @@ int dispatcher_loop(void) {
return 1;
}
+void dispatcher_alrm(int sig _U_) {
+ DISP_DBG((1,"ALRM received"));
+}
void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, int (*main)(int, char **)) {
static struct dispatcher d;
@@ -873,9 +928,6 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, in
int dbg_fd;
#endif
- disp_loop_timeout.tv_sec = 0;
- disp_loop_timeout.tv_usec = DISPATCHER_WAIT_INITIAL;
-
DISP_DBG_INIT();
#ifdef DEBUG_DISPATCHER
dbg_fd = fileno(debug_fp);
@@ -889,6 +941,9 @@ void echld_dispatcher_start(int* in_pipe_fds, int* out_pipe_fds, char* argv0, in
signal(SIGPIPE,dispatcher_sig);
signal(SIGINT,SIG_IGN);
signal(SIGCONT,SIG_IGN);
+ signal(SIGABRT,dispatcher_sig);
+ signal(SIGHUP,dispatcher_sig);
+ signal(SIGALRM,dispatcher_alrm);
dispatcher = &d;
diff --git a/echld/echld-int.h b/echld/echld-int.h
index 1c5e563915..0bb9dd34fe 100644
--- a/echld/echld-int.h
+++ b/echld/echld-int.h
@@ -61,9 +61,11 @@
#include "capture_session.h"
#include "capture_ifinfo.h"
#include "capture_sync.h"
-
-#include "../epan/filesystem.h"
-
+#include "version_info.h"
+#include "wsutil/crash_info.h"
+#include "wsutil/privileges.h"
+#include "epan/filesystem.h"
+#include "epan/epan.h"
#include "echld.h"
#ifdef __cplusplus
@@ -71,8 +73,6 @@ extern "C" {
#endif
/* XXX these shouldn't be needed */
-typedef struct _column_info column_info;
-typedef struct _proto_node proto_tree;
typedef struct tvbuff tvb_t;
struct _hdr {
@@ -104,6 +104,7 @@ typedef enum _cst {
READING,
CAPTURING,
DONE,
+ CLOSING,
CLOSED=-1,
ERRORED=-2
} child_state_t;
@@ -145,6 +146,22 @@ typedef struct _param {
echld_bool_t (*set)(char* val , char** err);
} param_t;
+#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; } \
+
+#define PARAM_INT(Name, Default) static int param_ ## Name = Default; \
+ static char* param_get_ ## Name (char** err _U_ ) { return g_strdup_printf("%d",param_ ## Name); } \
+ static echld_bool_t param_set_ ## Name (char* val , char** err _U_) { char* p; int temp = (int)strtol(val, &p, 10); if (p<=val) { *err = g_strdup("not an integer"); return FALSE; } else { param_ ## Name = temp; return TRUE; } }
+
+#define PARAM_BOOL(Name, Default) static gboolean param_ ## Name = Default; \
+ static char* param_get_ ## Name (char** err _U_ ) { return g_strdup_printf("%s",param_ ## Name ? "TRUE" : "FALSE"); } \
+ static echld_bool_t param_set_ ## Name (char* val , char** err _U_) { param_ ## Name = (*val == 'T' || *val == 't') ? TRUE : FALSE; return TRUE;}
+
+#define PARAM(Name) {#Name, param_get_ ## Name, param_set_ ## Name}
+#define RO_PARAM(Name) {#Name, param_get_ ## Name, NULL}
+#define WO_PARAM(Name) {#Name, NULL, param_set_ ## Name}
+
/* 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 +233,7 @@ extern void echld_unused(void);
#define DEBUG_PARENT 5
/* timers */
-#define DISPATCHER_WAIT_INITIAL 999999 /* almost 1s */
+#define DISPATCHER_WAIT_INITIAL 5000000 /* 5s */
#define CHILD_CLOSE_SLEEP_TIME 2000000 /* 2s */
#define CHILD_START_WAIT_TIME 100000 /* 0.1s */
#define DISP_KILLED_CHILD_WAIT 100000 /* 0.1s */
diff --git a/echld/echld-util.c b/echld/echld-util.c
index a6552ac7aa..d86adc3758 100644
--- a/echld/echld-util.c
+++ b/echld/echld-util.c
@@ -29,6 +29,8 @@
#include "echld-int.h"
#include "echld-util.h"
+#include <glib.h>
+
struct _ping {
struct timeval tv;
echld_ping_cb_t cb;
@@ -109,7 +111,7 @@ static gboolean got_param(echld_msg_type_t type, GByteArray* ba _U_, void* data)
break;
}
default:
- err_msg = g_strdup_printf("other type='%c'",type);
+ err_msg = g_strdup_printf("other type='%s'",TY(type));
g->cb(NULL,NULL,err_msg,g->cb_data);
g_free(err_msg);
break;
@@ -157,3 +159,54 @@ extern echld_state_t echld_set_param(int chld_id, const char* param, const char*
return echld_reqh(chld_id, ECHLD_SET_PARAM, 0, em, got_param, g);
}
+typedef struct _close {
+ echld_close_cb_t cb;
+ void* cb_data;
+} close_t;
+
+static gboolean closed(echld_msg_type_t type, GByteArray* ba, void* data) {
+ close_t* c = (close_t*)data;
+ parent_decoder_t* dec;
+ char* err_msg;
+
+ echld_get_all_codecs(NULL, NULL, NULL, &dec);
+
+ switch (type) {
+ case ECHLD_CLOSING: {
+ if (c->cb) {
+ c->cb(NULL,c->cb_data);
+ }
+ break;
+ }
+ case ECHLD_ERROR: {
+ int errnum;
+
+ if ( dec->error(ba, &errnum ,&err_msg) ) {
+ c->cb(err_msg,c->cb_data);
+ g_free(err_msg);
+ } else {
+ c->cb("Canot decode error message",c->cb_data);
+ }
+ break;
+ }
+ default:
+ err_msg = g_strdup_printf("other type='%s'",TY(type));
+ c->cb(err_msg,c->cb_data);
+ g_free(err_msg);
+ break;
+ }
+
+ g_free(c);
+ return TRUE;
+
+}
+
+echld_state_t echld_close(int child_id, echld_close_cb_t pcb, void* cb_data) {
+ close_t* c = g_new0(close_t,1);
+ c->cb = pcb;
+ c->cb_data = cb_data;
+
+ return echld_reqh(child_id,ECHLD_CLOSE_CHILD, 0, NULL, closed, c);
+}
+
+
diff --git a/echld/echld-util.h b/echld/echld-util.h
index a1a625d570..2d7e9de4d8 100644
--- a/echld/echld-util.h
+++ b/echld/echld-util.h
@@ -30,6 +30,10 @@
extern "C" {
#endif
+typedef void (*echld_close_cb_t)(const char* error, void* data);
+WS_DLL_PUBLIC echld_state_t echld_close(int child_id, echld_close_cb_t pcb, void* cb_data);
+
+
typedef void (*echld_ping_cb_t)(long usec, void* data);
WS_DLL_PUBLIC echld_state_t echld_ping(int child_id, echld_ping_cb_t pcb, void* cb_data);
diff --git a/echld_test.c b/echld_test.c
index dd0a6407c3..3829518789 100644
--- a/echld_test.c
+++ b/echld_test.c
@@ -44,6 +44,7 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <glib.h>
#include <glib/gprintf.h>
@@ -54,143 +55,214 @@
#include "epan/epan.h"
#include "wsutil/str_util.h"
-int pings = 0;
-int errors = 0;
+typedef char* (*cmd_cb_t)(char** params, char** err);
-void ping_cb(long usec, void* data _U_) {
+typedef struct _cmd_t {
+ const char* txt;
+ cmd_cb_t cb;
+ int args_taken;
+ const char* help;
+} cmd_t;
- fprintf(stderr, "Ping ping=%d usec=%d\n", pings ,(int)usec );
+static char* new_child_cmd(char** params _U_, char** err) {
+ int child = echld_new(NULL);
- if (usec >= 0) {
- pings++;
- } else {
- errors++;
+ if (child <= 0) {
+ *err = g_strdup("No child\n");
+ return NULL;
}
+
+ return g_strdup_printf("New chld_id=%d\n",child);;
}
-int got_param = 0;
-void param_cb(const char* param, const char* value, const char* error, void* data _U_) {
- if (error) {
- fprintf(stderr, "Param Set Error msg=%s\n", error );
- got_param = 0;
- return;
+void ping_cb(long usec, void* data) {
+ int ping_id = *((int*)data);
+
+ if (usec >= 0) {
+ fprintf(stdout, "Ping ping_id=%d returned in %dus\n",ping_id,(int)usec);
+ } else {
+ fprintf(stdout, "Ping ping_id=%d erored\n",ping_id);
}
- got_param = 1;
- fprintf(stderr, "Param: param='%s' val='%s'\n", param, value );
+ g_free(data);
}
-int main(int argc _U_, char** argv _U_) {
- struct timeval tv;
- int tot_cycles = 0;
- int max_cycles = 50;
- int child = -1;
- int keep_going = 1;
+static char* ping_cmd(char** params, char** err) {
+ int child = (int) strtol(params[1], NULL, 10);
+ static int ping_id = 0;
+ int* ping_data = g_new(int,1);
- tv.tv_sec = 0;
- tv.tv_usec = 250000;
+ *ping_data = ping_id++;
- echld_set_parent_dbg_level(5);
+ if (!echld_ping(child,ping_cb,ping_data)) {
+ *err = g_strdup_printf("Could not send ping child=%d",child);
+ return NULL;
+ } else {
+ return g_strdup_printf("Ping sent child=%d",child);
+ }
+}
- echld_initialize(ECHLD_ENCODING_JSON,argv[0],main);
+void param_cb(const char* param, const char* value, const char* error, void* data _U_) {
+ if (error) {
+ fprintf(stdout, "Param Set Error msg=%s\n", error );
+ } else {
+ fprintf(stdout, "Param: param='%s' val='%s'\n", param, value );
+ }
+}
- do {
- if ( tot_cycles == 2 ) echld_ping(0,ping_cb,NULL);
+static char* set_cmd(char** params, char** err) {
+ int child = (int) strtol(params[1], NULL, 10);
+ char* param = params[2];
+ char* value = params[3];
- if ( tot_cycles == 4 ) {
- if (pings!=1) {
- fprintf(stderr, "No Dispatcher PONG 0\n");
- break;
- }
- echld_ping(0,ping_cb,NULL);
- }
+ if ( ! echld_set_param(child,param,value,param_cb,NULL) ) {
+ *err = g_strdup_printf("Failed to SET child=%d param='%s' value='%s'",child,param,value);
+ return NULL;
+ } else {
+ return g_strdup_printf("Set command sent child=%d param='%s' value='%s'",child,param,value);
+ }
+}
- if ( tot_cycles == 6 ) {
- if (pings!=2) {
- fprintf(stderr, "No Dispatcher PONG 1\n");
- break;
- }
+static char* get_cmd(char** params, char** err) {
+ int child = (int) strtol(params[1], NULL, 10);
+ char* param = params[2];
- echld_set_param(0,"dbg_level","5",param_cb,NULL);
- }
+ if ( ! echld_get_param(child,param,param_cb,NULL) ) {
+ *err = g_strdup_printf("Failed to GET child=%d param='%s'",child,param);
+ return NULL;
+ } else {
+ return g_strdup_printf("Get command sent child=%d param='%s'",child,param);
+ }
+}
- if ( tot_cycles == 8) {
- if (! got_param ) {
- fprintf(stderr, "Set Dispatcher Param Failed\n");
- break;
- }
+static void close_cb(const char* error, void* data) {
+ if (error) {
+ fprintf(stdout, "Close Error msg=%s\n", error );
+ } else {
+ fprintf(stdout, "Closed: child=%d\n", *((int*)data) );
+ }
+}
- echld_get_param(0,"interfaces",param_cb,NULL);
- }
+static char* close_cmd(char** params, char** err) {
+ int child = (int) strtol(params[1], NULL, 10);
+ int* cmdp = g_new(int,1);
+ *cmdp = child;
+ if ( ! echld_close(child,close_cb,cmdp) ) {
+ *err = g_strdup_printf("Could not close child=%d",child);
+ return NULL;
+ } else {
+ return g_strdup_printf("CLose command sent child=%d",child);
+ }
+}
+int keep_going = 1;
- if ( tot_cycles == 10) {
- if (! got_param ) {
- fprintf(stderr, "Set Dispatcher Param Failed\n");
- break;
- }
+static char* quit_cmd(char** params _U_, char** err _U_) {
+ keep_going = 0;
+ return g_strdup("Quitting");
+}
- child = echld_new(NULL);
-
- fprintf(stderr, "New chld_id=%d\n",child);
+static char* help_cmd(char**, char**);
- if (child <= 0) {
- fprintf(stderr, "No child\n");
- break;
- }
- }
+static char* nothing_at_last_cmd(char** pars _U_, char** err _U_) {
+ return g_strdup("");
+}
- if ( tot_cycles == 16 ) echld_ping(child,ping_cb,NULL);
+cmd_t commands[] = {
+ { "QUIT", quit_cmd, 0, "QUIT"},
+ { "HELP", help_cmd, 0, "HELP"},
+ { "NEW", new_child_cmd, 0, "NEW"},
+ { "PING", ping_cmd, 1, "PING child_id"},
+ { "SET", set_cmd, 3, "SET child_id param_name param_val"},
+ { "GET", get_cmd, 2, "GET child_id param_name"},
+ { "CLOSE", close_cmd, 1, "CLOSE child_id"},
+ { "", nothing_at_last_cmd,0,""},
+ { NULL, NULL, 0, NULL }
+};
+
+static char* help_cmd(char** params _U_, char** err _U_) {
+ GString* out = g_string_new("Commands:\n");
+ cmd_t* c = commands;
+ char* s;
+
+ for (;c->txt;c++) {
+ g_string_append_printf(out,"%s\n",c->help);
+ }
+ s = out->str;
+ g_string_free(out,FALSE);
+ return s;
+}
- if ( tot_cycles == 18 ) {
- if (pings!=3) {
- fprintf(stderr, "No Child PONG 0\n");
- break;
- }
- echld_ping(child,ping_cb,NULL);
- }
- if ( tot_cycles == 20 ) {
- if (pings!=4) {
- fprintf(stderr, "No Child PONG 1\n");
- break;
- }
- echld_set_param(child,"cookie","hello-hello",param_cb,NULL);
- }
+int got_param = 0;
- if ( tot_cycles == 22 ) {
- if (!got_param) {
- fprintf(stderr, "Set Child Param Failed\n");
- break;
- }
+int main(int argc _U_, char** argv _U_) {
+ struct timeval tv;
+ int tot_cycles = 0;
- echld_get_param(child,"dbg_level",param_cb,NULL);
- }
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
- if ( tot_cycles == 24 ) {
- if (!got_param) {
- fprintf(stderr, "Get Child Param Failed\n");
- break;
- }
+ echld_set_parent_dbg_level(5);
+
+ echld_initialize(ECHLD_ENCODING_JSON,argv[0],main);
- keep_going = 0;
+ do {
+ fd_set rfds;
+ fd_set efds;
+ int nfds;
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&efds);
+ FD_SET(0,&rfds);
+ FD_SET(0,&efds);
+
+ nfds = echld_select(FD_SETSIZE, &rfds, NULL, &efds, &tv);
+
+ if (FD_ISSET(0,&rfds)) {
+ size_t len;
+ char* cmd_line;
+
+ if(( cmd_line = fgetln(stdin,&len) )) {
+ cmd_t* c = commands;
+ cmd_line[len] = 0;
+ g_strchomp(cmd_line);
+
+ for (;c->txt;c++) {
+ if ( strcasestr(cmd_line, c->txt) == cmd_line ) {
+ char** params = g_strsplit(cmd_line, " ", c->args_taken+1);
+ char* err = NULL;
+ char* str = c->cb(params,&err);
+
+ if (err) {
+ fprintf(stdout, "Error: %s\n", err);
+ g_free(err);
+ } else {
+ fprintf(stdout, "%s\n", str);
+ g_free(str);
+ }
+
+ g_strfreev(params);
+ goto cmd_executed;
+ }
+ }
+
+ fprintf(stdout, "Error: no such command %s\n", cmd_line);
+ }
}
+ cmd_executed:
tot_cycles++;
- echld_wait(&tv);
- } while( keep_going && (tot_cycles < max_cycles));
+ } while( keep_going );
- fprintf(stderr, "Done: pings=%d errors=%d tot_cycles=%d\n", pings, errors ,tot_cycles );
+ fprintf(stderr, "Done: tot_cycles=%d\n", tot_cycles );
echld_terminate();
return 0;
}
-
-
-void main_window_update(void) {}