forked from enlightenment/efl
Replace shell remote connection with localhost TCP connection
This commit is contained in:
parent
36959014d3
commit
d6e3ab67db
|
@ -164,7 +164,6 @@ endif
|
||||||
|
|
||||||
bin_PROGRAMS += \
|
bin_PROGRAMS += \
|
||||||
bin/efl/efl_debugd \
|
bin/efl/efl_debugd \
|
||||||
bin/efl/efl_debug_shell_bridge \
|
|
||||||
bin/efl/efl_debug
|
bin/efl/efl_debug
|
||||||
|
|
||||||
bin_efl_efl_debugd_SOURCES = bin/efl/efl_debugd.c
|
bin_efl_efl_debugd_SOURCES = bin/efl/efl_debugd.c
|
||||||
|
@ -172,11 +171,6 @@ 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_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_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_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_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@
|
bin_efl_efl_debug_LDADD = @EFL_LIBS@ @USE_EINA_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ECORE_CON_INTERNAL_LIBS@
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
efl_debugd
|
efl_debugd
|
||||||
efl_debug_shell_bridge
|
|
||||||
efl_debug
|
efl_debug
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
/* 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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "eina_debug_private.h"
|
#include "eina_debug_private.h"
|
||||||
|
|
||||||
|
@ -84,7 +86,7 @@ Opcode_Information *_opcodes[MAX_OPCODES];
|
||||||
|
|
||||||
/* epoll stuff */
|
/* epoll stuff */
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static int _epfd = -1, _listening_master_fd = -1, _listening_slave_fd = -1;
|
static int _epfd = -1, _listening_unix_fd = -1, _listening_tcp_fd = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static Client *
|
static Client *
|
||||||
|
@ -402,7 +404,7 @@ _monitor()
|
||||||
if (events[i].events & EPOLLIN)
|
if (events[i].events & EPOLLIN)
|
||||||
{
|
{
|
||||||
// Someone wants to connect
|
// Someone wants to connect
|
||||||
if(events[i].data.fd == _listening_master_fd || events[i].data.fd == _listening_slave_fd)
|
if(events[i].data.fd == _listening_unix_fd || events[i].data.fd == _listening_tcp_fd)
|
||||||
{
|
{
|
||||||
int new_fd = accept(events[i].data.fd, NULL, NULL);
|
int new_fd = accept(events[i].data.fd, NULL, NULL);
|
||||||
if (new_fd < 0) perror("Accept");
|
if (new_fd < 0) perror("Accept");
|
||||||
|
@ -411,7 +413,7 @@ _monitor()
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
c = calloc(1, sizeof(*c));
|
c = calloc(1, sizeof(*c));
|
||||||
c->fd = new_fd;
|
c->fd = new_fd;
|
||||||
c->is_master = (events[i].data.fd == _listening_master_fd);
|
c->is_master = (events[i].data.fd == _listening_tcp_fd);
|
||||||
_clients = eina_list_append(_clients, c);
|
_clients = eina_list_append(_clients, c);
|
||||||
event.data.fd = new_fd;
|
event.data.fd = new_fd;
|
||||||
event.events = EPOLLIN;
|
event.events = EPOLLIN;
|
||||||
|
@ -480,12 +482,70 @@ _socket_home_get()
|
||||||
#define LENGTH_OF_SOCKADDR_UN(s) \
|
#define LENGTH_OF_SOCKADDR_UN(s) \
|
||||||
(strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
|
(strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
|
||||||
static int
|
static int
|
||||||
_local_listening_socket_create(const char *path)
|
_listening_unix_socket_create()
|
||||||
{
|
{
|
||||||
|
char buf[1048];
|
||||||
struct sockaddr_un socket_unix;
|
struct sockaddr_un socket_unix;
|
||||||
int socket_unix_len, curstate = 0;
|
int socket_unix_len, curstate = 0;
|
||||||
|
char *socket_path = _socket_home_get();
|
||||||
|
mode_t mask = 0;
|
||||||
// create the socket
|
// create the socket
|
||||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
Eina_Bool ret = EINA_FALSE;
|
||||||
|
|
||||||
|
if (fd < 0) goto end;
|
||||||
|
// set the socket to close when we exec things so they don't inherit it
|
||||||
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) goto end;
|
||||||
|
// set up some socket options on addr re-use
|
||||||
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
|
||||||
|
sizeof(curstate)) < 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s", socket_path, LOCAL_SERVER_PATH);
|
||||||
|
if (mkdir(buf, S_IRWXU) < 0 && errno != EEXIST)
|
||||||
|
{
|
||||||
|
perror("mkdir SERVER_PATH");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s/%s", socket_path, LOCAL_SERVER_PATH, LOCAL_SERVER_NAME);
|
||||||
|
if (mkdir(buf, S_IRWXU) < 0 && errno != EEXIST)
|
||||||
|
{
|
||||||
|
perror("mkdir SERVER_NAME");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
mask = umask(S_IRWXG | S_IRWXO);
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s/%s/%i", socket_path,
|
||||||
|
LOCAL_SERVER_PATH, LOCAL_SERVER_NAME, LOCAL_SERVER_PORT);
|
||||||
|
// sa that it's a unix socket and where the path is
|
||||||
|
socket_unix.sun_family = AF_UNIX;
|
||||||
|
strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path) - 1);
|
||||||
|
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
|
||||||
|
unlink(socket_unix.sun_path);
|
||||||
|
if (bind(fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
|
||||||
|
{
|
||||||
|
perror("ERROR on binding");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
listen(fd, 5);
|
||||||
|
ret = EINA_TRUE;
|
||||||
|
end:
|
||||||
|
umask(mask);
|
||||||
|
if (!ret && fd >= 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
free(socket_path);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_listening_tcp_socket_create()
|
||||||
|
{
|
||||||
|
struct sockaddr_in server;
|
||||||
|
int curstate = 0;
|
||||||
|
// create the socket
|
||||||
|
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (fd < 0) goto err;
|
if (fd < 0) goto err;
|
||||||
// set the socket to close when we exec things so they don't inherit it
|
// 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;
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) goto err;
|
||||||
|
@ -493,12 +553,13 @@ _local_listening_socket_create(const char *path)
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
|
||||||
sizeof(curstate)) < 0)
|
sizeof(curstate)) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
// sa that it's a unix socket and where the path is
|
|
||||||
socket_unix.sun_family = AF_UNIX;
|
//Prepare the sockaddr_in structure
|
||||||
strncpy(socket_unix.sun_path, path, sizeof(socket_unix.sun_path) - 1);
|
server.sin_family = AF_INET;
|
||||||
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
|
inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr);
|
||||||
unlink(socket_unix.sun_path);
|
server.sin_port = htons(REMOTE_SERVER_PORT);
|
||||||
if (bind(fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
|
|
||||||
|
if (bind(fd, (struct sockaddr *)&server, sizeof(server)) < 0)
|
||||||
{
|
{
|
||||||
perror("ERROR on binding");
|
perror("ERROR on binding");
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -515,48 +576,27 @@ static Eina_Bool
|
||||||
_server_launch()
|
_server_launch()
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
char buf[4096];
|
|
||||||
struct epoll_event event = {0};
|
struct epoll_event event = {0};
|
||||||
mode_t mask = 0;
|
|
||||||
char *socket_path = _socket_home_get();
|
|
||||||
if (!socket_path) return EINA_FALSE;
|
|
||||||
_epfd = epoll_create (MAX_EVENTS);
|
_epfd = epoll_create (MAX_EVENTS);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", socket_path, SERVER_PATH);
|
_listening_unix_fd = _listening_unix_socket_create();
|
||||||
if (mkdir(buf, S_IRWXU) < 0 && errno != EEXIST)
|
if (_listening_unix_fd <= 0) goto err;
|
||||||
{
|
event.data.fd = _listening_unix_fd;
|
||||||
perror("mkdir SERVER_PATH");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s/%s", socket_path, SERVER_PATH, SERVER_NAME);
|
|
||||||
if (mkdir(buf, S_IRWXU) < 0 && errno != EEXIST)
|
|
||||||
{
|
|
||||||
perror("mkdir SERVER_NAME");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
mask = umask(S_IRWXG | S_IRWXO);
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s/%s/%i", socket_path, SERVER_PATH, SERVER_NAME, SERVER_MASTER_PORT);
|
|
||||||
_listening_master_fd = _local_listening_socket_create(buf);
|
|
||||||
if (_listening_master_fd <= 0) goto err;
|
|
||||||
event.data.fd = _listening_master_fd;
|
|
||||||
event.events = EPOLLIN;
|
event.events = EPOLLIN;
|
||||||
epoll_ctl (_epfd, EPOLL_CTL_ADD, _listening_master_fd, &event);
|
epoll_ctl (_epfd, EPOLL_CTL_ADD, _listening_unix_fd, &event);
|
||||||
snprintf(buf, sizeof(buf), "%s/%s/%s/%i", socket_path, SERVER_PATH, SERVER_NAME, SERVER_SLAVE_PORT);
|
|
||||||
_listening_slave_fd = _local_listening_socket_create(buf);
|
_listening_tcp_fd = _listening_tcp_socket_create();
|
||||||
if (_listening_slave_fd <= 0) goto err;
|
if (_listening_tcp_fd <= 0) goto err;
|
||||||
event.data.fd = _listening_slave_fd;
|
event.data.fd = _listening_tcp_fd;
|
||||||
event.events = EPOLLIN;
|
event.events = EPOLLIN;
|
||||||
epoll_ctl (_epfd, EPOLL_CTL_ADD, _listening_slave_fd, &event);
|
epoll_ctl (_epfd, EPOLL_CTL_ADD, _listening_tcp_fd, &event);
|
||||||
umask(mask);
|
|
||||||
free(socket_path);
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
err:
|
err:
|
||||||
if (mask) umask(mask);
|
if (_listening_unix_fd >= 0) close(_listening_unix_fd);
|
||||||
if (_listening_master_fd >= 0) close(_listening_master_fd);
|
_listening_unix_fd = -1;
|
||||||
_listening_master_fd = -1;
|
if (_listening_tcp_fd >= 0) close(_listening_tcp_fd);
|
||||||
if (_listening_slave_fd >= 0) close(_listening_slave_fd);
|
_listening_tcp_fd = -1;
|
||||||
_listening_slave_fd = -1;
|
|
||||||
free(socket_path);
|
|
||||||
#endif
|
#endif
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "eina_debug.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 int _module_shutdown_opcode = EINA_DEBUG_OPCODE_INVALID;
|
||||||
static Eina_Hash *_modules_hash = NULL;
|
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
|
/* Semaphore used by the debug thread to wait for another thread to do the
|
||||||
* requested job.
|
* requested job.
|
||||||
* It is needed when packets are needed to be treated into a specific
|
* 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;
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
const Eina_Debug_Opcode *ops;
|
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 **cbs; /* Table of callbacks lists indexed by opcode id */
|
||||||
Eina_List *opcode_reply_infos;
|
Eina_List *opcode_reply_infos;
|
||||||
Eina_Debug_Dispatch_Cb dispatch_cb; /* Session dispatcher */
|
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 */
|
void *data; /* User data */
|
||||||
double encoding_ratio; /* Encoding ratio */
|
|
||||||
int cbs_length; /* cbs table size */
|
int cbs_length; /* cbs table size */
|
||||||
int fd_in; /* File descriptor to read */
|
int fd; /* File descriptor */
|
||||||
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 */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void _opcodes_register_all(Eina_Debug_Session *session);
|
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.opcode = op;
|
||||||
hdr.cid = dest_id;
|
hdr.cid = dest_id;
|
||||||
hdr.thread_id = thread_id;
|
hdr.thread_id = thread_id;
|
||||||
if (!session->encode_cb)
|
e_debug("socket: %d / opcode %X / bytes to send: %d",
|
||||||
{
|
session->fd, op, hdr.size);
|
||||||
e_debug("socket: %d / opcode %X / bytes to send: %d",
|
|
||||||
session->fd_out, op, hdr.size);
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
eina_spinlock_take(&_eina_debug_lock);
|
eina_spinlock_take(&_eina_debug_lock);
|
||||||
/* Sending header */
|
/* Sending header */
|
||||||
write(session->fd_out, &hdr, sizeof(hdr));
|
write(session->fd, &hdr, sizeof(hdr));
|
||||||
/* Sending payload */
|
/* Sending payload */
|
||||||
if (size) write(session->fd_out, data, size);
|
if (size) write(session->fd, data, size);
|
||||||
eina_spinlock_release(&_eina_debug_lock);
|
eina_spinlock_release(&_eina_debug_lock);
|
||||||
#endif
|
#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;
|
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);
|
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
|
#ifndef _WIN32
|
||||||
static int
|
static int
|
||||||
_packet_receive(Eina_Debug_Session *session, unsigned char **buffer)
|
_packet_receive(Eina_Debug_Session *session, unsigned char **buffer)
|
||||||
{
|
{
|
||||||
unsigned char *packet_buf = NULL, *size_buf;
|
unsigned char *packet_buf = NULL;
|
||||||
int rret = -1, ratio, size_sz;
|
int rret = -1;
|
||||||
|
unsigned int size = 0;
|
||||||
|
|
||||||
if (!session) goto end;
|
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)
|
if (size > EINA_DEBUG_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
e_debug("Packet too big: %d. The maximum allowed is %d", 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);
|
packet_buf = malloc(size);
|
||||||
if (packet_buf)
|
if (packet_buf)
|
||||||
{
|
{
|
||||||
unsigned int cur_packet_size = size_sz;
|
unsigned int cur_packet_size = 4;
|
||||||
memcpy(packet_buf, size_buf, size_sz);
|
memcpy(packet_buf, &size, 4);
|
||||||
/* Receive all the remaining packet bytes */
|
/* Receive all the remaining packet bytes */
|
||||||
while (cur_packet_size < size)
|
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)
|
if (rret <= 0)
|
||||||
{
|
{
|
||||||
e_debug("Error on read: %d", rret);
|
e_debug("Error on read: %d", rret);
|
||||||
|
@ -331,13 +207,6 @@ _packet_receive(Eina_Debug_Session *session, unsigned char **buffer)
|
||||||
}
|
}
|
||||||
cur_packet_size += rret;
|
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;
|
*buffer = packet_buf;
|
||||||
rret = cur_packet_size;
|
rret = cur_packet_size;
|
||||||
e_debug("Received a packet of %d bytes", 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 */
|
/* Close fd here so the thread terminates its own session by itself */
|
||||||
if (!session) return;
|
if (!session) return;
|
||||||
close(session->fd_in);
|
close(session->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
|
@ -496,12 +365,6 @@ static const Eina_Debug_Opcode _MONITOR_OPS[] =
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Eina_Debug_Opcode _BRIDGE_OPS[] =
|
|
||||||
{
|
|
||||||
{"Bridge/Keep-Alive", &_bridge_keep_alive_opcode, NULL},
|
|
||||||
{NULL, NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_static_opcode_register(Eina_Debug_Session *session,
|
_static_opcode_register(Eina_Debug_Session *session,
|
||||||
int op_id, Eina_Debug_Cb cb)
|
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))
|
(strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
|
||||||
#endif
|
#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 *
|
EAPI Eina_Debug_Session *
|
||||||
eina_debug_local_connect(Eina_Bool is_master)
|
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;
|
int fd, socket_unix_len, curstate = 0;
|
||||||
struct sockaddr_un socket_unix;
|
struct sockaddr_un socket_unix;
|
||||||
|
|
||||||
Eina_Debug_Session *session = calloc(1, sizeof(*session));
|
if (is_master) return eina_debug_remote_connect(REMOTE_SERVER_PORT);
|
||||||
session->dispatch_cb = eina_debug_dispatch;
|
|
||||||
session->fd_out = session->fd_in = -1;
|
|
||||||
// try this socket file - it will likely be:
|
// try this socket file - it will likely be:
|
||||||
// ~/.ecore/efl_debug/0
|
// ~/.ecore/efl_debug/0
|
||||||
// or maybe
|
// or maybe
|
||||||
// /var/run/UID/.ecore/efl_debug/0
|
// /var/run/UID/.ecore/efl_debug/0
|
||||||
// either way a 4k buffer should be ebough ( if it's not we're on an
|
snprintf(buf, sizeof(buf), "%s/%s/%s/%i", _socket_home_get(),
|
||||||
// insane system)
|
LOCAL_SERVER_PATH, LOCAL_SERVER_NAME, LOCAL_SERVER_PORT);
|
||||||
snprintf(buf, sizeof(buf), "%s/%s/%s/%i", _socket_home_get(), SERVER_PATH, SERVER_NAME,
|
|
||||||
is_master ? SERVER_MASTER_PORT : SERVER_SLAVE_PORT);
|
|
||||||
// create the socket
|
// create the socket
|
||||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (fd < 0) goto err;
|
if (fd < 0) goto err;
|
||||||
|
@ -678,118 +585,21 @@ eina_debug_local_connect(Eina_Bool is_master)
|
||||||
// actually connect to efl_debugd service
|
// actually connect to efl_debugd service
|
||||||
if (connect(fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
|
if (connect(fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
// we succeeded
|
|
||||||
session->fd_out = session->fd_in = fd;
|
|
||||||
// start the monitor thread
|
|
||||||
_thread_start(session);
|
|
||||||
|
|
||||||
_daemon_greet(session);
|
_last_local_session = _session_create(fd);
|
||||||
_opcodes_register_all(session);
|
eina_debug_opcodes_register(_last_local_session, _MONITOR_OPS, NULL, NULL);
|
||||||
if (!is_master)
|
|
||||||
eina_debug_opcodes_register(session, _MONITOR_OPS, NULL, NULL);
|
|
||||||
|
|
||||||
_last_local_session = session;
|
return _last_local_session;
|
||||||
return session;
|
|
||||||
err:
|
err:
|
||||||
// some kind of connection failure here, so close a valid socket and
|
// some kind of connection failure here, so close a valid socket and
|
||||||
// get out of here
|
// get out of here
|
||||||
if (fd >= 0) close(fd);
|
if (fd >= 0) close(fd);
|
||||||
free(session);
|
|
||||||
#else
|
#else
|
||||||
(void) is_master;
|
(void) is_master;
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
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
|
// 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
|
// 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
|
// way. this is an alternative to using external debuggers so we can get
|
||||||
|
@ -833,7 +643,7 @@ _monitor(void *_data)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
close(session->fd_in);
|
close(session->fd);
|
||||||
_opcodes_unregister_all(session);
|
_opcodes_unregister_all(session);
|
||||||
free(session);
|
free(session);
|
||||||
session = NULL;
|
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.
|
/* Send only if session's fd connected.
|
||||||
* Otherwise, it will be sent when 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);
|
_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
|
static Eina_Debug_Error
|
||||||
_self_dispatch(Eina_Debug_Session *session, void *buffer)
|
_self_dispatch(Eina_Debug_Session *session, void *buffer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,47 +153,20 @@ EAPI void eina_debug_disable(void);
|
||||||
*
|
*
|
||||||
* @param is_master true if the application is a debugger. EINA_FALSE otherwise.
|
* @param is_master true if the application is a debugger. EINA_FALSE otherwise.
|
||||||
*
|
*
|
||||||
* @return EINA_TRUE on success, EINA_FALSE otherwise.
|
* @return the session on success or NULL otherwise
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Debug_Session *eina_debug_local_connect(Eina_Bool is_master);
|
EAPI Eina_Debug_Session *eina_debug_local_connect(Eina_Bool is_master);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Connect to remote shell daemon
|
* @brief Connect to remote daemon
|
||||||
*
|
*
|
||||||
* This function executes the shell. The given commands will be parsed and consumed one by one.
|
* This function connects to localhost:port.
|
||||||
* The last command should be the execution of efl_debug_shell_bridge.
|
|
||||||
*
|
*
|
||||||
* @param cmds the commands to execute
|
* @param port the port to connect to
|
||||||
*
|
*
|
||||||
* @return EINA_TRUE on success, EINA_FALSE otherwise.
|
* @return the session on success or NULL otherwise
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Debug_Session *eina_debug_shell_remote_connect(const char *cmds);
|
EAPI Eina_Debug_Session *eina_debug_remote_connect(int port);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
* @brief Terminate the session
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
# include "eina_lock.h"
|
# include "eina_lock.h"
|
||||||
# include "eina_thread.h"
|
# include "eina_thread.h"
|
||||||
|
|
||||||
#define SERVER_PATH ".edebug"
|
#define LOCAL_SERVER_PATH ".edebug"
|
||||||
#define SERVER_NAME "efl_debug"
|
#define LOCAL_SERVER_NAME "efl_debug"
|
||||||
#define SERVER_MASTER_PORT 0
|
#define LOCAL_SERVER_PORT 0
|
||||||
#define SERVER_SLAVE_PORT 1
|
|
||||||
|
#define REMOTE_SERVER_PORT 6666
|
||||||
|
|
||||||
#ifdef DEBUGON
|
#ifdef DEBUGON
|
||||||
# define e_debug(fmt, args...) fprintf(stderr, "%d:"__FILE__":%s/%d : " fmt "\n", getpid(), __FUNCTION__, __LINE__, ##args)
|
# define e_debug(fmt, args...) fprintf(stderr, "%d:"__FILE__":%s/%d : " fmt "\n", getpid(), __FUNCTION__, __LINE__, ##args)
|
||||||
|
@ -22,9 +23,7 @@
|
||||||
# define e_debug_end(x...) do { } while (0)
|
# define e_debug_end(x...) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Max packet size
|
/* Max packet size */
|
||||||
* If the shell is used, the ratio is 2.0. It means the max size (not encoded) should be half.
|
|
||||||
*/
|
|
||||||
#define EINA_DEBUG_MAX_PACKET_SIZE 10000000
|
#define EINA_DEBUG_MAX_PACKET_SIZE 10000000
|
||||||
|
|
||||||
typedef struct _Eina_Debug_Session Eina_Debug_Session;
|
typedef struct _Eina_Debug_Session Eina_Debug_Session;
|
||||||
|
|
Loading…
Reference in New Issue