diff options
author | Anatolii Nikulin <nikulin.a@samsung.com> | 2016-09-08 12:50:12 +0300 |
---|---|---|
committer | Anatolii Nikulin <nikulin.a@samsung.com> | 2016-10-14 16:53:39 +0300 |
commit | 2d7bfd1ecf5a77a0ab815a05d5d2629566f1cb07 (patch) | |
tree | b4b75ac20904f5c446271b7c639dd771059ce5ad | |
parent | 74568764618eb821cd43a9494d0011c8828cd4eb (diff) | |
download | swap-manager-2d7bfd1ecf5a77a0ab815a05d5d2629566f1cb07.tar.gz swap-manager-2d7bfd1ecf5a77a0ab815a05d5d2629566f1cb07.tar.bz2 swap-manager-2d7bfd1ecf5a77a0ab815a05d5d2629566f1cb07.zip |
Rework WSI
Replace webkit by libchromium, add function to get websoket ID,
update to new libwebsocket API
Change-Id: I2ab20fe23fb04114a42649ba901693de8a6cd38a
Signed-off-by: Anatolii Nikulin <nikulin.a@samsung.com>
-rw-r--r-- | daemon/Makefile | 2 | ||||
-rw-r--r-- | daemon/wsi.c | 247 | ||||
-rw-r--r-- | packaging/swap-manager.spec | 9 | ||||
-rwxr-xr-x | scripts/gen_wsi_prof.sh | 17 |
4 files changed, 205 insertions, 70 deletions
diff --git a/daemon/Makefile b/daemon/Makefile index fb3e9db..c89ea11 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -190,7 +190,7 @@ endif # NSP_SUPPORT ifeq ($(WSI_SUPPORT),y) SRC_C += wsi.c LDFLAGS += -lwebsockets -ljson-c - FLAGS += -DWSI_SUPPORT + CFLAGS += -DWSI_SUPPORT GENERATED_WSI_PROF_H = include/generated/wsi_prof.h GENERATED_HEADERS += $(GENERATED_WSI_PROF_H) diff --git a/daemon/wsi.c b/daemon/wsi.c index 7f89fb7..e201d5d 100644 --- a/daemon/wsi.c +++ b/daemon/wsi.c @@ -32,6 +32,13 @@ #include <libwebsockets.h> #include <errno.h> #include <json.h> + +#include <netinet/tcp.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> + #include "wsi.h" #include "swap_debug.h" #include "daemon.h" @@ -40,7 +47,7 @@ #include "smack.h" #include "wsi_prof.h" /* Generated automatically */ -#define MAX_MSG_LENGTH 4096 +#define MAX_MSG_LENGTH 8192 #define PSTATE_DEFAULT (1UL << ( 0)) #define PSTATE_CONNECTED (1UL << ( 1)) @@ -74,17 +81,15 @@ enum protocol_names { PROTOCOL_PROFILING }; -const char WSI_HOST[] = "127.0.0.1"; -struct libwebsocket_context *context; -struct libwebsocket *wsi; - -unsigned int pstate = PSTATE_DEFAULT; -int request_id = 1; +static const char WSI_HOST[] = "127.0.0.1"; +static struct lws_context *__context; +static struct lws *__wsi; -pthread_t wsi_start_thread = -1; -pthread_t wsi_handle_thread = -1; +static unsigned int pstate = PSTATE_DEFAULT; +static int request_id = 1; -/* static void wsi_destroy(void); */ +static pthread_t wsi_start_thread = -1; +static pthread_t wsi_handle_thread = -1; static int set_profile_info(const char *path, const char *info) { @@ -111,10 +116,8 @@ int wsi_set_profile(const struct app_info_t *app_info) { const char INSPSERVER_START_FILE[] = "/sys/kernel/debug/swap/webprobe/inspector_server_start"; - const char WILL_EXECUTE_FILE[] = - "/sys/kernel/debug/swap/webprobe/will_execute"; - const char DID_EXECUTE_FILE[] = - "/sys/kernel/debug/swap/webprobe/did_execute"; + const char TICK_PROBE_FILE[] = + "/sys/kernel/debug/swap/webprobe/tick_probe"; const char APP_INFO_FILE[] = "/sys/kernel/debug/swap/webprobe/app_info"; int ret = 0; @@ -137,13 +140,8 @@ int wsi_set_profile(const struct app_info_t *app_info) if (ret) goto fail; - snprintf(info_tmp, sizeof(info_tmp), "0x%lx", WILLEXECUTE_ADDR); - ret = set_profile_info(WILL_EXECUTE_FILE, info_tmp); - if (ret) - goto fail; - - snprintf(info_tmp, sizeof(info_tmp), "0x%lx", DIDEXECUTE_ADDR); - ret = set_profile_info(DID_EXECUTE_FILE, info_tmp); + snprintf(info_tmp, sizeof(info_tmp), "0x%lx", TICK_PROBE_ADDR); + ret = set_profile_info(TICK_PROBE_FILE, info_tmp); if (ret) goto fail; @@ -209,7 +207,7 @@ int wsi_enable_profiling(enum web_prof_state_t mode) return ret; } -static void send_request(const char *method) +static void send_request(struct lws *wsi, const char *method) { #define MAX_REQUEST_LENGTH 128 @@ -244,7 +242,7 @@ static void send_request(const char *method) strncpy(buf, payload, MAX_REQUEST_LENGTH - 1); - if (libwebsocket_write(wsi, (unsigned char *)buf, payload_len, + if (lws_write(wsi, (unsigned char *)buf, payload_len, LWS_WRITE_TEXT) < 0) { LOGE("cannot write to web socket (method: %s)\n", method); return; @@ -253,21 +251,21 @@ static void send_request(const char *method) SETSTAT(pstate, PSTATE_WAIT_ACK); } -static int profiling_callback(struct libwebsocket_context *context, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, +static int profiling_callback(struct lws *wsi, + enum lws_callback_reasons reason, void *user, void *in, size_t len) { json_object *jobj, *jobjr; int res_id; + char *msg; switch (reason) { case LWS_CALLBACK_CLIENT_ESTABLISHED: LOGI("Connected to server\n"); SETSTAT(pstate, PSTATE_CONNECTED); - send_request("Profiler.enable"); - send_request("Profiler.start"); + send_request(wsi, "Profiler.enable"); + send_request(wsi, "Profiler.start"); break; case LWS_CALLBACK_DEL_POLL_FD: @@ -280,17 +278,17 @@ static int profiling_callback(struct libwebsocket_context *context, break; case LWS_CALLBACK_CLIENT_RECEIVE: - if (libwebsockets_remaining_packet_payload(wsi)) + if (lws_remaining_packet_payload(wsi)) LOGE("json message too long\n"); - ((char *)in)[len] = '\0'; - LOGI("json message recv; len: %d; msg: %s\n", (int)len, - (char *)in); + msg = in; + msg[len] = '\0'; + LOGI("json message recv; len: %zu; msg: %s\n", len, msg); - if (!libwebsocket_is_final_fragment(wsi)) + if (!lws_is_final_fragment(wsi)) break; - jobjr = json_tokener_parse((char *)in); + jobjr = json_tokener_parse(msg); /* {"result":{},"id":?} */ json_object_object_get_ex(jobjr, "id", &jobj); @@ -344,6 +342,9 @@ static int profiling_callback(struct libwebsocket_context *context, */ break; + case LWS_CALLBACK_GET_THREAD_ID: + break; + default: LOGW("Message unknown. Reason: %d\n", reason); break; @@ -352,52 +353,67 @@ static int profiling_callback(struct libwebsocket_context *context, return 0; } -static struct libwebsocket_protocols protocols[] = { - { "profiling-protocol", profiling_callback, 0, MAX_MSG_LENGTH }, - { NULL, NULL, 0, 0 } +static struct lws_protocols protocols[] = { + { "profiling-protocol", profiling_callback, 0, MAX_MSG_LENGTH, 0, NULL }, + { NULL, NULL, 0, 0, 0, NULL } }; -static void destroy_wsi_conn(struct libwebsocket_context *context) +static void destroy_wsi_conn(struct lws_context *context) { /* */ - libwebsocket_context_destroy(context); + lws_context_destroy(context); } -static int init_wsi_conn(struct libwebsocket_context **context, - struct libwebsocket **wsi, - const char *address, int port) +static inline const struct lws_extension *get_internal_extensions(void) +{ + return NULL; +} + +#define PATH_LEN 128 +static int init_wsi_conn(struct lws_context **context, struct lws **wsi, + const char *address, int port, const char *id) { static struct lws_context_creation_info info; + struct lws_client_connect_info client_info; char host[32]; char origin[32]; - const char *page = "/devtools/page/1"; + char path[PATH_LEN]; int ietf_version = -1; /* latest */ snprintf(host, sizeof(host), "%s:%d", address, port); snprintf(origin, sizeof(origin), "http://%s:%d", address, port); - LOGI(" host =<%s> origin = <%s>\n", host, origin); + snprintf(path, sizeof(path), "/devtools/page/%s", id); + LOGI(" host: \"%s\", origin: \"%s\", path: \"%s\"\n", + host, origin, path); memset(&info, 0, sizeof(info)); - info.port = CONTEXT_PORT_NO_LISTEN; info.protocols = protocols; info.gid = -1; info.uid = -1; info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; - info.extensions = libwebsocket_get_internal_extensions(); + info.extensions = get_internal_extensions(); info.options = 0; - *context = libwebsocket_create_context(&info); + *context = lws_create_context(&info); if (*context == NULL) { LOGE("libwebsocket context creation failed\n"); return 1; } - *wsi = libwebsocket_client_connect(*context, address, port, 0, page, - host, origin, - protocols[PROTOCOL_PROFILING].name, - ietf_version); + memset(&client_info, 0, sizeof(client_info)); + client_info.context = *context; + client_info.address = address; + client_info.ssl_connection = 0; + client_info.path = path; + client_info.port = port; + client_info.host = host; + client_info.origin = origin; + client_info.protocol = protocols[PROTOCOL_PROFILING].name; + client_info.ietf_version_or_minus_one = ietf_version; + + *wsi = lws_client_connect_via_info(&client_info); if (*wsi == NULL) { LOGE("libwebsocket connect failed\n"); @@ -416,17 +432,128 @@ static void *handle_ws_responses(void *arg) !CHKSTAT(pstate, PSTATE_DISCONNECT)) || (!CHKSTAT(pstate, PSTATE_DISCONNECT) && CHKSTAT(pstate, PSTATE_INIT_DONE | PSTATE_INIT_START))) { - libwebsocket_service(context, 1000); + lws_service(__context, 1000); } LOGI("handle response thread finished\n"); return NULL; } +int socket_connect(const char *host, in_port_t port) +{ + struct hostent *hp; + struct sockaddr_in addr; + int on = 1, sk, ret; + + hp = gethostbyname(host); + if (!hp) + return -1; + + memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); + addr.sin_port = htons(port); + addr.sin_family = AF_INET; + sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sk < 0) { + LOGE("failed to open TCP socket\n"); + return -1; + } + + ret = setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, + (const char *)&on, sizeof(int)); + + if (ret < 0) { + LOGE("failed to set socket option\n"); + close(sk); + return -1; + } + + ret = connect(sk, (struct sockaddr *)&addr, + sizeof(struct sockaddr_in)); + if (ret < 0) { + LOGE("failed to connect socket\n"); + close(sk); + return -1; + } + + return sk; +} + +#define BUFFER_SIZE 1024 +#define HTTP_REQUEST_BUFLEN 1024 +static const char __http_requst[] = "GET /json HTTP/1.1\r\n" + "Host: %s:%d\r\n" + "Connection: Keep-Alive\r\n" + "User-Agent: Apache-HttpClient/4.1.2 " + "(java 1.5)\r\n\r\n"; +static const char __http_ok[] = "HTTP/1.1 200 OK"; +static const size_t __http_ok_len = sizeof(__http_ok) - 1; +static const char __http_end[] = "\r\n\r\n"; +static const size_t __http_end_len = sizeof(__http_end) - 1; + +static bool path_id_get(char *id, size_t idlen, const char *host, int port) +{ + bool ret = false; + int sk; + ssize_t n; + char buffer[BUFFER_SIZE] = { 0 }; + char request[HTTP_REQUEST_BUFLEN]; + size_t reqlen; + char *s, *p; + const char *id_str = NULL; + json_object *obj, *id_obj, *root; + + sk = socket_connect(host, port); + + snprintf(request, HTTP_REQUEST_BUFLEN, __http_requst, host, port); + reqlen = strlen(request); + n = write(sk, request, reqlen); + if (n < reqlen) + goto connection_shutdown; + + n = read(sk, buffer, BUFFER_SIZE - 1); + if (n < 0) + goto connection_shutdown; + + if (strncmp(buffer, __http_ok, __http_ok_len)) + goto connection_shutdown; + + s = buffer + __http_ok_len + 2; + p = strstr(s, __http_end); + if (!p) + goto connection_shutdown; + + p += __http_end_len; + root = json_tokener_parse(p); + obj = json_object_array_get_idx(root, 0); + json_object_object_get_ex(obj, "id", &id_obj); + if (!id_obj) + goto json_root_obj_put; + + id_str = json_object_get_string(id_obj); + if (id_str) { + snprintf(id, idlen, "%s", id_str); + ret = true; + } else { + id[0] = '\0'; + } + +json_root_obj_put: + json_object_put(root); + +connection_shutdown: + shutdown(sk, SHUT_RDWR); + close(sk); + + return ret; +} + +#define IDLEN 128 static int wsi_init(const char *address, int port) { int res = 0; int i = 0; + char id[IDLEN]; + if (!port) { char buf[sizeof(struct msg_t) + sizeof(uint32_t)]; struct msg_t *msg = (struct msg_t *)buf; @@ -452,7 +579,13 @@ static int wsi_init(const char *address, int port) goto exit; } - if (init_wsi_conn(&context, &wsi, address, port) != 0) { + if (!path_id_get(id, sizeof(id), address, port)) { + LOGE("failed to get ID for request\n"); + res = 1; + goto exit; + } + + if (init_wsi_conn(&__context, &__wsi, address, port, id) != 0) { LOGE("cannot init wsi connection\n"); res = 1; goto exit; @@ -480,7 +613,7 @@ static int wsi_start_profiling(void) { if (pthread_create(&wsi_handle_thread, NULL, &handle_ws_responses, NULL)) { LOGE("Can't create handle_ws_ threads\n"); - destroy_wsi_conn(context); + destroy_wsi_conn(__context); return 1; } @@ -490,8 +623,8 @@ static int wsi_start_profiling(void) static void wsi_stop_profiling(void) { if (CHKSTAT(pstate, PSTATE_CONNECTED)) { - send_request("Profiler.stop"); - send_request("Profiler.disable"); + send_request(__wsi, "Profiler.stop"); + send_request(__wsi, "Profiler.disable"); } } @@ -575,7 +708,7 @@ void wsi_stop(void) } wsi_handle_thread = -1; - destroy_wsi_conn(context); + destroy_wsi_conn(__context); pstate = PSTATE_DEFAULT; } diff --git a/packaging/swap-manager.spec b/packaging/swap-manager.spec index 45c5f51..fe7ac3d 100644 --- a/packaging/swap-manager.spec +++ b/packaging/swap-manager.spec @@ -10,7 +10,7 @@ Source: %{name}_%{version}.tar.gz # setup config %define NSP_SUPPORT 0 %define WSP_SUPPORT 0 -%define WSI_SUPPORT 0 +%define WSI_SUPPORT 1 %define WAYLAND_SUPPORT 0 %if "%{_with_wayland}" == "1" @@ -56,7 +56,12 @@ BuildRequires: pkgconfig(tizen-extension-client) %define NSP_SUPPORT 1 # FIXME: add WSP_SUPPORT wrt webkit2-efl and webkit2-efl-debuginfo -# FIXME: add WSI_SUPPORT libwebsockets-devel + +%if %{WSI_SUPPORT} +BuildRequires: pkgconfig(chromium-efl) +BuildRequires: chromium-efl-debuginfo +BuildRequires: pkgconfig(libwebsockets) +%endif Requires: swap-modules Requires: swap-probe diff --git a/scripts/gen_wsi_prof.sh b/scripts/gen_wsi_prof.sh index 7890ef0..ce9b053 100755 --- a/scripts/gen_wsi_prof.sh +++ b/scripts/gen_wsi_prof.sh @@ -23,13 +23,13 @@ source $script_dir/dyn_vars if [ "$__tizen_profile_name__" == "tv" ]; then webkit_package_name=webkit2-efl-tv else - webkit_package_name=webkit2-efl + webkit_package_name=chromium-efl fi if [ "$__tizen_product_tv__" == "1" ]; then - lib_file=$(rpm -ql ${webkit_package_name} | grep "/usr/lib/libewebkit2.so$" | head -1) + lib_file=$(rpm -ql ${webkit_package_name} | grep "/usr/lib/libchromium-ewk.so" | head -1) else - lib_file=$(rpm -ql ${webkit_package_name}-debuginfo | grep "/usr/lib/debug/usr/lib/libewebkit2.so.debug$" | head -1) + lib_file=$(rpm -ql ${webkit_package_name}-debuginfo | grep "/usr/lib/debug/usr/lib/libchromium-ewk.so.debug" | head -1) fi tmp=$(mktemp) @@ -41,18 +41,16 @@ if [ "$__tizen_profile_name__" == "tv" ]; then else func_names+=(ewk_context_inspector_server_start) fi -func_names+=(_ZN3JSC16ProfileGenerator11willExecuteEPNS_9ExecStateERKNS_14CallIdentifierE) -func_names+=(_ZN3JSC16ProfileGenerator10didExecuteEPNS_9ExecStateERKNS_14CallIdentifierE) +func_names+=(_ZN2v88internal11ProfileNode14FindOrAddChildEPNS0_9CodeEntryE) addrs=(`get_addrs ${func_names[@]}`) inspector_addr=${addrs[0]} -willexecute_addr=${addrs[1]} -didexecute_addr=${addrs[2]} +tick_addr=${addrs[1]} rm ${tmp} -if [ -z "${inspector_addr}" -o -z "${willexecute_addr}" -o -z "${didexecute_addr}" ]; then +if [ -z "${inspector_addr}" -o -z "${tick_addr}" ]; then exit 1 fi @@ -66,8 +64,7 @@ cat << EOF static const unsigned long INSPECTOR_ADDR = ${inspector_addr}; -static const unsigned long WILLEXECUTE_ADDR = ${willexecute_addr}; -static const unsigned long DIDEXECUTE_ADDR = ${didexecute_addr}; +static const unsigned long TICK_PROBE_ADDR = ${tick_addr}; #endif /* WSI_PROF_H_ */ EOF |