diff --git a/legacy/evas/src/bin/Makefile.am b/legacy/evas/src/bin/Makefile.am index 0a2d6ef9c8..6cddccd64d 100644 --- a/legacy/evas/src/bin/Makefile.am +++ b/legacy/evas/src/bin/Makefile.am @@ -45,7 +45,7 @@ if EVAS_CSERVE2 SUBDIRS = loaders libexec_PROGRAMS = evas_cserve2 evas_cserve2_slave dummy_slave -bin_PROGRAMS = evas_cserve2_client evas_cserve2_usage +bin_PROGRAMS = evas_cserve2_client evas_cserve2_usage evas_cserve2_debug AM_CPPFLAGS = \ -I. \ @@ -86,9 +86,15 @@ evas_cserve2_client.c evas_cserve2_usage_SOURCES = \ evas_cserve2_usage.c +evas_cserve2_debug_SOURCES = \ +evas_cserve2_debug.c + evas_cserve2_usage_LDADD = \ @EINA_LIBS@ +evas_cserve2_debug_LDADD = \ +@EINA_LIBS@ + evas_cserve2_slave_SOURCES = \ evas_cserve2_slave.c \ evas_cserve2_utils.c diff --git a/legacy/evas/src/bin/evas_cserve2_debug.c b/legacy/evas/src/bin/evas_cserve2_debug.c new file mode 100644 index 0000000000..c86045c641 --- /dev/null +++ b/legacy/evas/src/bin/evas_cserve2_debug.c @@ -0,0 +1,451 @@ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "evas_cs2.h" + +static int socketfd = -1; +static unsigned int _rid_count = 1; +static int _evas_cserve2_debug_log_dom = -1; + +static struct sockaddr_un socksize; +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX sizeof(socksize.sun_path) +#endif + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_evas_cserve2_debug_log_dom, __VA_ARGS__) +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_evas_cserve2_debug_log_dom, __VA_ARGS__) +#ifdef WRN +#undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(_evas_cserve2_debug_log_dom, __VA_ARGS__) +#ifdef INF +#undef INF +#endif +#define INF(...) EINA_LOG_DOM_INFO(_evas_cserve2_debug_log_dom, __VA_ARGS__) + +static void +_socket_path_set(char *path) +{ + char *env; + char buf[UNIX_PATH_MAX]; + + env = getenv("EVAS_CSERVE2_SOCKET"); + if (env && env[0]) + { + strncpy(path, env, UNIX_PATH_MAX - 1); + return; + } + + snprintf(buf, sizeof(buf), "/tmp/.evas-cserve2-%x.socket", (int)getuid()); + /* FIXME: check we can actually create this socket */ + strcpy(path, buf); +} + +static Eina_Bool +_server_connect(void) +{ + int s, len; + struct sockaddr_un remote; + + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + { + ERR("socket"); + return EINA_FALSE; + } + + remote.sun_family = AF_UNIX; + _socket_path_set(remote.sun_path); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + if (connect(s, (struct sockaddr *)&remote, len) == -1) + { + ERR("connect"); + return EINA_FALSE; + } + + fcntl(s, F_SETFL, O_NONBLOCK); + + socketfd = s; + + DBG("connected to cserve2 server."); + return EINA_TRUE; +} + +static void +_server_disconnect(void) +{ + close(socketfd); + socketfd = -1; +} + +static Eina_Bool +_server_send(const void *data, int size) +{ + int sent = 0; + ssize_t ret; + const char *msg = data; + + while (sent < size) + { + ret = send(socketfd, msg + sent, size - sent, MSG_NOSIGNAL); + if (ret < 0) + { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + return EINA_FALSE; + } + sent += ret; + } + + return EINA_TRUE; +} + +static int sr_size = 0; +static int sr_got = 0; +static char *sr_buf = NULL; + +static void * +_server_read(int *size) +{ + int n; + void *ret; + + if (sr_size) + goto get_data; + + n = recv(socketfd, &sr_size, sizeof(sr_size), 0); + if (n < 0) + return NULL; + + sr_buf = malloc(sr_size); + +get_data: + n = recv(socketfd, sr_buf + sr_got, sr_size - sr_got, 0); + if (n < 0) + return NULL; + + sr_got += n; + if (sr_got < sr_size) + return NULL; + + *size = sr_size; + sr_size = 0; + sr_got = 0; + ret = sr_buf; + sr_buf = NULL; + + return ret; +} + +static void +_debug_msg_send(void) +{ + Msg_Base msg; + int size; + + memset(&msg, 0, sizeof(msg)); + msg.type = CSERVE2_FONT_DEBUG; + msg.rid = _rid_count++; + + size = sizeof(msg); + + if (!_server_send(&size, sizeof(size))) + { + ERR("Could not send usage msg size to server."); + return; + } + if (!_server_send(&msg, size)) + { + ERR("Could not send usage msg body to server."); + return; + } +} + +typedef struct _Font_Entry Font_Entry; +typedef struct _Cache_Entry Cache_Entry; +typedef struct _Glyph_Entry Glyph_Entry; + +struct _Font_Entry +{ + const char *file; + const char *name; + unsigned int rend_flags; + unsigned int size; + unsigned int dpi; + unsigned int unused; + Eina_List *caches; +}; + +struct _Cache_Entry +{ + const char *shmname; + unsigned int size; + unsigned int usage; + Eina_List *glyphs; +}; + +struct _Glyph_Entry +{ + unsigned int index; + unsigned int offset; + unsigned int size; + unsigned int rows; + unsigned int width; + unsigned int pitch; + unsigned int num_grays; + unsigned int pixel_mode; +}; + +#define READIT(_dst, _src) \ + do { \ + memcpy(&_dst, _src, sizeof(_dst)); \ + _src += sizeof(_dst); \ + } while(0) + +static Glyph_Entry * +_parse_glyph_entry(char **msg) +{ + Glyph_Entry *ge; + char *buf = *msg; + + ge = calloc(1, sizeof(*ge)); + + READIT(ge->index, buf); + READIT(ge->offset, buf); + READIT(ge->size, buf); + READIT(ge->rows, buf); + READIT(ge->width, buf); + READIT(ge->pitch, buf); + READIT(ge->num_grays, buf); + READIT(ge->pixel_mode, buf); + + *msg = buf; + + return ge; +} + +static Cache_Entry * +_parse_cache_entry(char **msg) +{ + Cache_Entry *ce; + char *buf = *msg; + unsigned int n; + + ce = calloc(1, sizeof(*ce)); + + READIT(n, buf); + ce->shmname = eina_stringshare_add_length(buf, n); + buf += n; + + READIT(ce->size, buf); + READIT(ce->usage, buf); + + READIT(n, buf); + while (n--) + { + Glyph_Entry *ge; + ge = _parse_glyph_entry(&buf); + ce->glyphs = eina_list_append(ce->glyphs, ge); + } + + *msg = buf; + + return ce; +} + +static Font_Entry * +_parse_font_entry(char **msg) +{ + Font_Entry *fe; + char *buf = *msg; + unsigned int n; + + fe = calloc(1, sizeof(*fe)); + + READIT(n, buf); + if (n) + fe->file = eina_stringshare_add_length(buf, n); + buf += n; + READIT(n, buf); + if (n) + fe->name = eina_stringshare_add_length(buf, n); + buf += n; + + READIT(fe->rend_flags, buf); + READIT(fe->size, buf); + READIT(fe->dpi, buf); + READIT(fe->unused, buf); + + READIT(n, buf); + while (n--) + { + Cache_Entry *ce; + ce = _parse_cache_entry(&buf); + fe->caches = eina_list_append(fe->caches, ce); + } + + *msg = buf; + + return fe; +} + +static Eina_List * +_debug_msg_read(void) +{ + Msg_Base *msg = NULL; + char *buf; + int size; + unsigned int nfonts; + Eina_List *fonts = NULL; + + printf("Requesting server debug info.\n\n"); + while (!msg) + msg = _server_read(&size); + + if (msg->type != CSERVE2_FONT_DEBUG) + { + ERR("Invalid message received from server." + "Something went badly wrong."); + return NULL; + } + + buf = (char *)msg + sizeof(*msg); + + READIT(nfonts, buf); + while (nfonts--) + { + Font_Entry *fe; + fe = _parse_font_entry(&buf); + fonts = eina_list_append(fonts, fe); + } + + return fonts; +} + +static void +_glyph_entry_free(Glyph_Entry *ge) +{ + free(ge); +} + +static void +_cache_entry_free(Cache_Entry *ce) +{ + Glyph_Entry *ge; + + EINA_LIST_FREE(ce->glyphs, ge) + _glyph_entry_free(ge); + + eina_stringshare_del(ce->shmname); + free(ce); +} + +static void +_font_entry_free(Font_Entry *fe) +{ + Cache_Entry *ce; + + EINA_LIST_FREE(fe->caches, ce) + _cache_entry_free(ce); + + eina_stringshare_del(fe->name); + eina_stringshare_del(fe->file); + free(fe); +} + +static void +_glyph_entry_print(Glyph_Entry *ge) +{ + const char *pxmode[] = { + "FT_PIXEL_MODE_NONE", + "FT_PIXEL_MODE_MONO", + "FT_PIXEL_MODE_GRAY", + "FT_PIXEL_MODE_GRAY2", + "FT_PIXEL_MODE_GRAY4", + "FT_PIXEL_MODE_LCD", + "FT_PIXEL_MODE_LCD_V" + }; + printf("\t\tGLYPH %u offset: %u size: %u %ux%u pitch: %u grays: %u " + "pixel mode: %s\n", + ge->index, ge->offset, ge->size, ge->width, ge->rows, ge->pitch, + ge->num_grays, pxmode[ge->pixel_mode]); +} + +static void +_cache_entry_print(Cache_Entry *ce) +{ + Eina_List *l; + Glyph_Entry *ge; + + printf("\tSHM %s used %u/%u\n", ce->shmname, ce->usage, ce->size); + + EINA_LIST_FOREACH(ce->glyphs, l, ge) + _glyph_entry_print(ge); +} + +static void +_font_entry_print(Font_Entry *fe) +{ + Eina_List *l; + Cache_Entry *ce; + + printf("FONT %s:%s size: %u dpi: %u %s%s%s %s\n", + fe->file, fe->name, fe->size, fe->dpi, + fe->rend_flags == 0 ? "REGULAR " : "", + fe->rend_flags & 1 ? "SLANT " : "", + fe->rend_flags & 2 ? "WEIGHT" : "", + fe->unused ? "(unused)" : ""); + + EINA_LIST_FOREACH(fe->caches, l, ce) + _cache_entry_print(ce); + + putchar('\n'); +} + +int +main(void) +{ + Eina_List *fonts; + Font_Entry *fe; + + eina_init(); + + _evas_cserve2_debug_log_dom = eina_log_domain_register + ("evas_cserve2_debug", EINA_COLOR_BLUE); + + if (!_server_connect()) + { + ERR("Could not connect to server."); + return -1; + } + + _debug_msg_send(); + + fonts = _debug_msg_read(); + + EINA_LIST_FREE(fonts, fe) + { + _font_entry_print(fe); + _font_entry_free(fe); + } + + _server_disconnect(); + + eina_shutdown(); +}