forked from enlightenment/efl
Add shell remote connection
This feature is essential to debug remote applications.
This commit is contained in:
parent
5251ee326d
commit
39c6a9562b
|
@ -164,6 +164,7 @@ endif
|
|||
|
||||
bin_PROGRAMS += \
|
||||
bin/efl/efl_debugd \
|
||||
bin/efl/efl_debug_shell_bridge \
|
||||
bin/efl/efl_debug
|
||||
|
||||
bin_efl_efl_debugd_SOURCES = bin/efl/efl_debugd.c
|
||||
|
@ -171,6 +172,11 @@ bin_efl_efl_debugd_CPPFLAGS = -I$(top_builddir)/src/bin/efl @EINA_CFLAGS@ @ECORE
|
|||
bin_efl_efl_debugd_LDADD = @EFL_LIBS@ @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
|
||||
bin_efl_efl_debugd_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
|
||||
|
||||
bin_efl_efl_debug_shell_bridge_SOURCES = bin/efl/efl_debug_shell_bridge.c
|
||||
bin_efl_efl_debug_shell_bridge_CPPFLAGS = -I$(top_builddir)/src/bin/efl @EINA_CFLAGS@ @ECORE_CFLAGS@ @ECORE_CON_CFLAGS@
|
||||
bin_efl_efl_debug_shell_bridge_LDADD = @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
|
||||
bin_efl_efl_debug_shell_bridge_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
|
||||
|
||||
bin_efl_efl_debug_SOURCES = bin/efl/efl_debug.c
|
||||
bin_efl_efl_debug_CPPFLAGS = -I$(top_builddir)/src/bin/efl @EINA_CFLAGS@ @ECORE_CFLAGS@ @ECORE_CON_CFLAGS@
|
||||
bin_efl_efl_debug_LDADD = @EFL_LIBS@ @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
efl_debugd
|
||||
efl_debug_shell_bridge
|
||||
efl_debug
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2015 Carsten Haitzler
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library;
|
||||
* if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Eo.h>
|
||||
#include <Eina.h>
|
||||
#include <Ecore.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static Eina_Debug_Session *_shell_session = NULL, *_local_session = NULL;
|
||||
|
||||
static int _nb_msgs = 0;
|
||||
|
||||
static Eina_Bool
|
||||
_check_nb_msgs(void *data EINA_UNUSED)
|
||||
{
|
||||
static int last_nb_msgs = 0;
|
||||
if (last_nb_msgs == _nb_msgs)
|
||||
{
|
||||
ecore_main_loop_quit();
|
||||
return EINA_FALSE;
|
||||
}
|
||||
last_nb_msgs = _nb_msgs;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
_forward(Eina_Debug_Session *session, void *buffer)
|
||||
{
|
||||
Eina_Debug_Packet_Header *hdr = buffer;
|
||||
char *payload = ((char *)buffer) + sizeof(*hdr);
|
||||
int size = hdr->size - sizeof(*hdr);
|
||||
eina_debug_session_send_to_thread(session == _local_session ? _shell_session : _local_session,
|
||||
hdr->cid, hdr->thread_id, hdr->opcode, payload, size);
|
||||
if (session == _shell_session) _nb_msgs = (_nb_msgs + 1) % 1000000;
|
||||
free(buffer);
|
||||
return EINA_DEBUG_OK;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
eina_debug_disable();
|
||||
eina_init();
|
||||
ecore_init();
|
||||
|
||||
_local_session = eina_debug_local_connect(EINA_TRUE);
|
||||
eina_debug_session_dispatch_override(_local_session, _forward);
|
||||
|
||||
_shell_session = eina_debug_fds_attach(STDIN_FILENO, STDOUT_FILENO);
|
||||
eina_debug_session_dispatch_override(_shell_session, _forward);
|
||||
eina_debug_session_shell_codec_enable(_shell_session);
|
||||
|
||||
ecore_timer_add(30.0, _check_nb_msgs, NULL);
|
||||
ecore_main_loop_begin();
|
||||
|
||||
ecore_shutdown();
|
||||
eina_shutdown();
|
||||
}
|
||||
|
|
@ -574,7 +574,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
|
|||
_slave_added_opcode = _opcode_register("daemon/observer/slave_added", EINA_DEBUG_OPCODE_INVALID, NULL);
|
||||
_slave_deleted_opcode = _opcode_register("daemon/observer/slave_deleted", EINA_DEBUG_OPCODE_INVALID, NULL);
|
||||
_cid_from_pid_opcode = _opcode_register("daemon/info/cid_from_pid", EINA_DEBUG_OPCODE_INVALID, _cid_get_cb);
|
||||
_test_loop_opcode = _opcode_register("daemon/test/loop", EINA_DEBUG_OPCODE_INVALID, _data_test_cb);
|
||||
_test_loop_opcode = _opcode_register("Test/data_loop", EINA_DEBUG_OPCODE_INVALID, _data_test_cb);
|
||||
|
||||
_server_launch();
|
||||
_monitor();
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "eina_util.h"
|
||||
#include "eina_evlog.h"
|
||||
#include "eina_hash.h"
|
||||
#include "eina_stringshare.h"
|
||||
#include "eina_debug_private.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
@ -83,12 +84,17 @@ 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;
|
||||
|
||||
static unsigned int _poll_time = 0;
|
||||
static Eina_Debug_Timer_Cb _poll_timer_cb = NULL;
|
||||
static void *_poll_timer_data = NULL;
|
||||
|
||||
static Eina_Semaphore _thread_cmd_ready_sem;
|
||||
|
||||
typedef void *(*Eina_Debug_Encode_Cb)(const void *buffer, int size, int *ret_size);
|
||||
typedef void *(*Eina_Debug_Decode_Cb)(const void *buffer, int size, int *ret_size);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int magic; /* Used to certify the validity of the struct */
|
||||
|
@ -101,12 +107,22 @@ 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 */
|
||||
double encoding_ratio; /* Encoding ratio */
|
||||
/* List of shell commands to send before the communication
|
||||
* with the daemon. Only used when a shell remote connection is requested.
|
||||
*/
|
||||
Eina_List *cmds;
|
||||
int cbs_length; /* cbs table size */
|
||||
int fd_in; /* File descriptor to read */
|
||||
int fd_out; /* File descriptor to write */
|
||||
/* Indicator to wait for input before continuing sending commands.
|
||||
* Only used in shell remote connections */
|
||||
Eina_Bool wait_for_input : 1;
|
||||
};
|
||||
|
||||
static void _opcodes_register_all();
|
||||
static void _opcodes_register_all(Eina_Debug_Session *session);
|
||||
static void _thread_start(Eina_Debug_Session *session);
|
||||
|
||||
EAPI int
|
||||
|
@ -121,16 +137,39 @@ 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);
|
||||
#ifndef _WIN32
|
||||
e_debug("socket: %d / opcode %X / packet size %ld / bytes to send: %d",
|
||||
session->fd_out, op, hdr->size + sizeof(int), total_size);
|
||||
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_out, &hdr, sizeof(hdr));
|
||||
/* Sending payload */
|
||||
if (size) write(session->fd_out, data, size);
|
||||
eina_spinlock_release(&_eina_debug_lock);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *total_buf = NULL;
|
||||
void *new_buf;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -159,33 +198,133 @@ _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(unsigned char **buffer)
|
||||
{
|
||||
unsigned char *packet_buf = NULL;
|
||||
int rret = -1;
|
||||
int size = 0;
|
||||
unsigned char *packet_buf = NULL, *size_buf;
|
||||
int rret = -1, ratio, size_sz;
|
||||
|
||||
if (!_session) goto end;
|
||||
|
||||
if (read(_session->fd_in, &size, 4) == 4)
|
||||
if (_session->wait_for_input)
|
||||
{
|
||||
/* Wait for input */
|
||||
char c;
|
||||
int flags = fcntl(_session->fd_in, F_GETFL, 0);
|
||||
e_debug_begin("Characters received: ");
|
||||
fcntl(_session->fd_in, F_SETFL, flags | O_NONBLOCK);
|
||||
while (read(_session->fd_in, &c, 1) == 1) e_debug_continue("%c", c);
|
||||
fcntl(_session->fd_in, F_SETFL, flags);
|
||||
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)
|
||||
{
|
||||
int size;
|
||||
if (_session->decode_cb)
|
||||
{
|
||||
/* Decode the size if needed */
|
||||
void *size_decoded_buf = _session->decode_cb(size_buf, size_sz, NULL);
|
||||
size = (*(int *)size_decoded_buf) * _session->encoding_ratio;
|
||||
free(size_decoded_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = *(int *)size_buf;
|
||||
}
|
||||
e_debug("Begin to receive a packet of %d bytes", size);
|
||||
// allocate a buffer for the next bytes to receive
|
||||
packet_buf = malloc(size);
|
||||
if (packet_buf)
|
||||
{
|
||||
int cur_packet_size = 4;
|
||||
memcpy(packet_buf, &size, sizeof(int));
|
||||
int cur_packet_size = size_sz;
|
||||
memcpy(packet_buf, size_buf, size_sz);
|
||||
/* 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);
|
||||
if (rret <= 0) goto end;
|
||||
if (rret <= 0)
|
||||
{
|
||||
e_debug("Error on read: %d", rret);
|
||||
perror("Read");
|
||||
goto end;
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -332,6 +471,11 @@ static const Eina_Debug_Opcode _EINA_DEBUG_MONITOR_OPS[] = {
|
|||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static const Eina_Debug_Opcode _EINA_DEBUG_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)
|
||||
|
@ -534,6 +678,95 @@ err:
|
|||
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, _EINA_DEBUG_BRIDGE_OPS, NULL);
|
||||
eina_debug_timer_add(10000, _bridge_keep_alive_send, session);
|
||||
// start the monitor thread
|
||||
_thread_start(session);
|
||||
return session;
|
||||
}
|
||||
#else
|
||||
(void) cmd;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_debug_timer_add(unsigned int timeout_ms, Eina_Debug_Timer_Cb cb, void *data)
|
||||
{
|
||||
|
@ -605,7 +838,7 @@ _monitor(void *_data)
|
|||
// if not negative - we have a real message
|
||||
if (size > 0)
|
||||
{
|
||||
if(!_session->dispatch_cb(_session, buffer))
|
||||
if (EINA_DEBUG_OK != _session->dispatch_cb(_session, buffer))
|
||||
{
|
||||
// something we don't understand
|
||||
e_debug("EINA DEBUG ERROR: Unknown command");
|
||||
|
@ -694,10 +927,67 @@ eina_debug_opcodes_register(Eina_Debug_Session *session, const Eina_Debug_Opcode
|
|||
session->opcode_reply_infos, info);
|
||||
|
||||
//send only if _session's fd connected, if not - it will be sent when connected
|
||||
if(session && session->fd_in != -1)
|
||||
if(session && session->fd_in != -1 && !session->cmds)
|
||||
_opcodes_registration_send(session, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoder for shell sessions
|
||||
* Each byte is encoded in two bytes.
|
||||
*/
|
||||
static void *
|
||||
_shell_encode_cb(const void *data, int src_size, int *dest_size)
|
||||
{
|
||||
const char *src = data;
|
||||
int new_size = src_size * 2;
|
||||
char *dest = malloc(new_size);
|
||||
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, int src_size, int *dest_size)
|
||||
{
|
||||
const char *src = data;
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -155,6 +155,44 @@ EAPI void eina_debug_disable(void);
|
|||
*/
|
||||
EAPI Eina_Debug_Session *eina_debug_local_connect(Eina_Bool is_master);
|
||||
|
||||
/**
|
||||
* @brief Connect to remote shell daemon
|
||||
*
|
||||
* This function executes the shell. The given commands will be parsed and consumed one by one.
|
||||
* The last command should be the execution of efl_debug_shell_bridge.
|
||||
*
|
||||
* @param cmds the commands to execute
|
||||
*
|
||||
* @return EINA_TRUE on success, EINA_FALSE otherwise.
|
||||
*/
|
||||
EAPI Eina_Debug_Session *eina_debug_shell_remote_connect(const char *cmds);
|
||||
|
||||
/**
|
||||
* @brief Create a session and attach the given file descriptors
|
||||
*
|
||||
* This function is essentially used for the shell bridge, as it needs to connect
|
||||
* to the stdin/stdout file descriptors.
|
||||
*
|
||||
* @param fd_in the file descriptor to read from
|
||||
* @param fd_out the file descriptor to write to
|
||||
*
|
||||
* @return EINA_TRUE on success, EINA_FALSE otherwise.
|
||||
*/
|
||||
EAPI Eina_Debug_Session *eina_debug_fds_attach(int fd_in, int fd_out);
|
||||
|
||||
/**
|
||||
* @brief Enable the shell codec on the given session
|
||||
*
|
||||
* This leads to encode and decode each packet that are going to/coming from
|
||||
* on this session.
|
||||
* It is needed for the communication between the debug tool and the
|
||||
* shell bridge, as some characters are interpreted by the terminal (sh/ssh...).
|
||||
*
|
||||
* @param session the session
|
||||
*/
|
||||
EAPI void
|
||||
eina_debug_session_shell_codec_enable(Eina_Debug_Session *session);
|
||||
|
||||
/**
|
||||
* @brief Terminate the session
|
||||
*
|
||||
|
@ -248,6 +286,7 @@ EAPI int eina_debug_session_send_to_thread(Eina_Debug_Session *session, int dest
|
|||
EAPI Eina_Bool eina_debug_timer_add(unsigned int timeout_ms, Eina_Debug_Timer_Cb cb, void *data);
|
||||
|
||||
EAPI int eina_debug_thread_id_get(void);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
|
|
Loading…
Reference in New Issue