diff --git a/src/bin/efl/efl_debug.c b/src/bin/efl/efl_debug.c index f27504d3af..594aba6e1b 100644 --- a/src/bin/efl/efl_debug.c +++ b/src/bin/efl/efl_debug.c @@ -16,150 +16,360 @@ * if not, see . */ +#define EFL_BETA_API_SUPPORT 1 +#define EFL_EO_API_SUPPORT 1 #include "efl_debug_common.h" -static unsigned char *buf; -static unsigned int buf_size; +static Eo *dialer; +static Eo *input; +static Eo *output; +static Eo *send_copier; +static Eo *recv_copier; -static int my_argc; -static char **my_argv; -static const char *expect = NULL; +static Eina_List *waiting; -static Ecore_Con_Server *svr; +static int retval = EXIT_SUCCESS; + +static const char CLST[4] = "CLST"; static void -_do(char *op, unsigned char *d, int size) +_process_reply(const char op[static 4], const Eina_Slice payload) { - if (!strcmp(op, "CLST")) - { - int i, n; +#define IS_OP(x) memcmp(op, x, 4) == 0 - n = (size) / sizeof(int); - if (n < 10000) + if (IS_OP(CLST)) + { + int mypid = getpid(); + size_t offset; + + waiting = eina_list_remove(waiting, CLST); + + for (offset = 0; offset + sizeof(int) <= payload.len; offset += sizeof(int)) { - int *pids = malloc(n * sizeof(int)); - if (pids) - { - int mypid = getpid(); - memcpy(pids, d, n * sizeof(int)); - for (i = 0; i < n; i++) - { - if (pids[i] == mypid) continue; - if (pids[i] > 0) printf("%i\n", pids[i]); - } - free(pids); - } + int p; + + memcpy(&p, payload.bytes + offset, sizeof(int)); + + if (p == mypid) continue; + if (p > 0) printf("%i\n", p); } } - if ((expect) && (!strcmp(op, expect))) ecore_main_loop_quit(); -} - -Eina_Bool -_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev EINA_UNUSED) -{ - int i; - for (i = 1; i < my_argc; i++) + else { - if (!strcmp(my_argv[i], "list")) - { - send_svr(svr, "LIST", NULL, 0); - expect = "CLST"; - } - else if ((!strcmp(my_argv[i], "pon")) && - (i < (my_argc - 2))) - { - unsigned char tmp[8]; - int pid = atoi(my_argv[i + 1]); - unsigned int freq = atoi(my_argv[i + 2]); - i += 2; - store_val(tmp, 0, pid); - store_val(tmp, 4, freq); - send_svr(svr, "PLON", tmp, sizeof(tmp)); - ecore_main_loop_quit(); - } - else if ((!strcmp(my_argv[i], "poff")) && - (i < (my_argc - 1))) - { - unsigned char tmp[4]; - int pid = atoi(my_argv[i + 1]); - i++; - store_val(tmp, 0, pid); - send_svr(svr, "PLOF", tmp, sizeof(tmp)); - ecore_main_loop_quit(); - } - else if ((!strcmp(my_argv[i], "evlogon")) && - (i < (my_argc - 1))) - { - unsigned char tmp[4]; - int pid = atoi(my_argv[i + 1]); - i++; - store_val(tmp, 0, pid); - send_svr(svr, "EVON", tmp, sizeof(tmp)); - ecore_main_loop_quit(); - } - else if ((!strcmp(my_argv[i], "evlogoff")) && - (i < (my_argc - 1))) - { - unsigned char tmp[4]; - int pid = atoi(my_argv[i + 1]); - i++; - store_val(tmp, 0, pid); - send_svr(svr, "EVOF", tmp, sizeof(tmp)); - ecore_main_loop_quit(); - } + fprintf(stderr, "ERROR: unexpected server reply: %.4s\n", op); + retval = EXIT_FAILURE; } - return ECORE_CALLBACK_RENEW; + + if (!waiting) ecore_main_loop_quit(); + +#undef IS_OP } -Eina_Bool -_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev EINA_UNUSED) +static void +_on_data(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) { - ecore_main_loop_quit(); - return ECORE_CALLBACK_RENEW; + Eina_Slice slice, payload; + Efl_Debug_Message_Header msgheader; + + if (!efl_io_queue_slice_get(output, &slice)) + return; + + if (slice.len < sizeof(msgheader)) + return; + + memcpy(&msgheader, slice.mem, sizeof(msgheader)); + if (msgheader.size < 4) /* must contain at last 4 byte opcode */ + { + fprintf(stderr, "ERROR: invalid message header, size=%u\n", msgheader.size); + retval = EXIT_FAILURE; + ecore_main_loop_quit(); + return; + } + + if (msgheader.size + 4 > slice.len) + return; + + payload.bytes = slice.bytes + sizeof(msgheader); + payload.len = msgheader.size - 4; + + _process_reply(msgheader.op, payload); + + efl_io_queue_discard(output, sizeof(msgheader) + payload.len); } static Eina_Bool -_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Data *ev) +_command_send(const char op[static 4], const void *data, unsigned int len) { - char op[5]; - unsigned char *d = NULL; - int size; + Eina_Error err; + Efl_Debug_Message_Header msghdr = { + .size = 4 + len, + }; + Eina_Slice s, r; - _protocol_collect(&(buf), &(buf_size), ev->data, ev->size); - while ((size = _proto_read(&(buf), &(buf_size), op, &d)) >= 0) + memcpy(msghdr.op, op, 4); + + s.mem = &msghdr; + s.len = sizeof(msghdr); + + err = efl_io_writer_write(input, &s, &r); + if (err || r.len) goto end; + + if (!len) goto end; + + s.mem = data; + s.len = len; + err = efl_io_writer_write(input, &s, &r); + + end: + if (err) { - _do(op, d, size); - free(d); - d = NULL; + fprintf(stderr, "ERROR: could not queue message '%.4s': %s\n", op, eina_error_msg_get(err)); + retval = EXIT_FAILURE; + return EINA_FALSE; } - return ECORE_CALLBACK_RENEW; + + if (r.len) + { + fprintf(stderr, "ERROR: could not queue message '%.4s': out of memory\n", op); + retval = EXIT_FAILURE; + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static void +_dialer_eos(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + ecore_main_loop_quit(); +} + +static void +_dialer_error(void *data EINA_UNUSED, const Efl_Event *event) +{ + Eina_Error *perr = event->info; + + fprintf(stderr, "ERROR: error communicating to %s: %s\n", + efl_net_dialer_address_dial_get(dialer), + eina_error_msg_get(*perr)); + retval = EINA_TRUE; + ecore_main_loop_quit(); } int main(int argc, char **argv) { + Eo *loop; + char *path; + Eina_Error err; + int i; + + if (argc < 2) + { + fprintf(stderr, "ERROR: missing argument.\n"); + return EXIT_FAILURE; + } + for (i = 1; i < argc; i++) + { + if ((strcmp(argv[i], "-h") != 0) && + (strcmp(argv[i], "--help") != 0)) + continue; + + printf("Usage:\n" + "\n" + "\t%s [arguments]\n" + "\n" + "where is one of:\n" + "\tlist list connected process (pid)\n" + "\tpon enable profiling for at frequency in microseconds.\n" + "\tpoff disable profiling for \n" + "\tevlogon start logging events to ~/efl_debug_evlog-.log\n" + "\tevlogoff stop logging events from \n", + argv[0]); + + return EXIT_SUCCESS; + } + + ecore_app_no_system_modules(); + eina_init(); ecore_init(); ecore_con_init(); - my_argc = argc; - my_argv = argv; - - svr = ecore_con_server_connect(ECORE_CON_LOCAL_USER, "efl_debug", 0, NULL); - if (!svr) + path = ecore_con_local_path_new(EINA_FALSE, "efl_debug", 0); + if (!path) { - fprintf(stderr, "ERROR: Cannot connect to debug daemon.\n"); - return -1; + fprintf(stderr, "ERROR: could not get local communication path\n"); + retval = EXIT_FAILURE; + goto end; } - ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, (Ecore_Event_Handler_Cb)_server_add, NULL); - ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, (Ecore_Event_Handler_Cb)_server_del, NULL); - ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, (Ecore_Event_Handler_Cb)_server_data, NULL); + loop = ecore_main_loop_get(); + +#ifdef EFL_NET_DIALER_UNIX_CLASS + dialer = efl_add(EFL_NET_DIALER_UNIX_CLASS, loop); +#else + /* TODO: maybe start a TCP using locahost:12345? + * Right now eina_debug_monitor is only for AF_UNIX, so not an issue. + */ + fprintf(stderr, "ERROR: your platform doesn't support Efl.Net.Dialer.Unix\n"); +#endif + if (!dialer) + { + fprintf(stderr, "ERROR: could not create communication dialer\n"); + retval = EXIT_FAILURE; + goto end; + } + efl_event_callback_add(dialer, EFL_NET_DIALER_EVENT_ERROR, _dialer_error, NULL); + efl_event_callback_add(dialer, EFL_IO_READER_EVENT_EOS, _dialer_eos, NULL); + + input = efl_add(EFL_IO_QUEUE_CLASS, loop); + if (!input) + { + fprintf(stderr, "ERROR: could not create input queue\n"); + retval = EXIT_FAILURE; + goto end; + } + + output = efl_add(EFL_IO_QUEUE_CLASS, loop, + efl_event_callback_add(efl_added, EFL_IO_QUEUE_EVENT_SLICE_CHANGED, _on_data, NULL)); + if (!output) + { + fprintf(stderr, "ERROR: could not create output queue\n"); + retval = EXIT_FAILURE; + goto end; + } + + send_copier = efl_add(EFL_IO_COPIER_CLASS, loop, + efl_io_copier_source_set(efl_added, input), + efl_io_copier_destination_set(efl_added, dialer), + efl_io_closer_close_on_destructor_set(efl_added, EINA_FALSE)); + if (!send_copier) + { + fprintf(stderr, "ERROR: could not create send copier\n"); + retval = EXIT_FAILURE; + goto end; + } + + recv_copier = efl_add(EFL_IO_COPIER_CLASS, loop, + efl_io_copier_source_set(efl_added, dialer), + efl_io_copier_destination_set(efl_added, output), + efl_io_closer_close_on_destructor_set(efl_added, EINA_FALSE)); + if (!recv_copier) + { + fprintf(stderr, "ERROR: could not create receive copier\n"); + retval = EXIT_FAILURE; + goto end; + } + + for (i = 1; i < argc; i++) + { + const char *cmd = argv[i]; + + if (strcmp(cmd, "list") == 0) + { + if (!_command_send("LIST", NULL, 0)) + goto end; + waiting = eina_list_append(waiting, CLST); + } + else if (strcmp(cmd, "pon") == 0) + { + if (i + 2 >= argc) + { + fprintf(stderr, "ERROR: missing argument: pon \n"); + retval = EXIT_FAILURE; + goto end; + } + else + { + int data[2] = {atoi(argv[i + 1]), atoi(argv[1 + 2])}; + if (!_command_send("PLON", data, sizeof(data))) + goto end; + i += 2; + } + } + else if (strcmp(cmd, "poff") == 0) + { + if (i + 1 >= argc) + { + fprintf(stderr, "ERROR: missing argument: poff \n"); + retval = EXIT_FAILURE; + goto end; + } + else + { + int data[1] = {atoi(argv[i + 1])}; + if (!_command_send("PLOFF", data, sizeof(data))) + goto end; + i++; + } + } + else if (strcmp(cmd, "evlogon") == 0) + { + if (i + 1 >= argc) + { + fprintf(stderr, "ERROR: missing argument: evlogon \n"); + retval = EXIT_FAILURE; + goto end; + } + else + { + int data[1] = {atoi(argv[i + 1])}; + if (!_command_send("EVON", data, sizeof(data))) + goto end; + i++; + } + } + else if (strcmp(cmd, "evlogoff") == 0) + { + if (i + 1 >= argc) + { + fprintf(stderr, "ERROR: missing argument: evlogoff \n"); + retval = EXIT_FAILURE; + goto end; + } + else + { + int data[1] = {atoi(argv[i + 1])}; + if (!_command_send("EVOF", data, sizeof(data))) + goto end; + i++; + } + } + else + { + fprintf(stderr, "ERROR: unknown command: %s\n", argv[i]); + retval = EXIT_FAILURE; + goto end; + } + } + efl_io_queue_eos_mark(input); + + err = efl_net_dialer_dial(dialer, path); + if (err) + { + fprintf(stderr, "ERROR: could not connect '%s': %s\n", path, eina_error_msg_get(err)); + retval = EXIT_FAILURE; + goto end; + } ecore_main_loop_begin(); - ecore_con_server_flush(svr); + + while ((!efl_io_closer_closed_get(dialer)) && + efl_io_queue_usage_get(input)) + efl_io_copier_flush(send_copier); + + end: + eina_list_free(waiting); + efl_del(input); + efl_del(output); + efl_del(dialer); + efl_del(send_copier); + efl_del(recv_copier); + free(path); ecore_con_shutdown(); ecore_shutdown(); eina_shutdown(); + return retval; } diff --git a/src/bin/efl/efl_debug_common.h b/src/bin/efl/efl_debug_common.h index dc6190e653..29e9739c7f 100644 --- a/src/bin/efl/efl_debug_common.h +++ b/src/bin/efl/efl_debug_common.h @@ -27,6 +27,11 @@ #include #include +typedef struct _Efl_Debug_Message_Header { + unsigned int size; + char op[4]; +} Efl_Debug_Message_Header; + void _protocol_collect(unsigned char **buf, unsigned int *buf_size, void *data, int size); int _proto_read(unsigned char **buf, unsigned int *buf_size, @@ -36,16 +41,6 @@ int _proto_read(unsigned char **buf, unsigned int *buf_size, memcpy(&dst, ((unsigned char *)buf) + off, sizeof(dst)) #define store_val(buf, off, src) \ memcpy(buf + off, &src, sizeof(src)) -#define send_svr(svr, op, data, size) \ - do { \ - unsigned char head[8]; \ - char *op2 = op; \ - int size2 = size + 4; \ - memcpy(head + 0, &size2, 4); \ - memcpy(head + 4, op2, 4); \ - ecore_con_server_send(svr, head, 8); \ - if (size > 0) ecore_con_server_send(svr, data, size); \ - } while (0) #define send_cli(cli, op, data, size) \ do { \ unsigned char head[8]; \