forked from enlightenment/efl
262 lines
6.7 KiB
C
262 lines
6.7 KiB
C
/* 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 "efl_debug_common.h"
|
|
|
|
typedef struct _Client Client;
|
|
|
|
struct _Client
|
|
{
|
|
Ecore_Con_Client *client;
|
|
unsigned char *buf;
|
|
unsigned int buf_size;
|
|
|
|
Ecore_Timer *evlog_fetch_timer;
|
|
int evlog_on;
|
|
FILE *evlog_file;
|
|
|
|
int version;
|
|
pid_t pid;
|
|
};
|
|
|
|
static Ecore_Con_Server *svr = NULL;
|
|
static Eina_List *clients = NULL;
|
|
|
|
static Client *
|
|
_client_pid_find(int pid)
|
|
{
|
|
Client *c;
|
|
Eina_List *l;
|
|
|
|
if (pid <= 0) return NULL;
|
|
EINA_LIST_FOREACH(clients, l, c)
|
|
{
|
|
if (c->pid == pid) return c;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_evlog(void *data)
|
|
{
|
|
Client *c = data;
|
|
send_cli(c->client, "EVLG", NULL, 0);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static void
|
|
_do(Client *c, char *op, unsigned char *d, int size)
|
|
{
|
|
Client *c2;
|
|
Eina_List *l;
|
|
|
|
if ((!strcmp(op, "HELO")) && (size >= 8))
|
|
{
|
|
int version;
|
|
int pid;
|
|
|
|
fetch_val(version, d, 0);
|
|
fetch_val(pid, d, 4);
|
|
c->version = version;
|
|
c->pid = pid;
|
|
}
|
|
else if (!strcmp(op, "LIST"))
|
|
{
|
|
int n = eina_list_count(clients);
|
|
unsigned int *pids = malloc(n * sizeof(int));
|
|
if (pids)
|
|
{
|
|
int i = 0;
|
|
|
|
EINA_LIST_FOREACH(clients, l, c2)
|
|
{
|
|
pids[i] = c2->pid;
|
|
i++;
|
|
}
|
|
send_cli(c->client, "CLST", pids, n * sizeof(int));
|
|
free(pids);
|
|
}
|
|
}
|
|
else if ((!strcmp(op, "PLON")) && (size >= 8))
|
|
{
|
|
int pid;
|
|
unsigned int freq = 1000;
|
|
fetch_val(pid, d, 0);
|
|
fetch_val(freq, d, 4);
|
|
if ((c2 = _client_pid_find(pid)))
|
|
{
|
|
unsigned char buf[4];
|
|
store_val(buf, 0, freq);
|
|
send_cli(c2->client, "PLON", buf, sizeof(buf));
|
|
}
|
|
}
|
|
else if (!strcmp(op, "PLOF"))
|
|
{
|
|
int pid;
|
|
fetch_val(pid, d, 0);
|
|
if ((c2 = _client_pid_find(pid)))
|
|
{
|
|
send_cli(c2->client, "PLOF", NULL, 0);
|
|
}
|
|
}
|
|
else if (!strcmp(op, "EVON"))
|
|
{
|
|
int pid;
|
|
fetch_val(pid, d, 0);
|
|
if ((c2 = _client_pid_find(pid)))
|
|
{
|
|
c2->evlog_on++;
|
|
if (c2->evlog_on == 1)
|
|
{
|
|
char buf[4096];
|
|
|
|
send_cli(c2->client, "EVON", NULL, 0);
|
|
c2->evlog_fetch_timer = ecore_timer_add(0.2, _cb_evlog, c2);
|
|
snprintf(buf, sizeof(buf), "%s/efl_debug_evlog-%i.log",
|
|
getenv("HOME"), c2->pid);
|
|
c2->evlog_file = fopen(buf, "w");
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(op, "EVOF"))
|
|
{
|
|
int pid;
|
|
fetch_val(pid, d, 0);
|
|
if ((c2 = _client_pid_find(pid)))
|
|
{
|
|
c2->evlog_on--;
|
|
if (c2->evlog_on == 0)
|
|
{
|
|
send_cli(c2->client, "EVOF", NULL, 0);
|
|
if (c2->evlog_fetch_timer)
|
|
{
|
|
ecore_timer_del(c2->evlog_fetch_timer);
|
|
c2->evlog_fetch_timer = NULL;
|
|
}
|
|
if (c2->evlog_file)
|
|
{
|
|
fclose(c2->evlog_file);
|
|
c2->evlog_file = NULL;
|
|
}
|
|
}
|
|
else if (c2->evlog_on < 0)
|
|
c2->evlog_on = 0;
|
|
}
|
|
}
|
|
else if (!strcmp(op, "EVLG"))
|
|
{
|
|
unsigned int *overflow = (unsigned int *)(d + 0);
|
|
unsigned char *p = d + 4;
|
|
unsigned int blocksize = size - 4;
|
|
|
|
if ((c->evlog_file) && (blocksize > 0))
|
|
{
|
|
unsigned int header[3];
|
|
|
|
header[0] = 0xffee211;
|
|
header[1] = blocksize;
|
|
header[2] = *overflow;
|
|
fwrite(header, 12, 1, c->evlog_file);
|
|
fwrite(p, blocksize, 1, c->evlog_file);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Eina_Bool
|
|
_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Client_Add *ev)
|
|
{
|
|
Client *c = calloc(1, sizeof(Client));
|
|
if (c)
|
|
{
|
|
c->client = ev->client;
|
|
clients = eina_list_append(clients, c);
|
|
ecore_con_client_data_set(c->client, c);
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_client_del(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Client_Del *ev)
|
|
{
|
|
Client *c = ecore_con_client_data_get(ev->client);
|
|
if (c)
|
|
{
|
|
clients = eina_list_remove(clients, c);
|
|
if (c->evlog_fetch_timer)
|
|
{
|
|
ecore_timer_del(c->evlog_fetch_timer);
|
|
c->evlog_fetch_timer = NULL;
|
|
}
|
|
if (c->evlog_file)
|
|
{
|
|
fclose(c->evlog_file);
|
|
c->evlog_file = NULL;
|
|
}
|
|
free(c);
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_client_data(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Client_Data *ev)
|
|
{
|
|
Client *c = ecore_con_client_data_get(ev->client);
|
|
if (c)
|
|
{
|
|
char op[5];
|
|
unsigned char *d = NULL;
|
|
int size;
|
|
|
|
_protocol_collect(&(c->buf), &(c->buf_size), ev->data, ev->size);
|
|
while ((size = _proto_read(&(c->buf), &(c->buf_size), op, &d)) >= 0)
|
|
{
|
|
_do(c, op, d, size);
|
|
free(d);
|
|
d = NULL;
|
|
}
|
|
}
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
int
|
|
main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
|
|
{
|
|
eina_init();
|
|
ecore_init();
|
|
ecore_con_init();
|
|
|
|
svr = ecore_con_server_add(ECORE_CON_LOCAL_USER, "efl_debug", 0, NULL);
|
|
if (!svr)
|
|
{
|
|
fprintf(stderr, "ERROR: Cannot create debug daemon.\n");
|
|
return -1;
|
|
}
|
|
|
|
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb)_client_add, NULL);
|
|
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, (Ecore_Event_Handler_Cb)_client_del, NULL);
|
|
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, (Ecore_Event_Handler_Cb)_client_data, NULL);
|
|
|
|
ecore_main_loop_begin();
|
|
|
|
ecore_con_server_del(svr);
|
|
|
|
ecore_con_shutdown();
|
|
ecore_shutdown();
|
|
eina_shutdown();
|
|
}
|