From 43e02a0f247e2b5f5d4111ac3eb54f94500999e2 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Thu, 20 Apr 2017 16:52:46 +0300 Subject: [PATCH] Move screenshot storing to manager Change-Id: Id31ba8135075c4f265819f4ecb2f3525686f78b1 Signed-off-by: Vyacheslav Cherkashin --- helper/libdaprobe.c | 58 +++++++++++ include/daprobe.h | 1 + probe_screenshot/dacapture_wayland.c | 187 ++++++++++++++++++++++++++++++----- 3 files changed, 219 insertions(+), 27 deletions(-) diff --git a/helper/libdaprobe.c b/helper/libdaprobe.c index 9dec44d..5b56caa 100755 --- a/helper/libdaprobe.c +++ b/helper/libdaprobe.c @@ -630,6 +630,64 @@ const char *msg_code_to_srt(enum AppMessageType type) } } +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +static bool do_send(int fd, void *data, size_t len, int flags) +{ + const size_t CHUNK_SIZE = 1024; + + while (len) { + size_t sz = MIN(len, CHUNK_SIZE); + ssize_t ret = send(fd, data, sz, flags); + + if (ret == -1) { + PRINTERR("Cannot send data, len=%zu, err=%d", + sz, errno); + break; + } else if ((size_t)ret == sz) { + len -= sz; + data += sz; + continue; + } else { + PRINTERR("Cannot send data, len=%zu, send_len=%zu", + sz, ret); + break; + } + } + + return !len; +} + +static void do_msg_send(int fd, enum AppMessageType type, + void *data, size_t len) +{ + struct msg_header { + int type; + int length; + }; + + struct msg_header header = { + .type = type, + .length = len, + }; + + do_send(fd, &header, sizeof(header), MSG_NOSIGNAL); + do_send(fd, data, len, MSG_NOSIGNAL); +} + +void msg_send(enum AppMessageType type, void *data, size_t len) +{ + int fd = gTraceInfo.socket.daemonSock; + pthread_mutex_t *mutex = &gTraceInfo.socket.sockMutex; + + if (fd == -1) + return; + + real_pthread_mutex_lock(mutex); + do_msg_send(fd, type, data, len); + real_pthread_mutex_unlock(mutex); +} + + bool printLog(log_t *log, int msgType) { ssize_t res, len; diff --git a/include/daprobe.h b/include/daprobe.h index 921062f..4cd0c28 100644 --- a/include/daprobe.h +++ b/include/daprobe.h @@ -97,6 +97,7 @@ int update_heap_memory_size(bool isAdd, size_t size); bool print_log_fmt(int msgType, const char *func_name, int line, ...); bool print_log_str(int msgType, char *st); bool printLog(log_t* log, int msgType); +void msg_send(enum AppMessageType type, void *data, size_t len); void *rtdl_next(const char *symname); void *rtld_default(const char *symname); diff --git a/probe_screenshot/dacapture_wayland.c b/probe_screenshot/dacapture_wayland.c index b379ef5..d219905 100755 --- a/probe_screenshot/dacapture_wayland.c +++ b/probe_screenshot/dacapture_wayland.c @@ -44,6 +44,7 @@ #include // for mutex #include // MIN, MAX #include // mmap +#include #include #include @@ -622,6 +623,158 @@ void current_angle_set(int angle) __current_angle = angle; } + +struct file_data { + size_t len; + void *data; +}; + +static size_t fsize(int fd) +{ + struct stat st; + if (fstat(fd, &st) != 0) + return 0; + return st.st_size; +} + +static int do_read_file(int fd, void *data, size_t len) +{ + while (len) { + ssize_t n = read(fd, data, len); + if (n == -1) { + if (errno == EINTR) + continue; + + return -errno; + } else if (n == 0) { + return -EPERM; + } + + len -= n; + data += n; + } + + return 0; +} + +static struct file_data *file_data_create(const char *path) +{ + int fd, ret; + struct file_data *fdata; + const size_t MAX_FILE_SIZE = 32 * 1024 * 1024; + + fdata = malloc(sizeof(*fdata)); + if (!fdata) { + PRINTERR("Out of memory"); + return NULL; + } + + fd = open(path, O_RDONLY); + if (fd == -1) { + PRINTERR("Cannot open '%s', errno=%d", path, fd); + goto free_fdata; + } + + fdata->len = fsize(fd); + if (!fdata->len) { + PRINTERR("Cannot calculate file size, path='%s'", path); + goto close_fd; + } + + if (fdata->len > MAX_FILE_SIZE) { + PRINTERR("file size is very long, len=%zu", fdata->len); + goto close_fd; + } + + fdata->data = malloc(fdata->len); + if (!fdata->data) { + PRINTERR("Out of memory"); + goto close_fd; + } + + ret = do_read_file(fd, fdata->data, fdata->len); + if (ret) { + PRINTERR("Cannot read file, ret=%d", ret); + goto free_data; + } + + close(fd); + return fdata; + +free_data: + free(fdata->data); +close_fd: + close(fd); +free_fdata: + free(fdata); + return NULL; +} + +static void file_data_free(struct file_data *data) +{ + free(data->data); + free(data); +} + + +static size_t screenshot_pack_info(char *buf) +{ + /* pack probe */ + PREPARE_LOCAL_BUF_THOUGH(buf); + PACK_COMMON_BEGIN(MSG_PROBE_SCREENSHOT, API_ID_captureScreen, "", 0); + /* Pack any address, cause this is not an event probe */ + PACK_COMMON_END_THOUGH('d', 0, 0, 0, 0xffffffff); + + return BUF_PTR - LOCAL_BUF; +} + +static int screenshot_send_to_socket(const char *path) +{ + struct file_data *fdata; + char sh_info[256]; + void *buf, *p; + size_t sh_info_len, buf_size; + + fdata = file_data_create(path); + if (!fdata) + return -1; + + /* pack common colums */ + sh_info_len = screenshot_pack_info(sh_info); + + /* format: + * + * | sh_info | | + * +----+------+-------+---------+ + * |len | data | angle | img.png | + * | 4 | ... | 4 | ... | + * + */ + buf_size = 4 + sh_info_len + 4 + fdata->len; + buf = malloc(buf_size); + if (!buf) { + PRINTERR("Out of memory"); + file_data_free(fdata); + return -1; + } + + /* pack sh_info */ + p = pack_int32(buf, sh_info_len); + p = pack_bin(p, sh_info, sh_info_len); + + /* pack angle */ + p = pack_int32(p, current_angle_get()); + + /* pack img.png */ + p = pack_bin(p, fdata->data, fdata->len); + + /* send screenshot to manager */ + msg_send(APP_MSG_IMAGE, buf, buf_size); + file_data_free(fdata); + + return 0; +} + int captureScreen() { static pthread_mutex_t captureScreenLock = PTHREAD_MUTEX_INITIALIZER; @@ -637,35 +790,15 @@ int captureScreen() getCurrentEventIndex()); ret = __capture_screnshot_wayland(dstpath); - if (ret == -EAGAIN) - ret = __capture_screnshot_wayland(dstpath); - if (!ret) { - if (chmod(dstpath, 0777) == -1) - PRINTWRN("cannot chmod -R777 <%s>", dstpath); - - /* welcome to the hell */ - log_t log; - PREPARE_LOCAL_BUF_THOUGH((char *)&log); - - /* skip header */ - LOCAL_BUF += offsetof(log_t, data); - /* pack screenshot name */ - BUF_PTR = pack_string(LOCAL_BUF, dstpath); /* file name */ - LOCAL_BUF = BUF_PTR; - - /* pack probe */ - PACK_COMMON_BEGIN(MSG_PROBE_SCREENSHOT, API_ID_captureScreen, "", 0); - /* Pack any address, cause this is not an event probe */ - PACK_COMMON_END_THOUGH('d', 0, 0, 0, 0xffffffff); - PACK_SCREENSHOT(dstpath, current_angle_get()); - SET_MSG_LEN(); - log.length = GET_MSG_LEN() + MSG_HDR_LEN + strlen(dstpath) + 1; - - /* send all message */ - printLog(&log, APP_MSG_IMAGE); - ret = 0; + if (ret) { + PRINTERR("Cannot capture screenshot, ret=%d", ret); + goto unlock; } + ret = screenshot_send_to_socket(dstpath); + remove(dstpath); + +unlock: pthread_mutex_unlock(&captureScreenLock); return ret; } -- 2.7.4