summaryrefslogblamecommitdiff
path: root/src/bin/efl/efl_debugd.c
blob: a46d42332b9279126a86f170343e5103eb644e84 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

















                                                                     
                             





                              


                              


                                       
 

                             




                                    













                                    







                                        
           
                                                    
 



                                            
      

                    
 









                                                     
           
                       
 




                                              
                                                                

                        
      
                                                 
      









                                                            
      
                                
      





                                                   
      












                                                                              
                                                                         
                                                    
                                                   





























                                                              
                                                         
                                 
                                          
 
                                               
           






                                                    
           
      





















                                                                                         









                                                   










                                                                                           





                                                                            
           


                                 
           





























                                                                                                    
/* 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();
}