static Ecore_Con_Server *svr;
static void
-_proto(unsigned char *d, unsigned int size)
+_do(char *op, unsigned char *d, int size)
{
- if (size >= 4)
+ if (!strcmp(op, "CLST"))
{
- char *cmd = (char *)d;
+ int i, n;
- if (!strncmp(cmd, "CLST", 4))
+ n = (size) / sizeof(int);
+ if (n < 10000)
{
- int i, n;
-
- n = (size - 4) / sizeof(int);
- if (n < 10000)
+ int *pids = malloc(n * sizeof(int));
+ if (pids)
{
- int *pids = malloc(n * sizeof(int));
- memcpy(pids, d + 4, n * sizeof(int));
+ memcpy(pids, d, n * sizeof(int));
for (i = 0; i < n; i++)
{
if (pids[i] > 0) printf("%i\n", pids[i]);
free(pids);
}
}
- if ((expect) && (!strncmp(cmd, expect, 4)))
- ecore_main_loop_quit();
- }
-}
-
-
-static Eina_Bool
-_server_proto(void)
-{
- unsigned int size, newsize;
- unsigned char *b;
- if (!buf) return EINA_FALSE;
- if (buf_size < 4) return EINA_FALSE;
- memcpy(&size, buf, 4);
- if (buf_size < (size + 4)) return EINA_FALSE;
- _proto(buf + 4, size);
- newsize = buf_size - (size + 4);
- if (buf_size == newsize)
- {
- free(buf);
- buf = NULL;
- buf_size = 0;
- }
- else
- {
- b = malloc(newsize);
- memcpy(b, buf + size + 4, newsize);
- free(buf);
- buf = b;
- buf_size = newsize;
}
- return EINA_TRUE;
+ if ((expect) && (!strcmp(op, expect))) ecore_main_loop_quit();
}
Eina_Bool
-_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev)
+_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev EINA_UNUSED)
{
int i;
for (i = 1; i < my_argc; i++)
{
if (!strcmp(my_argv[i], "list"))
{
- unsigned int size = 4;
- char *head = "LIST";
+ send_svr(svr, "LIST", NULL, 0);
expect = "CLST";
- ecore_con_server_send(svr, &size, 4);
- ecore_con_server_send(svr, head, 4);
+ printf("send... expect %s\n", expect);
}
else if ((!strcmp(my_argv[i], "pon")) &&
(i < (my_argc - 2)))
{
- unsigned int size = 12;
- char *head = "PLON";
+ unsigned char buf[8];
int pid = atoi(my_argv[i + 1]);
unsigned int freq = atoi(my_argv[i + 2]);
- i++;
- ecore_con_server_send(svr, &size, 4);
- ecore_con_server_send(svr, head, 4);
- ecore_con_server_send(svr, &pid, 4);
- ecore_con_server_send(svr, &freq, 4);
+ i += 2;
+ store_val(buf, 0, pid);
+ store_val(buf, 4, freq);
+ send_svr(svr, "PLON", buf, sizeof(buf));
ecore_main_loop_quit();
}
else if ((!strcmp(my_argv[i], "poff")) &&
(i < (my_argc - 1)))
{
- unsigned int size = 8;
- char *head = "PLOFF";
+ unsigned char buf[4];
int pid = atoi(my_argv[i + 1]);
i++;
- ecore_con_server_send(svr, &size, 4);
- ecore_con_server_send(svr, head, 4);
- ecore_con_server_send(svr, &pid, 4);
+ store_val(buf, 0, pid);
+ send_svr(svr, "PLOF", buf, sizeof(buf));
ecore_main_loop_quit();
}
}
}
Eina_Bool
-_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev)
+_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev EINA_UNUSED)
{
ecore_main_loop_quit();
return ECORE_CALLBACK_RENEW;
static Eina_Bool
_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Data *ev)
{
- if (!buf)
- {
- buf = malloc(ev->size);
- if (buf)
- {
- buf_size = ev->size;
- memcpy(buf, ev->data, ev->size);
- }
- }
- else
+ char op[5];
+ unsigned char *d = NULL;
+ int size;
+
+ _protocol_collect(&(buf), &(buf_size), ev->data, ev->size);
+ while ((size = _proto_read(&(buf), &(buf_size), op, &d)) >= 0)
{
- unsigned char *b = realloc(buf, buf_size + ev->size);
- if (b)
- {
- buf = b;
- memcpy(buf + buf_size, ev->data, ev->size);
- buf_size += ev->size;
- }
+ _do(op, d, size);
+ free(d);
+ d = NULL;
}
- while (_server_proto());
return ECORE_CALLBACK_RENEW;
}
svr = ecore_con_server_connect(ECORE_CON_LOCAL_USER, "efl_debug", 0, NULL);
if (!svr)
{
- fprintf(stderr, "ERROR: Cannot connetc to debug daemon.\n");
+ fprintf(stderr, "ERROR: Cannot connect to debug daemon.\n");
return -1;
}
#include "efl_debug_common.h"
+
+void
+_protocol_collect(unsigned char **buf, unsigned int *buf_size,
+ void *data, int size)
+{
+ // no buffer yet - duplicate it as out only data
+ if (!*buf)
+ {
+ *buf = malloc(size);
+ if (*buf)
+ {
+ *buf_size = size;
+ memcpy(*buf, data, size);
+ }
+ }
+ // we have data - append to the buffer and reallocate it as needed
+ else
+ {
+ unsigned char *b = realloc(*buf, *buf_size + size);
+ if (b)
+ {
+ *buf = b;
+ memcpy(*buf + *buf_size, data, size);
+ *buf_size += size;
+ }
+ }
+}
+
+int
+_proto_read(unsigned char **buf, unsigned int *buf_size,
+ char *op, unsigned char **data)
+{
+ unsigned int size, new_buf_size;
+ unsigned char *b;
+
+ // we have no data yet, or not enough - minimum 8 bytes
+ if (!*buf) return -1;
+ if (*buf_size < 8) return -1;
+ // get size of total message
+ memcpy(&size, *buf, 4);
+ // if size is invalid < 4 bytes - no message there
+ if (size < 4) return -1;
+ // if our total message buffer size is not big enough yet - no message
+ if (*buf_size < (size + 4)) return -1;
+
+ // copy out 4 byte opcode and nul byet terminate it
+ memcpy(op, *buf + 4, 4);
+ op[4] = 0;
+
+ // take off opcode header of 4 bytes
+ size -= 4;
+ // the new buffer size once we remove header+payload is...
+ new_buf_size = *buf_size - (size + 8);
+ if (size == 0)
+ {
+ *data = NULL;
+ size = 0;
+ }
+ else
+ {
+ // allocate new space for payload
+ *data = malloc(size);
+ if (!*data)
+ {
+ // allocation faild - no message
+ return -1;
+ }
+ memcpy(*data, *buf + 8, size);
+ }
+ // if new shrunk buffer size is empty -= just simply free buffer
+ if (new_buf_size == 0)
+ {
+ free(*buf);
+ *buf = NULL;
+ }
+ else
+ {
+ // allocate newly shrunk buffer
+ b = malloc(new_buf_size);
+ if (!b)
+ {
+ // alloc failure - bad. fail proto read then
+ free(*data);
+ return -1;
+ }
+ // copy data to new smaller buffer and free old, storing new buffer
+ memcpy(b, *buf + size + 8, new_buf_size);
+ free(*buf);
+ *buf = b;
+ }
+ // store new buffer size
+ *buf_size = new_buf_size;
+ return (int)size;
+}
#include <unistd.h>
#include <string.h>
+void _protocol_collect(unsigned char **buf, unsigned int *buf_size,
+ void *data, int size);
+int _proto_read(unsigned char **buf, unsigned int *buf_size,
+ char *op, unsigned char **data);
+
+#define fetch_val(dst, buf, off) \
+ memcpy(&dst, ((unsigned char *)buf) + off, sizeof(dst))
+#define store_val(buf, off, src) \
+ memcpy(buf + off, &src, sizeof(src))
+#define send_svr(svr, op, data, size) \
+ do { \
+ unsigned char head[8]; \
+ char *op2 = op; \
+ int size2 = size + 4; \
+ memcpy(head + 0, &size2, 4); \
+ memcpy(head + 4, op2, 4); \
+ ecore_con_server_send(svr, head, 8); \
+ if (size > 0) ecore_con_server_send(svr, data, size); \
+ } while (0)
+#define send_cli(cli, op, data, size) \
+ do { \
+ unsigned char head[8]; \
+ char *op2 = op; \
+ int size2 = size + 4; \
+ memcpy(head + 0, &size2, 4); \
+ memcpy(head + 4, op2, 4); \
+ ecore_con_client_send(cli, head, 8); \
+ if (size > 0) ecore_con_client_send(cli, data, size); \
+ } while (0)
+
#endif
struct _Client
{
Ecore_Con_Client *client;
- int version;
- pid_t pid;
- unsigned char *buf;
- unsigned int buf_size;
+ unsigned char *buf;
+ unsigned int buf_size;
+
+ 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 void
-_proto(Client *c, unsigned char *d, unsigned int size)
+_do(Client *c, char *op, unsigned char *d, int size)
{
- if (size >= 4)
+ Client *c2;
+ Eina_List *l;
+
+ if ((!strcmp(op, "HELO")) && (size >= 8))
{
- char *cmd = (char *)d;
+ int version;
+ int pid;
- if (!strncmp(cmd, "HELO", 4))
+ 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 version;
- int pid;
+ int i = 0;
- memcpy(&version, d + 4, 4);
- memcpy(&pid, d + 8, 4);
- c->version = version;
- c->pid = pid;
- }
- else if (!strncmp(cmd, "LIST", 4))
- {
- int n = eina_list_count(clients), i;
- unsigned int *pids, size2;
- Client *c2;
- Eina_List *l;
- char *head = "CLST";
-
- pids = malloc(n * sizeof(int));
- i = 0;
- size2 = 4 + (n * sizeof(int));
EINA_LIST_FOREACH(clients, l, c2)
{
pids[i] = c2->pid;
i++;
}
- ecore_con_client_send(c->client, &size2, 4);
- ecore_con_client_send(c->client, head, 4);
- ecore_con_client_send(c->client, pids, n * sizeof(int));
+ send_cli(c->client, "CLST", pids, n * sizeof(int));
free(pids);
}
- else if (!strncmp(cmd, "PLON", 4))
- {
- int pid;
- unsigned int freq = 1000;
- Client *c2;
- Eina_List *l;
-
- memcpy(&pid, d + 4, 4);
- memcpy(&freq, d + 8, 4);
- if (pid > 0)
- {
- EINA_LIST_FOREACH(clients, l, c2)
- {
- if (c2->pid == pid)
- {
- unsigned int size2 = 8;
-
- ecore_con_client_send(c2->client, &size2, 4);
- ecore_con_client_send(c2->client, d, 4);
- ecore_con_client_send(c2->client, &freq, 4);
- break;
- }
- }
- }
- }
- else if (!strncmp(cmd, "PLOF", 4))
- {
- int pid;
- Client *c2;
- Eina_List *l;
-
- memcpy(&pid, d + 4, 4);
- if (pid > 0)
- {
- EINA_LIST_FOREACH(clients, l, c2)
- {
- if (c2->pid == pid)
- {
- unsigned int size2 = 4;
-
- ecore_con_client_send(c2->client, &size2, 4);
- ecore_con_client_send(c2->client, d, 4);
- break;
- }
- }
- }
- }
}
-}
-
-static Eina_Bool
-_client_proto(Client *c)
-{
- unsigned int size, newsize;
- unsigned char *b;
- if (!c->buf) return EINA_FALSE;
- if (c->buf_size < 4) return EINA_FALSE;
- memcpy(&size, c->buf, 4);
- if (c->buf_size < (size + 4)) return EINA_FALSE;
- _proto(c, c->buf + 4, size);
- newsize = c->buf_size - (size + 4);
- if (c->buf_size == newsize)
+ else if ((!strcmp(op, "PLON")) && (size >= 8))
{
- free(c->buf);
- c->buf = NULL;
- c->buf_size = 0;
+ 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
+ else if (!strcmp(op, "PLOF"))
{
- b = malloc(newsize);
- memcpy(b, c->buf + size + 4, newsize);
- free(c->buf);
- c->buf = b;
- c->buf_size = newsize;
+ int pid;
+ fetch_val(pid, d, 0);
+ if ((c2 = _client_pid_find(pid)))
+ {
+ send_cli(c2->client, "PLOF", NULL, 0);
+ }
}
- return EINA_TRUE;
}
static Eina_Bool
Client *c = ecore_con_client_data_get(ev->client);
if (c)
{
- if (!c->buf)
- {
- c->buf = malloc(ev->size);
- if (c->buf)
- {
- c->buf_size = ev->size;
- memcpy(c->buf, ev->data, ev->size);
- }
- }
- else
+ 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)
{
- unsigned char *b = realloc(c->buf, c->buf_size + ev->size);
- if (b)
- {
- c->buf = b;
- memcpy(c->buf + c->buf_size, ev->data, ev->size);
- c->buf_size += ev->size;
- }
+ _do(c, op, d, size);
+ free(d);
+ d = NULL;
}
- while (_client_proto(c));
}
return ECORE_CALLBACK_RENEW;
}