diff options
author | Daniel Zaoui <daniel.zaoui@yahoo.com> | 2017-05-25 13:26:41 +0300 |
---|---|---|
committer | Daniel Zaoui <daniel.zaoui@yahoo.com> | 2017-06-05 08:55:37 +0300 |
commit | d6e3ab67dbf652dcb90ce890ec779372f7db3e44 (patch) | |
tree | 20452ae44334fc031ebb231fe248c68b5e8eb641 /src/lib/eina/eina_debug.c | |
parent | 36959014d3f632bba52f20d185bb11be3c2889d6 (diff) | |
download | efl-d6e3ab67dbf652dcb90ce890ec779372f7db3e44.tar.gz |
Replace shell remote connection with localhost TCP connection
Diffstat (limited to 'src/lib/eina/eina_debug.c')
-rw-r--r-- | src/lib/eina/eina_debug.c | 397 |
1 files changed, 75 insertions, 322 deletions
diff --git a/src/lib/eina/eina_debug.c b/src/lib/eina/eina_debug.c index 9ed8dc27b9..dcd707899d 100644 --- a/src/lib/eina/eina_debug.c +++ b/src/lib/eina/eina_debug.c @@ -36,6 +36,8 @@ #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> #include <fcntl.h> #include "eina_debug.h" @@ -86,8 +88,6 @@ static int _module_init_opcode = EINA_DEBUG_OPCODE_INVALID; static int _module_shutdown_opcode = EINA_DEBUG_OPCODE_INVALID; static Eina_Hash *_modules_hash = NULL; -static int _bridge_keep_alive_opcode = EINA_DEBUG_OPCODE_INVALID; - /* Semaphore used by the debug thread to wait for another thread to do the * requested job. * It is needed when packets are needed to be treated into a specific @@ -95,10 +95,6 @@ static int _bridge_keep_alive_opcode = EINA_DEBUG_OPCODE_INVALID; */ static Eina_Semaphore _thread_cmd_ready_sem; -/* Used to encode/decode data on sending/reception */ -typedef void *(*Eina_Debug_Encode_Cb)(const void *buffer, unsigned int size, unsigned int *ret_size); -typedef void *(*Eina_Debug_Decode_Cb)(const void *buffer, unsigned int size, unsigned int *ret_size); - typedef struct { const Eina_Debug_Opcode *ops; @@ -111,20 +107,9 @@ struct _Eina_Debug_Session Eina_List **cbs; /* Table of callbacks lists indexed by opcode id */ Eina_List *opcode_reply_infos; Eina_Debug_Dispatch_Cb dispatch_cb; /* Session dispatcher */ - Eina_Debug_Encode_Cb encode_cb; /* Packet encoder */ - Eina_Debug_Decode_Cb decode_cb; /* Packet decoder */ - Eina_List *cmds; /* List of shell commands to send before the communication - * with the daemon. Only used when a shell remote - * connection is requested. - */ void *data; /* User data */ - double encoding_ratio; /* Encoding ratio */ int cbs_length; /* cbs table size */ - int fd_in; /* File descriptor to read */ - int fd_out; /* File descriptor to write */ - Eina_Bool wait_for_input : 1; /* Indicator to wait for input before - * continuing sending commands. - * Only used in shell remote connections */ + int fd; /* File descriptor */ }; static void _opcodes_register_all(Eina_Debug_Session *session); @@ -142,39 +127,16 @@ eina_debug_session_send_to_thread(Eina_Debug_Session *session, int dest_id, int hdr.opcode = op; hdr.cid = dest_id; hdr.thread_id = thread_id; - if (!session->encode_cb) - { - e_debug("socket: %d / opcode %X / bytes to send: %d", - session->fd_out, op, hdr.size); + e_debug("socket: %d / opcode %X / bytes to send: %d", + session->fd, op, hdr.size); #ifndef _WIN32 - eina_spinlock_take(&_eina_debug_lock); - /* Sending header */ - write(session->fd_out, &hdr, sizeof(hdr)); - /* Sending payload */ - if (size) write(session->fd_out, data, size); - eina_spinlock_release(&_eina_debug_lock); + eina_spinlock_take(&_eina_debug_lock); + /* Sending header */ + write(session->fd, &hdr, sizeof(hdr)); + /* Sending payload */ + if (size) write(session->fd, data, size); + eina_spinlock_release(&_eina_debug_lock); #endif - } - else - { - unsigned char *total_buf = NULL; - void *new_buf; - unsigned int total_size = size + sizeof(hdr), new_size = 0; - total_buf = alloca(total_size); - memcpy(total_buf, &hdr, sizeof(hdr)); - if (size > 0) memcpy(total_buf + sizeof(hdr), data, size); - - new_buf = session->encode_cb(total_buf, total_size, &new_size); - e_debug("socket: %d / opcode %X / packet size %d / bytes to send: %d", - session->fd_out, op, total_size, new_size); -#ifndef _WIN32 - eina_spinlock_take(&_eina_debug_lock); - write(session->fd_out, new_buf, new_size); - eina_spinlock_release(&_eina_debug_lock); -#endif - free(new_buf); - } - return hdr.size; } @@ -208,104 +170,18 @@ _daemon_greet(Eina_Debug_Session *session) eina_debug_session_send(session, 0, EINA_DEBUG_OPCODE_HELLO, buf, size); } -static void -_cmd_consume(Eina_Debug_Session *session) -{ - const char *line = NULL; - do { - line = eina_list_data_get(session->cmds); - session->cmds = eina_list_remove_list(session->cmds, session->cmds); - if (line) - { - if (!strncmp(line, "WAIT", 4)) - { - e_debug("Wait for input"); - session->wait_for_input = EINA_TRUE; - return; - } - else if (!strncmp(line, "SLEEP_1", 7)) - { - e_debug("Sleep 1s"); - sleep(1); - } - else - { - e_debug("Apply cmd line: %s", line); - write(session->fd_out, line, strlen(line)); - write(session->fd_out, "\n", 1); - } - } - } - while (line); - /* When all the cmd has been applied, we can begin to send debug packets */ - _daemon_greet(session); - _opcodes_register_all(session); -} - -static Eina_List * -_parse_cmds(const char *cmds) -{ - Eina_List *lines = NULL; - while (cmds && *cmds) - { - char *tmp = strchr(cmds, '\n'); - Eina_Stringshare *line; - if (tmp) - { - line = eina_stringshare_add_length(cmds, tmp - cmds); - cmds = tmp + 1; - } - else - { - line = eina_stringshare_add(cmds); - cmds = NULL; - } - lines = eina_list_append(lines, line); - } - return lines; -} - #ifndef _WIN32 static int _packet_receive(Eina_Debug_Session *session, unsigned char **buffer) { - unsigned char *packet_buf = NULL, *size_buf; - int rret = -1, ratio, size_sz; + unsigned char *packet_buf = NULL; + int rret = -1; + unsigned int size = 0; if (!session) goto end; - if (session->wait_for_input) + if ((rret = read(session->fd, &size, 4)) == 4) { - /* Wait for input */ - char c; - int flags = fcntl(session->fd_in, F_GETFL, 0); - e_debug_begin("Characters received: "); - if (fcntl(session->fd_in, F_SETFL, flags | O_NONBLOCK) == -1) perror(0); - while (read(session->fd_in, &c, 1) == 1) e_debug_continue("%c", c); - if (fcntl(session->fd_in, F_SETFL, flags) == -1) perror(0); - e_debug_end(); - session->wait_for_input = EINA_FALSE; - _cmd_consume(session); - return 0; - } - - ratio = session->decode_cb && session->encoding_ratio ? session->encoding_ratio : 1.0; - size_sz = sizeof(int) * ratio; - size_buf = alloca(size_sz); - if ((rret = read(session->fd_in, size_buf, size_sz)) == size_sz) - { - unsigned int size; - if (session->decode_cb) - { - /* Decode the size if needed */ - void *size_decoded_buf = session->decode_cb(size_buf, size_sz, NULL); - size = (*(unsigned int *)size_decoded_buf) * session->encoding_ratio; - free(size_decoded_buf); - } - else - { - size = *(unsigned int *)size_buf; - } if (size > EINA_DEBUG_MAX_PACKET_SIZE) { e_debug("Packet too big: %d. The maximum allowed is %d", size, EINA_DEBUG_MAX_PACKET_SIZE); @@ -317,12 +193,12 @@ _packet_receive(Eina_Debug_Session *session, unsigned char **buffer) packet_buf = malloc(size); if (packet_buf) { - unsigned int cur_packet_size = size_sz; - memcpy(packet_buf, size_buf, size_sz); + unsigned int cur_packet_size = 4; + memcpy(packet_buf, &size, 4); /* Receive all the remaining packet bytes */ while (cur_packet_size < size) { - rret = read(session->fd_in, packet_buf + cur_packet_size, size - cur_packet_size); + rret = read(session->fd, packet_buf + cur_packet_size, size - cur_packet_size); if (rret <= 0) { e_debug("Error on read: %d", rret); @@ -331,13 +207,6 @@ _packet_receive(Eina_Debug_Session *session, unsigned char **buffer) } cur_packet_size += rret; } - if (session->decode_cb) - { - /* Decode the packet if needed */ - void *decoded_buf = session->decode_cb(packet_buf, size, &cur_packet_size); - free(packet_buf); - packet_buf = decoded_buf; - } *buffer = packet_buf; rret = cur_packet_size; e_debug("Received a packet of %d bytes", cur_packet_size); @@ -372,7 +241,7 @@ eina_debug_session_terminate(Eina_Debug_Session *session) { /* Close fd here so the thread terminates its own session by itself */ if (!session) return; - close(session->fd_in); + close(session->fd); } EAPI void @@ -496,12 +365,6 @@ static const Eina_Debug_Opcode _MONITOR_OPS[] = {NULL, NULL, NULL} }; -static const Eina_Debug_Opcode _BRIDGE_OPS[] = -{ - {"Bridge/Keep-Alive", &_bridge_keep_alive_opcode, NULL}, - {NULL, NULL, NULL} -}; - static void _static_opcode_register(Eina_Debug_Session *session, int op_id, Eina_Debug_Cb cb) @@ -643,6 +506,53 @@ _socket_home_get() (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path)) #endif +static Eina_Debug_Session * +_session_create(int fd) +{ + Eina_Debug_Session *session = calloc(1, sizeof(*session)); + session->dispatch_cb = eina_debug_dispatch; + session->fd = fd; + // start the monitor thread + _thread_start(session); + _daemon_greet(session); + _opcodes_register_all(session); + return session; +} + +EAPI Eina_Debug_Session * +eina_debug_remote_connect(int port) +{ +#ifndef _WIN32 + int fd; + struct sockaddr_in server; + + //Create socket + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) goto err; + // set the socket to close when we exec things so they don't inherit it + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) goto err; + + //Prepare the sockaddr_in structure + server.sin_family = AF_INET; + inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr); + server.sin_port = htons(port); + + if (connect(fd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + perror("connect failed. Error"); + goto err; + } + return _session_create(fd); +err: + // some kind of connection failure here, so close a valid socket and + // get out of here + if (fd >= 0) close(fd); +#else + (void) port; +#endif + return NULL; +} + EAPI Eina_Debug_Session * eina_debug_local_connect(Eina_Bool is_master) { @@ -651,17 +561,14 @@ eina_debug_local_connect(Eina_Bool is_master) int fd, socket_unix_len, curstate = 0; struct sockaddr_un socket_unix; - Eina_Debug_Session *session = calloc(1, sizeof(*session)); - session->dispatch_cb = eina_debug_dispatch; - session->fd_out = session->fd_in = -1; + if (is_master) return eina_debug_remote_connect(REMOTE_SERVER_PORT); + // try this socket file - it will likely be: // ~/.ecore/efl_debug/0 // or maybe // /var/run/UID/.ecore/efl_debug/0 - // either way a 4k buffer should be ebough ( if it's not we're on an - // insane system) - snprintf(buf, sizeof(buf), "%s/%s/%s/%i", _socket_home_get(), SERVER_PATH, SERVER_NAME, - is_master ? SERVER_MASTER_PORT : SERVER_SLAVE_PORT); + snprintf(buf, sizeof(buf), "%s/%s/%s/%i", _socket_home_get(), + LOCAL_SERVER_PATH, LOCAL_SERVER_NAME, LOCAL_SERVER_PORT); // create the socket fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) goto err; @@ -678,118 +585,21 @@ eina_debug_local_connect(Eina_Bool is_master) // actually connect to efl_debugd service if (connect(fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) goto err; - // we succeeded - session->fd_out = session->fd_in = fd; - // start the monitor thread - _thread_start(session); - _daemon_greet(session); - _opcodes_register_all(session); - if (!is_master) - eina_debug_opcodes_register(session, _MONITOR_OPS, NULL, NULL); + _last_local_session = _session_create(fd); + eina_debug_opcodes_register(_last_local_session, _MONITOR_OPS, NULL, NULL); - _last_local_session = session; - return session; + return _last_local_session; err: // some kind of connection failure here, so close a valid socket and // get out of here if (fd >= 0) close(fd); - free(session); #else (void) is_master; #endif return NULL; } -EAPI Eina_Debug_Session * -eina_debug_fds_attach(int fd_in, int fd_out) -{ - Eina_Debug_Session *session = calloc(1, sizeof(*session)); - session->dispatch_cb = eina_debug_dispatch; - session->fd_out = fd_out; - session->fd_in = fd_in; - // start the monitor thread - _thread_start(session); - _opcodes_register_all(session); - _last_local_session = session; - return session; -} - -static Eina_Bool -_bridge_keep_alive_send(void *data) -{ - Eina_Debug_Session *s = data; - eina_debug_session_send(s, 0, _bridge_keep_alive_opcode, NULL, 0); - return EINA_TRUE; -} - -EAPI Eina_Debug_Session * -eina_debug_shell_remote_connect(const char *cmds_str) -{ -#ifndef _WIN32 - Eina_List *cmds = _parse_cmds(cmds_str); - char *cmd = eina_list_data_get(cmds); - int pipeToShell[2], pipeFromShell[2]; - int pid = -1; - - cmds = eina_list_remove_list(cmds, cmds); - - pipe(pipeToShell); - pipe(pipeFromShell); - pid = fork(); - if (pid == -1) return EINA_FALSE; - if (!pid) - { - int i = 0; - const char *args[16] = { 0 }; - /* Child */ - close(STDIN_FILENO); - dup2(pipeToShell[0], STDIN_FILENO); - close(STDOUT_FILENO); - dup2(pipeFromShell[1], STDOUT_FILENO); - args[i++] = cmd; - do - { - cmd = strchr(cmd, ' '); - if (cmd) - { - *cmd = '\0'; - args[i++] = ++cmd; - } - } - while (cmd); - args[i++] = 0; - execvpe(args[0], (char **)args, environ); - perror("execvpe"); - exit(-1); - } - else - { - Eina_Debug_Session *session = calloc(1, sizeof(*session)); - /* Parent */ - session->dispatch_cb = eina_debug_dispatch; - session->fd_in = pipeFromShell[0]; - session->fd_out = pipeToShell[1]; - - int flags = fcntl(session->fd_in, F_GETFL, 0); - flags &= ~O_NONBLOCK; - if (fcntl(session->fd_in, F_SETFL, flags) == -1) perror(0); - - eina_debug_session_shell_codec_enable(session); - session->cmds = cmds; - _cmd_consume(session); - eina_debug_opcodes_register(session, _BRIDGE_OPS, NULL, NULL); - eina_debug_timer_add(10000, _bridge_keep_alive_send, session); - // start the monitor thread - _thread_start(session); - return session; - } -#else - (void) cmds_str; - return NULL; -#endif -} - // this is a DEDICATED debug thread to monitor the application so it works // even if the mainloop is blocked or the app otherwise deadlocked in some // way. this is an alternative to using external debuggers so we can get @@ -833,7 +643,7 @@ _monitor(void *_data) } else { - close(session->fd_in); + close(session->fd); _opcodes_unregister_all(session); free(session); session = NULL; @@ -898,67 +708,10 @@ eina_debug_opcodes_register(Eina_Debug_Session *session, const Eina_Debug_Opcode /* Send only if session's fd connected. * Otherwise, it will be sent when connected */ - if(session && session->fd_in != -1 && !session->cmds) + if(session && session->fd!= -1) _opcodes_registration_send(session, info); } -/* - * Encoder for shell sessions - * Each byte is encoded in two bytes. - */ -static void * -_shell_encode_cb(const void *data, unsigned int src_size, unsigned int *dest_size) -{ - const char *src = data; - unsigned int new_size = src_size * 2; - char *dest = malloc(new_size); - unsigned int i; - for (i = 0; i < src_size; i++) - { - dest[(i << 1) + 0] = ((src[i] & 0xF0) >> 4) + 0x40; - dest[(i << 1) + 1] = ((src[i] & 0x0F) >> 0) + 0x40; - } - if (dest_size) *dest_size = new_size; - return dest; -} - -/* - * Decoder for shell sessions - * Each two bytes are merged into one byte. - */ -static void * -_shell_decode_cb(const void *data, unsigned int src_size, unsigned int *dest_size) -{ - const char *src = data; - unsigned int i = 0, j; - char *dest = malloc(src_size / 2); - if (!dest) goto error; - for (i = 0, j = 0; j < src_size; j++) - { - if ((src[j] & 0xF0) == 0x40 && (src[j + 1] & 0xF0) == 0x40) - { - dest[i++] = ((src[j] - 0x40) << 4) | ((src[j + 1] - 0x40)); - j++; - } - } - goto end; -error: - free(dest); - dest = NULL; -end: - if (dest_size) *dest_size = i; - return dest; -} - -EAPI void -eina_debug_session_shell_codec_enable(Eina_Debug_Session *session) -{ - if (!session) return; - session->encode_cb = _shell_encode_cb; - session->decode_cb = _shell_decode_cb; - session->encoding_ratio = 2.0; -} - static Eina_Debug_Error _self_dispatch(Eina_Debug_Session *session, void *buffer) { |