1 /* EINA - EFL data type library
2  * Copyright (C) 2015 Carsten Haitzler
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library;
16  * if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 
23 #define EFL_BETA_API_SUPPORT 1
24 
25 #include <fcntl.h>
26 #include "eina_debug_private.h"
27 
28 #ifdef _WIN32
29 # include <evil_private.h> /* mkdir */
30 #endif
31 #include <Eina.h>
32 #include <Ecore.h>
33 #include <Ecore_Con.h>
34 
35 static int _log_dom = -1;
36 #ifdef ERR
37 # undef ERR
38 #endif
39 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
40 
41 #ifdef DBG
42 # undef DBG
43 #endif
44 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
45 
46 #ifdef INF
47 # undef INF
48 #endif
49 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
50 
51 #ifdef WRN
52 # undef WRN
53 #endif
54 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
55 
56 #ifdef CRI
57 # undef CRI
58 #endif
59 #define CRI(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
60 #if __BYTE_ORDER == __LITTLE_ENDIAN
61 #define SWAP_64(x) x
62 #define SWAP_32(x) x
63 #define SWAP_16(x) x
64 #else
65 #define SWAP_64(x) eina_swap64(x)
66 #define SWAP_32(x) eina_swap32(x)
67 #define SWAP_16(x) eina_swap16(x)
68 #endif
69 
70 #define STORE(_buf, pval, sz) \
71 { \
72    memcpy(_buf, pval, sz); \
73    _buf += sz; \
74 }
75 
76 #define EXTRACT(_buf, pval, sz) \
77 { \
78    memcpy(pval, _buf, sz); \
79    _buf += sz; \
80 }
81 
82 typedef struct _Client Client;
83 
84 struct _Client
85 {
86    Eo *              client;
87    Eina_Stringshare *app_name;
88 
89    int               version;
90    int               cid;
91    pid_t             pid;
92 
93    Eina_Bool         cl_stat_obs : 1;
94    Eina_Bool         is_master : 1;
95 };
96 
97 static Eina_List *_clients = NULL;
98 static int _retval;
99 
100 static Eo *_local_server = NULL, *_remote_server = NULL;
101 
102 typedef Eina_Bool (*Opcode_Cb)(Client *client, void *buffer, int size);
103 
104 static Eina_Hash *_string_to_opcode_hash = NULL;
105 
106 static int _free_cid = 1;
107 
108 static int _clients_stat_register_opcode = EINA_DEBUG_OPCODE_INVALID;
109 static int _slave_added_opcode = EINA_DEBUG_OPCODE_INVALID;
110 static int _slave_deleted_opcode = EINA_DEBUG_OPCODE_INVALID;
111 static int _cid_from_pid_opcode = EINA_DEBUG_OPCODE_INVALID;
112 static int _test_loop_opcode = EINA_DEBUG_OPCODE_INVALID;
113 
114 typedef struct
115 {
116    int opcode;
117    Eina_Stringshare *opcode_string;
118    Opcode_Cb cb;
119 } Opcode_Information;
120 
121 #define MAX_OPCODES 1000
122 Opcode_Information *_opcodes[MAX_OPCODES];
123 
124 static Client *
_client_find_by_cid(int cid)125 _client_find_by_cid(int cid)
126 {
127    Client *c;
128    Eina_List *l;
129    EINA_LIST_FOREACH(_clients, l, c)
130       if (c->cid == cid) return c;
131    return NULL;
132 }
133 
134 static Client *
_client_find_by_pid(int pid)135 _client_find_by_pid(int pid)
136 {
137    Client *c;
138    Eina_List *l;
139    EINA_LIST_FOREACH(_clients, l, c)
140       if (c->pid == pid) return c;
141    return NULL;
142 }
143 
144 static void
_send(Client * dest,int opcode,void * payload,int payload_size)145 _send(Client *dest, int opcode, void *payload, int payload_size)
146 {
147    Eina_Error err;
148    Eina_Slice s, r;
149    Eina_Debug_Packet_Header hdr;
150    int size = sizeof(Eina_Debug_Packet_Header) + payload_size;
151 
152    hdr.size = SWAP_32(size);
153    hdr.cid = 0;
154    hdr.opcode = SWAP_32(opcode);
155 
156    s.mem = &hdr;
157    s.len = sizeof(hdr);
158 
159    err = efl_io_writer_write(dest->client, &s, &r);
160    if (err || r.len) goto end;
161 
162    if (!payload_size) goto end;
163 
164    s.mem = payload;
165    s.len = payload_size;
166    err = efl_io_writer_write(dest->client, &s, &r);
167 
168    INF("Send packet (size = %d, opcode %s) to %s", size,
169          _opcodes[opcode]->opcode_string,
170          dest->app_name);
171 
172  end:
173    if (err)
174      {
175         fprintf(stderr, "ERROR: could not queue message '%d': %s\n", opcode, eina_error_msg_get(err));
176      }
177 
178    if (r.len)
179      {
180         fprintf(stderr, "ERROR: could not queue message '%d': out of memory\n", opcode);
181      }
182 }
183 
184 static Eina_Bool
_dispatch(Client * src,void * buffer)185 _dispatch(Client *src, void *buffer)
186 {
187    Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buffer;
188    if (hdr->cid)
189      {
190         /* If the client id is given, we forward */
191         Client *dest = _client_find_by_cid(hdr->cid);
192         if (dest)
193           {
194              if (dest->is_master != src->is_master)
195                {
196                   Eina_Slice s;
197                   s.mem = buffer;
198                   s.len = hdr->size;
199                   hdr->cid = SWAP_32(src->cid);
200                   hdr->size = SWAP_32(hdr->size);
201                   hdr->opcode = SWAP_32(hdr->opcode);
202                   if (efl_io_writer_write(dest->client, &s, NULL) !=
203                       EINA_ERROR_NO_ERROR)
204                     ERR("Cannot write to client [%s:%i]", dest->app_name, (int)dest->pid);
205                   INF("Transfer of %d bytes from %s(%d) to %s(%d): operation %s\n",
206                         hdr->size,
207                         src->app_name, src->pid,
208                         dest->app_name, dest->pid,
209                         _opcodes[hdr->opcode]->opcode_string);
210                }
211              else
212                {
213                   /*
214                    * Packets Master -> Master or Slave -> Slave are forbidden
215                    * Only Master <-> Slave packets are allowed.
216                    */
217                   ERR("Packet from %d to %d: denied (same type)\n", hdr->cid, dest->cid);
218                }
219           }
220      }
221    else
222      {
223         INF("Invoke %s\n", _opcodes[hdr->opcode]->opcode_string);
224         if (_opcodes[hdr->opcode]->cb)
225            return _opcodes[hdr->opcode]->cb(src,
226                  (char *)buffer + sizeof(Eina_Debug_Packet_Header),
227                  hdr->size - sizeof(Eina_Debug_Packet_Header));
228      }
229    return EINA_TRUE;
230 }
231 
232 static int
_opcode_register(const char * op_name,int op_id,Opcode_Cb cb)233 _opcode_register(const char *op_name, int op_id, Opcode_Cb cb)
234 {
235    static int free_opcode = 0;
236    Opcode_Information *op_info = eina_hash_find(_string_to_opcode_hash, op_name);
237    if (!op_info)
238      {
239         op_info = calloc(1, sizeof(*op_info));
240         if (op_id == EINA_DEBUG_OPCODE_INVALID)
241           {
242              do
243                {
244                   free_opcode = (free_opcode + 1) % MAX_OPCODES;
245                   op_id = free_opcode;
246                }
247              while(_opcodes[op_id]);
248           }
249         op_info->opcode = op_id;
250         op_info->opcode_string = eina_stringshare_add(op_name);
251         op_info->cb = cb;
252         eina_hash_add(_string_to_opcode_hash, op_name, op_info);
253         _opcodes[op_id] = op_info;
254      }
255    INF("Register %s -> opcode %d\n", op_name, op_info->opcode);
256    return op_info->opcode;
257 }
258 
259 static Eina_Bool
_hello_cb(Client * c,void * buffer,int size)260 _hello_cb(Client *c, void *buffer, int size)
261 {
262    Eina_List *itr;
263    char *buf = (char *)buffer, *tmp;
264    int version, pid, cid;
265 
266    EXTRACT(buf, &version, 4);
267    EXTRACT(buf, &pid, 4);
268    c->version = SWAP_32(version);
269    c->pid = SWAP_32(pid);
270    size -= 8;
271 
272    c->cid = _free_cid++;
273    cid = SWAP_32(c->cid);
274    if (size > 1)
275      {
276         c->app_name = eina_stringshare_add_length(buf, size);
277      }
278    INF("Connection of %s: pid %d - name %s -> cid %d\n",
279          c->is_master ? "Master" : "Slave",
280          c->pid, c->app_name, c->cid);
281 
282    if (c->is_master) return EINA_TRUE;
283 
284    /* Update the observers */
285    size = 2 * sizeof(int) + (c->app_name ? strlen(c->app_name) : 0) + 1; /* cid + pid + name + \0 */
286    buf = alloca(size);
287    tmp = buf;
288    STORE(tmp, &cid, sizeof(int));
289    STORE(tmp, &pid, sizeof(int));
290    if (c->app_name)
291      {
292         STORE(tmp, c->app_name, strlen(c->app_name) + 1);
293      }
294    else
295      {
296         char end = '\0';
297         STORE(tmp, &end, 1);
298      }
299    EINA_LIST_FOREACH(_clients, itr, c)
300      {
301         if (c->cl_stat_obs) _send(c, _slave_added_opcode, buf, size);
302      }
303    return EINA_TRUE;
304 }
305 
306 static Eina_Bool
_cid_get_cb(Client * src,void * buffer,int size EINA_UNUSED)307 _cid_get_cb(Client *src, void *buffer, int size EINA_UNUSED)
308 {
309    int pid = SWAP_32(*(int *)buffer);
310    Client *c = _client_find_by_pid(pid);
311    int cid = c ? SWAP_32(c->cid) : 0;
312    _send(src, _cid_from_pid_opcode, &cid, sizeof(int));
313    return EINA_TRUE;
314 }
315 
316 static Eina_Bool
_data_test_cb(Client * src,void * buffer,int size)317 _data_test_cb(Client *src, void *buffer, int size)
318 {
319    DBG("Data test: loop packet of %d bytes\n", size);
320    _send(src, _test_loop_opcode, buffer, size);
321    return EINA_TRUE;
322 }
323 
324 static Eina_Bool
_cl_stat_obs_register_cb(Client * src,void * buffer,int size)325 _cl_stat_obs_register_cb(Client *src, void *buffer, int size)
326 {
327    Client *c;
328    if (!src) return EINA_FALSE;
329    if (!src->is_master) return EINA_FALSE;
330    if (!src->cl_stat_obs)
331      {
332         Eina_List *itr;
333         src->cl_stat_obs = EINA_TRUE;
334         size = 0;
335         EINA_LIST_FOREACH(_clients, itr, c)
336           {
337              char *tmp;
338              int cid, pid;
339              if (c->is_master) continue;
340              size = 2 * sizeof(int) + (c->app_name ? strlen(c->app_name) : 0) + 1;
341              buffer = alloca(size);
342              tmp = buffer;
343              cid = SWAP_32(c->cid);
344              pid = SWAP_32(c->pid);
345              STORE(tmp, &cid, sizeof(int));
346              STORE(tmp, &pid, sizeof(int));
347              if (c->app_name)
348                {
349                   STORE(tmp, c->app_name, strlen(c->app_name) + 1);
350                }
351              else
352                {
353                   char end = '\0';
354                   STORE(tmp, &end, 1);
355                }
356              _send(src, _slave_added_opcode, buffer, size);
357           }
358      }
359    return EINA_TRUE;
360 }
361 
362 static Eina_Bool
_opcode_register_cb(Client * src,void * buffer,int size)363 _opcode_register_cb(Client *src, void *buffer, int size)
364 {
365    char *buf = (char *)buffer;
366    char *ops_buf = buf;
367    int ops_size = size;
368 
369    ops_buf += sizeof(uint64_t);
370    ops_size -= sizeof(uint64_t);
371    int *opcodes = (int *)ops_buf;
372 
373    while (ops_size > 0)
374      {
375         int len = strlen(ops_buf) + 1;
376         *opcodes++ = SWAP_32(_opcode_register(ops_buf, EINA_DEBUG_OPCODE_INVALID, NULL));
377         ops_buf += len;
378         ops_size -= len;
379      }
380 
381    _send(src, EINA_DEBUG_OPCODE_REGISTER, buf, (char *)opcodes - (char *)buf);
382 
383    return EINA_TRUE;
384 }
385 
386 static void
_client_data(void * data,const Efl_Event * event)387 _client_data(void *data, const Efl_Event *event)
388 {
389    static unsigned char *buffer = NULL;
390    unsigned int size = 0;
391    Eina_Debug_Packet_Header *hdr;
392    Client *c = data;
393    Eina_Slice slice;
394 
395    if (!c) return;
396 
397    if (!buffer) buffer = malloc(EINA_DEBUG_MAX_PACKET_SIZE);
398 
399    slice = efl_io_buffered_stream_slice_get(c->client);
400 
401    if (slice.len < sizeof(*hdr)) return;
402 
403    hdr = (Eina_Debug_Packet_Header *)slice.mem;
404    size = SWAP_32(hdr->size);
405    if (size < sizeof(*hdr)) /* must contain at least the header */
406      {
407         fprintf(stderr, "ERROR: invalid message header, size=%u\n", hdr->size);
408         goto err;
409      }
410 
411    if (size > EINA_DEBUG_MAX_PACKET_SIZE)
412      {
413         fprintf(stderr, "ERROR: packet too big (max: %d), size=%u\n",
414               EINA_DEBUG_MAX_PACKET_SIZE, hdr->size);
415         goto err;
416      }
417 
418    /* Incomplete packet: need to wait */
419    if (size > slice.len) return;
420 
421    memcpy(buffer, slice.mem, size);
422    hdr = (Eina_Debug_Packet_Header *)buffer;
423    hdr->size = SWAP_32(hdr->size);
424    hdr->opcode = SWAP_32(hdr->opcode);
425    hdr->cid = SWAP_32(hdr->cid);
426 
427    if(!_dispatch(c, buffer))
428      {
429         // something we don't understand
430         fprintf(stderr, "Dispatch: unknown command: %d\n", hdr->opcode);
431      }
432    efl_io_buffered_stream_discard(c->client, size);
433    return;
434 err:
435    if (!efl_io_closer_closed_get(event->object))
436       efl_io_closer_close(event->object);
437    fprintf(stderr, "INFO: client %p [pid: %d] sent invalid data\n", c, (int)c->pid);
438 }
439 
440 static void
_client_error(void * data,const Efl_Event * event)441 _client_error(void *data, const Efl_Event *event)
442 {
443    Client *c = data;
444    Eina_Error *perr = event->info;
445    WRN("client %p [pid: %d] error: %s",
446        c, (int)c->pid, eina_error_msg_get(*perr));
447    fprintf(stderr, "INFO: client %p [pid: %d] error: %s\n",
448            c, (int)c->pid, eina_error_msg_get(*perr));
449 }
450 
451 static void
_client_eos(void * data,const Efl_Event * event EINA_UNUSED)452 _client_eos(void *data, const Efl_Event *event EINA_UNUSED)
453 {
454    Client *c = data;
455    DBG("client %p (%p) [pid: %d] closed, pending read %zu, write %zu",
456        c, c->client, (int)c->pid,
457        efl_io_buffered_stream_pending_read_get(c->client),
458        efl_io_buffered_stream_pending_write_get(c->client));
459    efl_io_closer_close(c->client);
460 }
461 
462 static void
_client_write_finished(void * data,const Efl_Event * event EINA_UNUSED)463 _client_write_finished(void *data, const Efl_Event *event EINA_UNUSED)
464 {
465    Client *c = data;
466    DBG("client %p (%p) [pid: %d] finished writing, pending read %zu",
467        c, c->client, (int)c->pid, efl_io_buffered_stream_pending_read_get(c->client));
468 }
469 
470 static void
_client_read_finished(void * data,const Efl_Event * event EINA_UNUSED)471 _client_read_finished(void *data, const Efl_Event *event EINA_UNUSED)
472 {
473    Client *c = data;
474    DBG("client %p (%p) [pid: %d] finished reading, pending write %zu",
475        c, c->client, (int)c->pid, efl_io_buffered_stream_pending_write_get(c->client));
476 }
477 
478 static Efl_Callback_Array_Item *_client_cbs(void);
479 
480 static void
_client_finished(void * data,const Efl_Event * event EINA_UNUSED)481 _client_finished(void *data, const Efl_Event *event EINA_UNUSED)
482 {
483    Eina_List *itr;
484    Client *c = data, *c2;
485    int cid = SWAP_32(c->cid);
486    efl_event_callback_array_del(c->client, _client_cbs(), c);
487    INF("finished client %p (%p) [pid:%d]", c, c->client, c->pid);
488    _clients = eina_list_remove(_clients, c);
489    efl_unref(c->client);
490 
491    /* Don't update the observers if the client is a master */
492    if (c->is_master) return;
493 
494    EINA_LIST_FOREACH(_clients, itr, c2)
495      {
496         if (c2->cl_stat_obs) _send(c2, _slave_deleted_opcode, &cid, sizeof(int));
497      }
498    free(c);
499 }
500 
501 EFL_CALLBACKS_ARRAY_DEFINE(_client_cbs,
502                            { EFL_IO_READER_EVENT_EOS, _client_eos },
503                            { EFL_IO_BUFFERED_STREAM_EVENT_ERROR, _client_error },
504                            { EFL_IO_BUFFERED_STREAM_EVENT_READ_FINISHED, _client_read_finished },
505                            { EFL_IO_BUFFERED_STREAM_EVENT_WRITE_FINISHED, _client_write_finished },
506                            { EFL_IO_BUFFERED_STREAM_EVENT_FINISHED, _client_finished },
507                            { EFL_IO_BUFFERED_STREAM_EVENT_SLICE_CHANGED, _client_data });
508 
509 static void
_client_add(void * data EINA_UNUSED,const Efl_Event * event)510 _client_add(void *data EINA_UNUSED, const Efl_Event *event)
511 {
512    Client *c = calloc(1, sizeof(Client));
513 
514    EINA_SAFETY_ON_NULL_RETURN(c);
515    c->client = efl_ref(event->info);
516    c->is_master = (event->object == _remote_server);
517    _clients = eina_list_append(_clients, c);
518    efl_event_callback_array_add(c->client, _client_cbs(), c);
519    INF("server %p new client %p (%p)", event->object, c, c->client);
520 }
521 
522 static void
_error(void * data EINA_UNUSED,const Efl_Event * event)523 _error(void *data EINA_UNUSED, const Efl_Event *event)
524 {
525    Eina_Error *perr = event->info;
526    ERR("server %p error: %s", event->object, eina_error_msg_get(*perr));
527    fprintf(stderr, "ERROR: %s\n", eina_error_msg_get(*perr));
528    ecore_main_loop_quit();
529    _retval = EXIT_FAILURE;
530 }
531 
532 static Eina_Bool
_local_server_create(void)533 _local_server_create(void)
534 {
535    Eo *loop;
536    Eina_Error err;
537    mode_t mask = 0;
538    char path[512];
539    Eina_Bool ret = EINA_FALSE;
540 
541    eina_vpath_resolve_snprintf(path, sizeof(path), "(:usr.run:)/%s", LOCAL_SERVER_PATH);
542    if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST)
543      {
544         perror("mkdir SERVER_PATH");
545         goto end;
546      }
547    eina_vpath_resolve_snprintf(path, sizeof(path), "(:usr.run:)/%s/%s", LOCAL_SERVER_PATH, LOCAL_SERVER_NAME);
548    if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST)
549      {
550         perror("mkdir SERVER_NAME");
551         goto end;
552      }
553    mask = umask(S_IRWXG | S_IRWXO);
554    eina_vpath_resolve_snprintf(path, sizeof(path) - 1, "(:usr.run:)/%s/%s/%i",
555          LOCAL_SERVER_PATH, LOCAL_SERVER_NAME, LOCAL_SERVER_PORT);
556 
557    loop = efl_main_loop_get();
558 
559 #ifdef EFL_NET_SERVER_UNIX_CLASS
560    _local_server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, loop,
561                     efl_net_server_simple_inner_class_set(efl_added, EFL_NET_SERVER_UNIX_CLASS));
562 #else
563    /* TODO: maybe start a TCP using locahost:12345?
564     * Right now eina_debug_monitor is only for AF_UNIX, so not an issue.
565     */
566    fprintf(stderr, "ERROR: your platform doesn't support Efl.Net.Server.Unix\n");
567 #endif
568    if (!_local_server)
569      {
570         fprintf(stderr, "ERROR: could not create communication server\n");
571         goto end;
572      }
573 
574    efl_event_callback_add(_local_server, EFL_NET_SERVER_EVENT_CLIENT_ADD, _client_add, NULL);
575    efl_event_callback_add(_local_server, EFL_NET_SERVER_EVENT_SERVER_ERROR, _error, NULL);
576 
577 #ifdef EFL_NET_SERVER_UNIX_CLASS
578    {
579       Eo *inner_server = efl_net_server_simple_inner_server_get(_local_server);
580       efl_net_server_unix_leading_directories_create_set(inner_server, EINA_TRUE, 0700);
581    }
582 #endif
583 
584    err = efl_net_server_serve(_local_server, path);
585    if (err)
586      {
587         fprintf(stderr, "ERROR: could not serve '%s': %s\n", path, eina_error_msg_get(err));
588         goto end;
589      }
590    ret = EINA_TRUE;
591 end:
592    umask(mask);
593    if (!ret)
594      {
595         efl_del(_local_server);
596         _local_server = NULL;
597      }
598    return ret;
599 }
600 
601 static Eina_Bool
_remote_server_create(void)602 _remote_server_create(void)
603 {
604    Eo *loop;
605    Eina_Error err;
606    mode_t mask = 0;
607    Eina_Bool ret = EINA_FALSE;
608    char address[256];
609 
610    loop = efl_main_loop_get();
611 
612    _remote_server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, loop,
613                     efl_net_server_simple_inner_class_set(efl_added, EFL_NET_SERVER_TCP_CLASS));
614    if (!_remote_server)
615      {
616         fprintf(stderr, "ERROR: could not create communication server\n");
617         goto end;
618      }
619 
620    {
621       Eo *inner_server = efl_net_server_simple_inner_server_get(_remote_server);
622       efl_net_server_fd_reuse_address_set(inner_server, EINA_TRUE);
623    }
624    efl_event_callback_add(_remote_server, EFL_NET_SERVER_EVENT_CLIENT_ADD, _client_add, NULL);
625    efl_event_callback_add(_remote_server, EFL_NET_SERVER_EVENT_SERVER_ERROR, _error, NULL);
626 
627    sprintf(address, "127.0.0.1:%d", REMOTE_SERVER_PORT);
628    err = efl_net_server_serve(_remote_server, address);
629    if (err)
630      {
631         fprintf(stderr, "ERROR: could not serve port '%d': %s\n",
632               REMOTE_SERVER_PORT, eina_error_msg_get(err));
633         goto end;
634      }
635    ret = EINA_TRUE;
636 end:
637    umask(mask);
638    if (!ret)
639      {
640         efl_del(_remote_server);
641         _remote_server = NULL;
642      }
643    return ret;
644 }
645 
646 static Eina_Bool
_server_launch(void)647 _server_launch(void)
648 {
649    if (_local_server_create() <= 0) goto err;
650    if (_remote_server_create() <= 0) goto err;
651 
652    return EINA_TRUE;
653 err:
654    efl_del(_local_server);
655    efl_del(_remote_server);
656    return EINA_FALSE;
657 }
658 
659 int
main(int argc EINA_UNUSED,char ** argv EINA_UNUSED)660 main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
661 {
662    eina_debug_disable();
663    ecore_app_no_system_modules();
664 
665    eina_init();
666    ecore_init();
667    ecore_con_init();
668 
669    _retval = EXIT_SUCCESS;
670    _log_dom = eina_log_domain_register("efl_debugd", EINA_COLOR_CYAN);
671 
672    _string_to_opcode_hash = eina_hash_string_superfast_new(NULL);
673    _opcode_register("Daemon/opcode_register", EINA_DEBUG_OPCODE_REGISTER, _opcode_register_cb);
674    _opcode_register("Daemon/greet", EINA_DEBUG_OPCODE_HELLO, _hello_cb);
675    _clients_stat_register_opcode = _opcode_register("Daemon/Client/register_observer", EINA_DEBUG_OPCODE_INVALID, _cl_stat_obs_register_cb);
676    _slave_added_opcode = _opcode_register("Daemon/Client/added", EINA_DEBUG_OPCODE_INVALID, NULL);
677    _slave_deleted_opcode = _opcode_register("Daemon/Client/deleted", EINA_DEBUG_OPCODE_INVALID, NULL);
678    _cid_from_pid_opcode = _opcode_register("Daemon/Client/cid_from_pid", EINA_DEBUG_OPCODE_INVALID, _cid_get_cb);
679    _test_loop_opcode = _opcode_register("Test/data_loop", EINA_DEBUG_OPCODE_INVALID, _data_test_cb);
680 
681    if (_server_launch()) ecore_main_loop_begin();
682    else _retval = EXIT_FAILURE;
683 
684    ecore_con_shutdown();
685    ecore_shutdown();
686    eina_shutdown();
687 
688    return _retval;
689 }
690