Update the service, replace message-port with tidl. 66/185066/10
authorXie Ligang <ligang0.xie@samsung.com>
Thu, 26 Jul 2018 00:43:00 +0000 (08:43 +0800)
committerXie Ligang <ligang0.xie@samsung.com>
Fri, 27 Jul 2018 01:17:35 +0000 (09:17 +0800)
Change-Id: I696d80d885a485b589f5f5bd35495ece2af500f2
Signed-off-by: Xie Ligang <ligang0.xie@samsung.com>
packaging/nlp.spec
service/CMakeLists.txt
service/inc/message.h [new file with mode: 0644]
service/message.tidl [new file with mode: 0644]
service/prebuild.sh [new file with mode: 0755]
service/src/message.c [new file with mode: 0644]
service/src/service.c

index ca3ab41..508d6b0 100755 (executable)
@@ -13,6 +13,8 @@ BuildRequires: pkgconfig(capi-appfw-service-application)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(bundle)
 BuildRequires: pkgconfig(python)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(rpc-port)
 
 # runtime requires
 Requires(post): /sbin/ldconfig
index f105f4e..4001da5 100644 (file)
@@ -9,6 +9,7 @@ message("Building by ${CMAKE_SYSTEM_VERSION} machine")
 
 SET(SERVICE_SRC
     src/service.c
+    src/message.c
     )
 
 #include
@@ -26,10 +27,11 @@ MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
 
 pkg_check_modules(pkgs REQUIRED
         capi-base-common
-        capi-message-port
         capi-appfw-service-application
         bundle
         python
+        glib-2.0
+        rpc-port
     )
 FOREACH(flag ${pkgs_CFLAGS})
     SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
diff --git a/service/inc/message.h b/service/inc/message.h
new file mode 100644 (file)
index 0000000..a699078
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Generated by tidlc 1.2.4.
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <bundle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct message_context_s* rpc_port_stub_message_context_h;
+
+int rpc_port_stub_message_context_set_tag(rpc_port_stub_message_context_h ctx, void *tag);
+
+int rpc_port_stub_message_context_get_tag(rpc_port_stub_message_context_h ctx, void **tag);
+
+int rpc_port_stub_message_context_get_sender(rpc_port_stub_message_context_h ctx, char **sender);
+
+typedef struct message_notify_cb_s *rpc_port_message_notify_cb_h;
+
+int rpc_port_message_notify_cb_destroy(rpc_port_message_notify_cb_h h);
+
+int rpc_port_message_notify_cb_clone(rpc_port_message_notify_cb_h h, rpc_port_message_notify_cb_h *clone);
+
+int rpc_port_message_notify_cb_invoke(rpc_port_message_notify_cb_h h, const char *sender, bundle *msg);
+
+typedef struct {
+    void (*create)(rpc_port_stub_message_context_h context, void *user_data);
+    void (*terminate)(rpc_port_stub_message_context_h context, void *user_data);
+
+    int (*coregister)(rpc_port_stub_message_context_h context, const char *name, rpc_port_message_notify_cb_h cb, void *user_data);
+    void (*unregister)(rpc_port_stub_message_context_h context, void *user_data);
+    int (*send)(rpc_port_stub_message_context_h context, bundle *msg, void *user_data);
+} rpc_port_stub_message_callback_s;
+
+int rpc_port_stub_message_register(rpc_port_stub_message_callback_s *callback, void *user_data);
+
+int rpc_port_stub_message_unregister(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/service/message.tidl b/service/message.tidl
new file mode 100644 (file)
index 0000000..76ea688
--- /dev/null
@@ -0,0 +1,7 @@
+interface message {
+    void notify_cb(string sender, bundle *msg) delegate;
+
+    int coregister(string name, notify_cb cb);
+    void unregister() async;
+    int send(bundle *msg);
+}
diff --git a/service/prebuild.sh b/service/prebuild.sh
new file mode 100755 (executable)
index 0000000..979a7d2
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+tidlc -s -l C -i message.tidl -o message
+mv message.h ./inc/
+mv message.c ./src/
\ No newline at end of file
diff --git a/service/src/message.c b/service/src/message.c
new file mode 100644 (file)
index 0000000..6eff7e8
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * Generated by tidlc 1.2.4.
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <glib.h>
+#include <dlog.h>
+#include <rpc-port.h>
+#include <rpc-port-parcel.h>
+
+#include "message.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RPC_PORT_STUB"
+
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+typedef int (*stub_method)(rpc_port_h, rpc_port_parcel_h, void *data);
+
+enum message_method_e {
+    message_METHOD_Result,
+    message_METHOD_Callback,
+    message_METHOD_coregister,
+    message_METHOD_unregister,
+    message_METHOD_send,
+};
+
+enum message_delegate_e {
+    message_DELEGATE_notify_cb = 1,
+};
+
+static rpc_port_stub_h __message_stub;
+static rpc_port_stub_message_callback_s __message_callback;
+static void *__message_user_data;
+static GList *__message_contexts;
+
+struct message_context_s {
+    char *sender;
+    char *instance;
+    rpc_port_h port;
+    void *tag;
+    rpc_port_stub_message_callback_s callback;
+    void *user_data;
+};
+
+static struct message_context_s *__create_message_context(const char *sender, const char *instance)
+{
+    struct message_context_s *handle;
+
+    handle = calloc(1, sizeof(struct message_context_s));
+    if (!handle) {
+        _E("Out of memory");
+        return NULL;
+    }
+
+    handle->sender = strdup(sender);
+    if (!handle->sender) {
+        _E("Out of memory");
+        free(handle);
+        return NULL;
+    }
+
+    handle->instance = strdup(instance);
+    if (!handle->instance) {
+        _E("Out of memory");
+        free(handle->sender);
+        free(handle);
+        return NULL;
+    }
+
+    handle->callback = __message_callback;
+    handle->user_data = __message_user_data;
+
+    return handle;
+}
+
+static void __destroy_message_context(gpointer data)
+{
+    struct message_context_s *handle = data;
+
+    if (!handle) {
+        _E("Critical error!");
+        return;
+    }
+
+    free(handle->instance);
+    free(handle->sender);
+    free(handle);
+}
+
+static struct message_context_s *__find_message_context(const char *instance)
+{
+    struct message_context_s *handle;
+    GList *iter;
+
+    iter = __message_contexts;
+    while (iter) {
+        handle = (struct message_context_s *)iter->data;
+        if (!strcmp(handle->instance, instance))
+            return handle;
+        iter = g_list_next(iter);
+    }
+
+    return NULL;
+}
+
+int rpc_port_stub_message_context_set_tag(rpc_port_stub_message_context_h ctx, void *tag)
+{
+    if (!ctx) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    ctx->tag = tag;
+
+    return 0;
+}
+
+int rpc_port_stub_message_context_get_tag(rpc_port_stub_message_context_h ctx, void **tag)
+{
+    if (!ctx || !tag) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    *tag = ctx->tag;
+
+    return 0;
+}
+
+int rpc_port_stub_message_context_get_sender(rpc_port_stub_message_context_h ctx, char **sender)
+{
+    if (!ctx || !sender) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    *sender = strdup(ctx->sender);
+    if (*sender == NULL) {
+        _E("Out of memory");
+        return -1;
+    }
+
+    return 0;
+}
+
+struct message_notify_cb_s {
+    rpc_port_parcelable_t parcelable;
+    rpc_port_h port;
+    int id;
+    int seq_id;
+    bool once;
+    bool valid;
+};
+
+static void __message_notify_cb_to(rpc_port_parcel_h parcel, void *data)
+{
+    rpc_port_message_notify_cb_h handle = data;
+
+    if (!handle) {
+        _E("Invalid parameter");
+        return;
+    }
+
+    rpc_port_parcel_write_int32(parcel, handle->id);
+    rpc_port_parcel_write_int32(parcel, handle->seq_id);
+    rpc_port_parcel_write_bool(parcel, handle->once);
+}
+
+static void __message_notify_cb_from(rpc_port_parcel_h parcel, void *data)
+{
+    rpc_port_message_notify_cb_h handle = data;
+
+    if (!handle) {
+        _E("Invalid parameter");
+        return;
+    }
+
+    rpc_port_parcel_read_int32(parcel, &handle->id);
+    rpc_port_parcel_read_int32(parcel, &handle->seq_id);
+    rpc_port_parcel_read_bool(parcel, &handle->once);
+}
+
+int rpc_port_message_notify_cb_create(rpc_port_message_notify_cb_h *h)
+{
+    struct message_notify_cb_s *handle;
+    static int seq_num;
+
+    if (!h) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    handle = calloc(1, sizeof(struct message_notify_cb_s));
+    if (!handle) {
+        _E("Out of memory");
+        return -1;
+    }
+
+    handle->parcelable.to = __message_notify_cb_to;
+    handle->parcelable.from = __message_notify_cb_from;
+    handle->id = message_DELEGATE_notify_cb;
+    handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1;
+    handle->once = false;
+    handle->valid = true;
+
+    *h = handle;
+
+    return 0;
+}
+
+int rpc_port_message_notify_cb_destroy(rpc_port_message_notify_cb_h h)
+{
+    if (!h) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    free(h);
+
+    return 0;
+}
+
+int rpc_port_message_notify_cb_clone(rpc_port_message_notify_cb_h h, rpc_port_message_notify_cb_h *clone)
+{
+    rpc_port_message_notify_cb_h handle;
+
+    if (!h || !clone) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    handle = calloc(1, sizeof(struct message_notify_cb_s));
+    if (!handle) {
+        _E("Out of memory");
+        return -1;
+    }
+
+    handle->parcelable = h->parcelable;
+    handle->port = h->port;
+    handle->id = h->id;
+    handle->seq_id = h->seq_id;
+    handle->once = h->once;
+    handle->valid = h->valid;
+
+    *clone = handle;
+
+    return 0;
+}
+
+int rpc_port_message_notify_cb_invoke(rpc_port_message_notify_cb_h h, const char *sender, bundle *msg)
+{
+    rpc_port_parcel_h parcel = NULL;
+
+    if (!h || !h->port) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    if (h->once && !h->valid) {
+        _E("Invalid callback");
+        return -1;
+    }
+
+    rpc_port_parcel_create(&parcel);
+    if (!parcel) {
+        _E("Failed to create parcel");
+        return -1;
+    }
+
+    rpc_port_parcel_write_int32(parcel, message_METHOD_Callback);
+    rpc_port_parcel_write(parcel, &h->parcelable, h);
+    rpc_port_parcel_write_string(parcel, sender ? sender : "");
+    rpc_port_parcel_write_bundle(parcel, msg);
+
+    rpc_port_parcel_send(parcel, h->port);
+    rpc_port_parcel_destroy(parcel);
+    h->valid = false;
+
+    return 0;
+}
+
+int rpc_port_message_notify_cb_set_port(rpc_port_message_notify_cb_h h, rpc_port_h port)
+{
+    if (!h || !port) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    h->port = port;
+
+    return 0;
+}
+
+static int __message_method_coregister(rpc_port_h port, rpc_port_parcel_h parcel, void *data)
+{
+    rpc_port_stub_message_context_h context = data;
+    rpc_port_h callback_port;
+    int r;
+
+    r = rpc_port_stub_get_port(__message_stub, RPC_PORT_PORT_CALLBACK, context->instance, &callback_port);
+    if (r != 0)
+        _E("Failed to get callback port");
+
+    char *name;
+    rpc_port_message_notify_cb_h cb;
+
+    rpc_port_parcel_read_string(parcel, &name);
+    rpc_port_message_notify_cb_create(&cb);
+    rpc_port_message_notify_cb_set_port(cb, callback_port);
+    rpc_port_parcel_read(parcel, &cb->parcelable, cb);
+
+    int ret = context->callback.coregister(context, name, cb, context->user_data);
+    do {
+        rpc_port_parcel_h result;
+
+        rpc_port_parcel_create(&result);
+        rpc_port_parcel_write_int32(result, message_METHOD_Result);
+        rpc_port_parcel_write_int32(result, ret);
+        rpc_port_parcel_send(result, port);
+        rpc_port_parcel_destroy(result);
+    } while (0);
+
+    free(name);
+    rpc_port_message_notify_cb_destroy(cb);
+    return 0;
+}
+
+static int __message_method_unregister(rpc_port_h port, rpc_port_parcel_h parcel, void *data)
+{
+    rpc_port_stub_message_context_h context = data;
+    rpc_port_h callback_port;
+    int r;
+
+    r = rpc_port_stub_get_port(__message_stub, RPC_PORT_PORT_CALLBACK, context->instance, &callback_port);
+    if (r != 0)
+        _E("Failed to get callback port");
+
+    context->callback.unregister(context, context->user_data);
+
+    return 0;
+}
+
+static int __message_method_send(rpc_port_h port, rpc_port_parcel_h parcel, void *data)
+{
+    rpc_port_stub_message_context_h context = data;
+    rpc_port_h callback_port;
+    int r;
+
+    r = rpc_port_stub_get_port(__message_stub, RPC_PORT_PORT_CALLBACK, context->instance, &callback_port);
+    if (r != 0)
+        _E("Failed to get callback port");
+
+    bundle *msg;
+
+    rpc_port_parcel_read_bundle(parcel, &msg);
+
+    int ret = context->callback.send(context, msg, context->user_data);
+    do {
+        rpc_port_parcel_h result;
+
+        rpc_port_parcel_create(&result);
+        rpc_port_parcel_write_int32(result, message_METHOD_Result);
+        rpc_port_parcel_write_int32(result, ret);
+        rpc_port_parcel_send(result, port);
+        rpc_port_parcel_destroy(result);
+    } while (0);
+
+    bundle_free(msg);
+    return 0;
+}
+
+static stub_method __message_method_table[] = {
+    [message_METHOD_coregister] = __message_method_coregister,
+    [message_METHOD_unregister] = __message_method_unregister,
+    [message_METHOD_send] = __message_method_send,
+};
+
+static void __message_on_connected(const char *sender, const char *instance, void *data)
+{
+    rpc_port_stub_message_context_h context;
+
+    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
+    context = __create_message_context(sender, instance);
+    if (!context)
+        return;
+
+    if (context->callback.create)
+        context->callback.create(context, context->user_data);
+    __message_contexts = g_list_append(__message_contexts, context);
+}
+
+static void __message_on_disconnected(const char *sender, const char *instance, void *data)
+{
+    rpc_port_stub_message_context_h context;
+
+    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
+    context = __find_message_context(instance);
+    if (!context)
+        return;
+
+    if (context->callback.terminate)
+        context->callback.terminate(context, context->user_data);
+    __message_contexts = g_list_remove(__message_contexts, context);
+    __destroy_message_context(context);
+}
+
+static int __message_on_received(const char *sender, const char *instance, rpc_port_h port, void *data)
+{
+    rpc_port_stub_message_context_h context;
+    rpc_port_parcel_h parcel;
+    int cmd = -1;
+    int r;
+
+    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
+    context = __find_message_context(instance);
+    if (!context) {
+        _E("Failed to find message context(%s)", instance);
+        return -1;
+    }
+
+    context->port = port;
+    r = rpc_port_parcel_create_from_port(&parcel, port);
+    if (r != 0) {
+        _E("Failed to create parcel from port");
+        return r;
+    }
+
+    rpc_port_parcel_read_int32(parcel, &cmd);
+    if (cmd > 1 && cmd < (sizeof(__message_method_table) / sizeof(__message_method_table[0]))) {
+        if (__message_method_table[cmd])
+            r = __message_method_table[cmd](port, parcel, context);
+    } else {
+        _E("Unknown Command(%d)", cmd);
+        r = -1;
+    }
+
+    rpc_port_parcel_destroy(parcel);
+
+    return r;
+}
+
+static int __message_add_privileges(void)
+{
+
+    return 0;
+}
+
+int rpc_port_stub_message_register(rpc_port_stub_message_callback_s *callback, void *user_data)
+{
+    int r;
+
+    if (__message_stub) {
+        _W("Already exists");
+        return -1;
+    }
+
+    if (!callback) {
+        _E("Invalid parameter");
+        return -1;
+    }
+
+    __message_callback = *callback;
+    __message_user_data = user_data;
+    r = rpc_port_stub_create(&__message_stub, "message");
+    if (r != 0) {
+        _E("Failed to create stub handle");
+        return r;
+    }
+
+    r = rpc_port_stub_add_received_event_cb(__message_stub, __message_on_received, NULL);
+    if (r != 0) {
+        _E("Failed to add received event callback");
+        rpc_port_stub_destroy(__message_stub);
+        __message_stub = NULL;
+        return r;
+    }
+
+    r = rpc_port_stub_add_connected_event_cb(__message_stub, __message_on_connected, NULL);
+    if (r != 0) {
+        _E("Failed to add connected event callback");
+        rpc_port_stub_destroy(__message_stub);
+        __message_stub = NULL;
+        return r;
+    }
+
+    r = rpc_port_stub_add_disconnected_event_cb(__message_stub, __message_on_disconnected, NULL);
+    if (r != 0) {
+        _E("Failed to add disconnected event callback");
+        rpc_port_stub_destroy(__message_stub);
+        __message_stub = NULL;
+        return r;
+    }
+
+    r = __message_add_privileges();
+    if (r != 0) {
+        _E("Failed to add privileges");
+        rpc_port_stub_destroy(__message_stub);
+        __message_stub = NULL;
+        return r;
+    }
+
+    r = rpc_port_stub_listen(__message_stub);
+    if (r != 0) {
+        _E("Failed to listen stub");
+        rpc_port_stub_destroy(__message_stub);
+        __message_stub = NULL;
+        return r;
+    }
+
+    return 0;
+}
+
+int rpc_port_stub_message_unregister(void)
+{
+    int r;
+
+    if (!__message_stub)
+        return -1;
+
+    if (__message_contexts) {
+        g_list_free_full(__message_contexts, __destroy_message_context);
+        __message_contexts = NULL;
+    }
+
+    r = rpc_port_stub_destroy(__message_stub);
+    __message_stub = NULL;
+
+    return r;
+}
index 11f5abb..7c7955a 100644 (file)
 #include <tizen.h>
-#include <message_port.h>
 #include <dlfcn.h>
 #include <service_app.h>
 #include "service.h"
 #include <dlog.h>
+#include <glib.h>
+#include "message.h"
 
-void
-message_port_cb(int local_port_id, const char *remote_app_id, const char *remote_port,
-                bool trusted_remote_port, bundle *message, void *user_data)
+struct client_s {
+    char *id;
+    rpc_port_message_notify_cb_h cb;
+};
+
+static struct client_s *__create_client(const char *id,
+        rpc_port_message_notify_cb_h cb)
+{
+    struct client_s *handle;
+
+    handle = calloc(1, sizeof(struct client_s));
+    if (!handle) {
+        LOGE("Out of memory");
+        return NULL;
+    }
+
+    handle->id = strdup(id);
+    if (!handle->id) {
+        LOGE("Out of memory");
+        free(handle);
+        return NULL;
+    }
+
+    rpc_port_message_notify_cb_clone(cb, &handle->cb);
+    if (!handle->cb) {
+        LOGE("Out of memory");
+        free(handle->id);
+        free(handle);
+        return NULL;
+    }
+
+    return handle;
+}
+
+static void __destroy_client(gpointer data)
+{
+    struct client_s *handle = data;
+
+    if (!handle)
+        return;
+
+    if (handle->cb)
+        rpc_port_message_notify_cb_destroy(handle->cb);
+    if (handle->id)
+        free(handle->id);
+    free(handle);
+}
+
+
+static void __messeage_create(rpc_port_stub_message_context_h context,
+        void *user_data)
+{
+    char *sender = NULL;
+
+    rpc_port_stub_message_context_get_sender(context, &sender);
+    if (!sender)
+        return;
+
+    LOGI("[__RPC_PORT__] sender(%s)", sender);
+    free(sender);
+}
+
+static void __message_terminate(rpc_port_stub_message_context_h context,
+        void *user_data)
+{
+    char *sender = NULL;
+
+    rpc_port_stub_message_context_get_sender(context, &sender);
+    if (!sender)
+        return;
+
+    LOGI("[__RPC_PORT__] sender(%s)", sender);
+    free(sender);
+}
+
+static int __message_register(rpc_port_stub_message_context_h context,
+        const char *name, rpc_port_message_notify_cb_h cb,
+        void *user_data)
+{
+    struct client_s *client;
+
+    LOGI("[__RPC_PORT__] name(%s)", name);
+    client = __create_client(name, cb);
+    if (!client)
+        return -1;
+    rpc_port_stub_message_context_set_tag(context, client);
+    return 0;
+}
+
+static int __message_send(rpc_port_stub_message_context_h context,
+        const bundle *msg, void *user_data)
 {
-    const char *command = NULL;
+    struct client_s *sender_client = NULL;
+
+    char *message = NULL;
+    bundle_get_str(msg, "command", &message);
+    rpc_port_stub_message_context_get_tag(context, (void *)&sender_client);
+    LOGI("[__RPC_PORT__] name(%s), msg(%s)", sender_client->id, message);
+
     bundle *reply = bundle_create();
-    bundle_get_str(message, "command", &command);
     char *info = NULL;
     PyObject* args = NULL;
     PyObject* lists = NULL;
@@ -28,34 +122,31 @@ message_port_cb(int local_port_id, const char *remote_app_id, const char *remote
     PyObject* ld_module = NULL;
     PyObject* ld_result = NULL;
     PyObject* pos_elm_tuple = NULL;
-    bundle_get_str(message, "info", &info);
-    dlog_print(DLOG_INFO, LOG_TAG, "service get message from client, remote command is %s , remote info is %s",command ,info);
-
+    bundle_get_str(msg, "info", &info);
     NLTK_CMDS cmd = NLTK_CMD_NONE;
-    if (command)
+    if (message)
     {
-        if (!strcmp(command, "word_tokenize"))
+        if (!strcmp(message, "word_tokenize"))
         {
             cmd = NLTK_CMD_TOKENIZE;
         }
-        else if (!strcmp(command, "pos_tag" ))
+        else if (!strcmp(message, "pos_tag" ))
         {
             cmd = NLTK_CMD_POSTAG;
         }
-        else if (!strcmp(command, "ne_chunk"))
+        else if (!strcmp(message, "ne_chunk"))
         {
             cmd = NLTK_CMD_NECHUNK;
         }
-        else if (!strcmp(command, "lemmatize"))
+        else if (!strcmp(message, "lemmatize"))
         {
             cmd = NLTK_CMD_LEMMATIZE;
         }
-        else if (!strcmp(command, "langdetect"))
+        else if (!strcmp(message, "langdetect"))
         {
             cmd = NLTK_CMD_LANGDETECT;
         }
     }
-
     switch (cmd)
     {
         case NLTK_CMD_TOKENIZE:
@@ -69,8 +160,8 @@ message_port_cb(int local_port_id, const char *remote_app_id, const char *remote
                 strcpy(tokens[i]  ,nltk_get_string_from_element(nltk_get_element_from_list_by_index(lists, i)));
             }
             bundle_add_str(reply, "command", "word_tokenize");
-            bundle_add_str_array(reply, "return", tokens, len);
-            dlog_print(DLOG_INFO, LOG_TAG, "word_tokenize process done");
+            bundle_add_str_array(reply, "return_token", tokens, len);
+            LOGD("word_tokenize process done");
             break;
         case NLTK_CMD_POSTAG:
             args = nltk_make_args_from_string(info);
@@ -92,7 +183,7 @@ message_port_cb(int local_port_id, const char *remote_app_id, const char *remote
             bundle_add_str(reply, "command", "pos_tag");
             bundle_add_str_array(reply, "return_tag", tag, len);
             bundle_add_str_array(reply, "return_token", token, len);
-            dlog_print(DLOG_INFO, LOG_TAG, "pos_tag process done");
+            LOGD("pos_tag process done");
             break;
         case NLTK_CMD_NECHUNK:
             args = nltk_make_args_from_string(info);
@@ -119,7 +210,7 @@ message_port_cb(int local_port_id, const char *remote_app_id, const char *remote
             bundle_add_str(reply, "command", "ne_chunk");
             bundle_add_str_array(reply, "return_tag", s_tag, len);
             bundle_add_str_array(reply, "return_token", s_token, len);
-            dlog_print(DLOG_INFO, LOG_TAG, "ne_chunk process done");
+            LOGD("ne_chunk process done");
             break;
         case NLTK_CMD_LEMMATIZE:
             args = nltk_make_args_from_string(info);
@@ -132,7 +223,7 @@ message_port_cb(int local_port_id, const char *remote_app_id, const char *remote
             strcpy(lem_buf[0] , nltk_get_string_from_element(lm_result));
             bundle_add_str(reply, "command", "lemmatize");
             bundle_add_str_array(reply, "return_token", lem_buf, 1);
-            dlog_print(DLOG_INFO, LOG_TAG, "lemmatize process done");
+            LOGD("lemmatize process done");
             break;
         case NLTK_CMD_LANGDETECT:
             args = nltk_make_args_from_string(info);
@@ -143,43 +234,55 @@ message_port_cb(int local_port_id, const char *remote_app_id, const char *remote
             strcpy(lang_buf[0] , nltk_get_string_from_element(ld_result));
             bundle_add_str(reply, "command", "langdetect");
             bundle_add_str_array(reply, "return_token", lang_buf, 1);
-            dlog_print(DLOG_INFO, LOG_TAG, "langdetect process done");
+            LOGD("langdetect process done");
             break;
         default:
             bundle_add_str(reply, "command", "Exception happens");
             break;
     }
-
-    int ret = message_port_send_message(remote_app_id, remote_port, reply );
-    if (ret != MESSAGE_PORT_ERROR_NONE) {
-        dlog_print(DLOG_INFO, LOG_TAG, "Port send message error: %d", ret);
-    } else
-    {
-        dlog_print(DLOG_INFO, LOG_TAG, "service send message to client: %s", remote_port);
-    }
+    rpc_port_message_notify_cb_invoke(sender_client->cb, sender_client->id, reply);
     bundle_free(reply);
-    dlog_print(DLOG_INFO, LOG_TAG, "bundle released");
+    return 0;
 }
 
+static void __message_unregister(rpc_port_stub_message_context_h context,
+        void *user_data)
+{
+    struct client_s *client = NULL;
+
+    rpc_port_stub_message_context_get_tag(context, (void *)&client);
+    if (client == NULL)
+        return;
+    rpc_port_stub_message_context_set_tag(context, NULL);
+    LOGI("[__RPC_PORT__] name(%s)", client->id);
+    __destroy_client(client);
+}
+
+
 bool service_app_create(void *data)
 {
-    // Todo: add your code here.
-    int port_id = message_port_register_local_port("6666", message_port_cb, NULL);
-    if (port_id < 0)
-    {
-        dlog_print(DLOG_INFO, LOG_TAG, "NLTK ####Port register error: %d", port_id);
-    }
+    nltk_initialize();
+    globe_nltk = nltk_get_module("nltk");
+    LOGD("nltk library loaded success: ");
+    globe_lemm = nltk_get_module("nltk.stem");
+    LOGD("nltk stem library loaded success: ");
+    globe_lang = nltk_get_module("langdetect");
+    LOGD("langdetect library loaded success: ");
+
+    int ret;
+    rpc_port_stub_message_callback_s callback = {
+        __messeage_create,
+        __message_terminate,
+        __message_register,
+        __message_unregister,
+        __message_send
+    };
+
+    ret = rpc_port_stub_message_register(&callback, NULL);
+    if (ret != 0)
+        dlog_print(DLOG_INFO, LOG_TAG,"Failed to register message");
     else
-    {
-        dlog_print(DLOG_INFO, LOG_TAG, "NLTK ####Port register success: %d", port_id);
-        nltk_initialize();
-        globe_nltk = nltk_get_module("nltk");
-        dlog_print(DLOG_INFO, LOG_TAG, "nltk library loaded success: ");
-        globe_lemm = nltk_get_module("nltk.stem");
-        dlog_print(DLOG_INFO, LOG_TAG, "nltk stem library loaded success: ");
-        globe_lang = nltk_get_module("langdetect");
-        dlog_print(DLOG_INFO, LOG_TAG, "langdetect library loaded success: ");
-    }
+        dlog_print(DLOG_INFO, LOG_TAG,"successfully to register message");
 
     return true;
 }