Remote client service is implemented.
authorSung-jae Park <nicesj.park@samsung.com>
Mon, 5 Aug 2013 12:40:21 +0000 (21:40 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Mon, 5 Aug 2013 13:52:50 +0000 (22:52 +0900)
But not yet published.
Slave Life cycle management code is updated.
(Return value handling codes are updated)

Change-Id: I8670b9502c11dce404b5a42db6e00fc31dbbdbe4

20 files changed:
CMakeLists.txt
include/buffer_handler.h
include/client_life.h
include/conf.h
include/file_service.h [new file with mode: 0644]
include/service_common.h
packaging/data-provider-master.spec
src/buffer_handler.c
src/client_life.c
src/client_rpc.c
src/conf.c
src/critical_log.c
src/file_service.c [new file with mode: 0644]
src/main.c
src/server.c
src/service_common.c
src/shortcut_service.c
src/slave_life.c
src/utility_service.c
src/xmonitor.c

index d5c7722..db98c32 100644 (file)
@@ -60,6 +60,8 @@ ADD_DEFINITIONS("-DSHORTCUT_SMACK_LABEL=\"data-provider-master::shortcut\"")
 ADD_DEFINITIONS("-DNOTIFICATION_SMACK_LABEL=\"data-provider-master::notification\"")
 ADD_DEFINITIONS("-DBADGE_SMACK_LABEL=\"data-provider-master::badge\"")
 
+ADD_DEFINITIONS("-DCLIENT_PORT=\"8208\"")
+
 ADD_DEFINITIONS("-DNDEBUG")
 #ADD_DEFINITIONS("-DFLOG")
 ADD_DEFINITIONS(${pkg_CFLAGS})
@@ -96,6 +98,7 @@ ADD_EXECUTABLE(${PROJECT_NAME}
        src/notification_service.c
        src/utility_service.c
        src/service_common.c
+       src/file_service.c
 )
 
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkg_LDFLAGS} "-ldl")
index c2084cd..a60c59a 100644 (file)
@@ -16,6 +16,7 @@
 
 struct buffer_info;
 struct inst_info;
+struct buffer;
 
 enum buffer_type { /*!< Must have to be sync with libprovider, liblivebox-viewer */
        BUFFER_TYPE_FILE,
@@ -159,4 +160,12 @@ extern void *buffer_handler_pixmap_buffer(struct buffer_info *info);
 
 extern struct inst_info *buffer_handler_instance(struct buffer_info *info);
 
+extern struct buffer *buffer_handler_raw_open(enum buffer_type, void *resource);
+
+extern int buffer_handler_raw_close(struct buffer *buffer);
+
+extern void *buffer_handler_raw_data(struct buffer *buffer);
+
+extern int buffer_handler_raw_size(struct buffer *buffer);
+
 /* End of a file */
index 83e1899..fa88612 100644 (file)
@@ -66,8 +66,6 @@ extern struct client_node *client_deactivated_by_fault(struct client_node *clien
 extern void client_reset_fault(struct client_node *client);
 extern const int const client_is_faulted(const struct client_node *client);
 
-extern const int const client_is_activated(const struct client_node *client);
-
 /*!
  * \note
  * For other components which wants to know the state of a client
index 714d3a2..2cc2f2b 100644 (file)
@@ -49,6 +49,8 @@ struct conf {
 
        double slave_ttl;
        double slave_activate_time;
+       double slave_relaunch_time;
+       int slave_relaunch_count;
 
        int max_log_line;
        int max_log_file;
@@ -140,6 +142,8 @@ extern int conf_loader(void);
 #define REPLACE_TAG_APPID      g_conf.replace_tag
 #define SLAVE_TTL              g_conf.slave_ttl
 #define SLAVE_ACTIVATE_TIME    g_conf.slave_activate_time
+#define SLAVE_RELAUNCH_TIME    g_conf.slave_relaunch_time
+#define SLAVE_RELAUNCH_COUNT   g_conf.slave_relaunch_count
 
 #define MAX_LOG_LINE           g_conf.max_log_line
 #define MAX_LOG_FILE           g_conf.max_log_file
diff --git a/include/file_service.h b/include/file_service.h
new file mode 100644 (file)
index 0000000..208f739
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+extern int file_service_init(void);
+extern int file_service_fini(void);
+
+/* End of a file */
index 9cc0885..e60de2b 100644 (file)
@@ -27,6 +27,7 @@ extern int tcb_fd(struct tcb *tcb);
 extern struct service_context *tcb_svc_ctx(struct tcb *tcb);
 extern int tcb_client_type(struct tcb *tcb);
 extern int tcb_client_type_set(struct tcb *tcb, enum tcb_type type);
+extern int tcb_is_valid(struct service_context *svc_ctx, struct tcb *tcb);
 
 extern struct service_context *service_common_create(const char *addr, int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data), void *data);
 extern int service_common_destroy(struct service_context *svc_ctx);
index 26017ad..e74fad7 100644 (file)
@@ -1,6 +1,6 @@
 Name: data-provider-master
 Summary: Master service provider for liveboxes.
-Version: 0.24.23
+Version: 0.25.2
 Release: 1
 Group: HomeTF/Livebox
 License: Flora License
@@ -48,7 +48,17 @@ Keep trace on the life-cycle of the livebox and status of the service providers,
 %setup -q
 
 %build
-cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DPRODUCT=private
+%if 0%{?tizen_build_binary_release_type_eng}
+export CFLAGS="${CFLAGS} -DTIZEN_ENGINEER_MODE"
+export CXXFLAGS="${CXXFLAGS} -DTIZEN_ENGINEER_MODE"
+export FFLAGS="${FFLAGS} -DTIZEN_ENGINEER_MODE"
+%endif
+
+%if 0%{?sec_product_feature_livebox_shm}
+       cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DPRODUCT=baltic
+%else
+       cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DPRODUCT=private
+%endif
 
 CFLAGS="${CFLAGS} -Wall -Winline -Werror" LDFLAGS="${LDFLAGS}" make %{?jobs:-j%jobs}
 
@@ -101,6 +111,7 @@ chmod 640 /opt/dbspace/.livebox.db
 chown 0:5000 /opt/dbspace/.livebox.db-journal
 chmod 640 /opt/dbspace/.livebox.db-journal
 vconftool set -t bool "memory/data-provider-master/started" 0 -i -u 5000 -f -s system::vconf_system
+vconftool set -t string "db/data-provider-master/serveraddr" "/opt/usr/share/live_magazine/.client.socket" -i -u 5000 -f -s system::vconf_system
 echo "Successfully installed. Please start a daemon again manually"
 echo "%{_sysconfdir}/init.d/data-provider-master start"
 
index 7d67b6a..ea35e84 100644 (file)
@@ -517,7 +517,7 @@ static inline int load_shm_buffer(struct buffer_info *info)
        buffer->type = BUFFER_TYPE_SHM;
        buffer->refcnt = id;
        buffer->state = CREATED; /*!< Needless */
-       buffer->info = NULL; /*!< This has not to be used, every process will see this. So, don't try to save anything on here */
+       buffer->info = (void *)size; /*!< Use this field to indicates the size of SHM */
 
        len = strlen(SCHEMA_SHM) + 30; /* strlen("shm://") + 30 */
 
@@ -1327,4 +1327,178 @@ HAPI int buffer_handler_fini(void)
        return LB_STATUS_SUCCESS;
 }
 
+static inline struct buffer *raw_open_file(const char *filename)
+{
+       struct buffer *buffer;
+       int fd;
+       off_t off;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
+               ErrPrint("open: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       off = lseek(fd, 0L, SEEK_END);
+       if (off == (off_t)-1) {
+               ErrPrint("lseek: %s\n", strerror(errno));
+
+               if (close(fd) < 0)
+                       ErrPrint("close: %s\n", strerror(errno));
+
+               return NULL;
+       }
+
+       if (lseek(fd, 0L, SEEK_SET) == (off_t)-1) {
+               ErrPrint("lseek: %s\n", strerror(errno));
+
+               if (close(fd) < 0)
+                       ErrPrint("close: %s\n", strerror(errno));
+
+               return NULL;
+       }
+
+       buffer = calloc(1, sizeof(*buffer) + off);
+       if (!buffer) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+
+               if (close(fd) < 0)
+                       ErrPrint("close: %s\n", strerror(errno));
+
+               return NULL;
+       }
+
+       buffer->state = CREATED;
+       buffer->type = BUFFER_TYPE_FILE;
+       buffer->refcnt = 0;
+       buffer->info = (void *)off;
+
+       if (read(fd, buffer->data, off) < 0) {
+               ErrPrint("read: %s\n", strerror(errno));
+               free(buffer);
+
+               if (close(fd) < 0)
+                       ErrPrint("close: %s\n", strerror(errno));
+
+               return NULL;
+       }
+
+       if (close(fd) < 0)
+               ErrPrint("close: %s\n", strerror(errno));
+
+       return buffer;
+}
+
+static inline int raw_close_file(struct buffer *buffer)
+{
+       free(buffer);
+       return 0;
+}
+
+static inline struct buffer *raw_open_shm(int shm)
+{
+       struct buffer *buffer;
+
+       buffer = (struct buffer *)shmat(shm, NULL, SHM_RDONLY);
+       if (buffer == (struct buffer *)-1) {
+               ErrPrint("shmat: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       return buffer;
+}
+
+static inline int raw_close_shm(struct buffer *buffer)
+{
+       int ret;
+
+       ret = shmdt(buffer);
+       if (ret < 0)
+               ErrPrint("shmdt: %s\n", strerror(errno));
+
+       return ret;
+}
+
+static inline struct buffer *raw_open_pixmap(unsigned int pixmap)
+{
+       struct buffer *buffer;
+
+       buffer = calloc(1, sizeof(*buffer) + sizeof(int));
+       if (!buffer) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       buffer->state = CREATED;
+       buffer->type = BUFFER_TYPE_PIXMAP;
+
+       return buffer;
+}
+
+static inline int raw_close_pixmap(struct buffer *buffer)
+{
+       free(buffer);
+       return 0;
+}
+
+HAPI void *buffer_handler_raw_data(struct buffer *buffer)
+{
+       if (!buffer || buffer->state != CREATED)
+               return NULL;
+
+       return buffer->data;
+}
+
+HAPI int buffer_handler_raw_size(struct buffer *buffer)
+{
+       if (!buffer || buffer->state != CREATED)
+               return -EINVAL;
+
+       return (int)buffer->info;
+}
+
+HAPI struct buffer *buffer_handler_raw_open(enum buffer_type buffer_type, void *resource)
+{
+       struct buffer *handle;
+
+       switch (buffer_type) {
+       case BUFFER_TYPE_SHM:
+               handle = raw_open_shm((int)resource);
+               break;
+       case BUFFER_TYPE_FILE:
+               handle = raw_open_file(resource);
+               break;
+       case BUFFER_TYPE_PIXMAP:
+               handle = raw_open_pixmap((unsigned int)resource);
+               break;
+       default:
+               handle = NULL;
+               break;
+       }
+
+       return handle;
+}
+
+HAPI int buffer_handler_raw_close(struct buffer *buffer)
+{
+       int ret;
+
+       switch (buffer->type) {
+       case BUFFER_TYPE_SHM:
+               ret = raw_close_shm(buffer);
+               break;
+       case BUFFER_TYPE_FILE:
+               ret = raw_close_file(buffer);
+               break;
+       case BUFFER_TYPE_PIXMAP:
+               ret = raw_close_pixmap(buffer);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
 /* End of a file */
index 64c9920..32caae2 100644 (file)
@@ -252,9 +252,9 @@ HAPI struct client_node *client_create(pid_t pid, int handle)
        struct client_node *client;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (client) {
-               ErrPrint("Client %d is already exists\n", pid);
+               ErrPrint("Client %d(%d) is already exists\n", pid, handle);
                return client;
        }
 
@@ -594,11 +594,6 @@ HAPI void client_fini(void)
        }
 }
 
-HAPI const int const client_is_activated(const struct client_node *client)
-{
-       return client ? (client->pid != (pid_t)-1) : 1;
-}
-
 HAPI int client_global_event_handler_add(enum client_global_event event_type, int (*cb)(struct client_node *client, void *data), void *data)
 {
        struct global_event_handler *handler;
@@ -774,7 +769,7 @@ HAPI int client_broadcast(struct inst_info *inst, struct packet *packet)
 
        list = inst ? instance_client_list(inst) : s_info.client_list;
        EINA_LIST_FOREACH(list, l, client) {
-               if (client_pid(client) < 0) {
+               if (client_pid(client) == -1) {
                        ErrPrint("Client[%p] has PID[%d]\n", client, client_pid(client));
                        continue;
                }
index 78ca437..6276b99 100644 (file)
@@ -116,11 +116,6 @@ static Eina_Bool command_consumer_cb(void *data)
                goto out;
        }
 
-       if (!client_is_activated(command->client)) {
-               ErrPrint("Client[%p] is not activated, destroy this command\n", command->client);
-               goto out;
-       }
-
        if (client_is_faulted(command->client)) {
                ErrPrint("Client[%p] is faulted, discard command\n", command->client);
                goto out;
@@ -128,7 +123,7 @@ static Eina_Bool command_consumer_cb(void *data)
 
        rpc = client_data(command->client, RPC_TAG);
        if (!rpc) {
-               ErrPrint("Invalid command\n");
+               ErrPrint("Client is not activated\n");
                goto out;
        }
 
index 5ff4739..e86b3f9 100644 (file)
@@ -56,6 +56,8 @@ HAPI struct conf g_conf = {
 
        .slave_ttl = 30.0f,
        .slave_activate_time = 30.0f,
+       .slave_relaunch_time = 3.0f,
+       .slave_relaunch_count = 3,
 
        .max_log_line = 1000,
        .max_log_file = 3,
@@ -224,6 +226,19 @@ static void slave_activate_time_handler(char *buffer)
        DbgPrint("Slave activate time: %lf\n", g_conf.slave_activate_time);
 }
 
+static void slave_relaunch_time_handler(char *buffer)
+{
+       if (sscanf(buffer, "%lf", &g_conf.slave_relaunch_time) != 1)
+               ErrPrint("Failed to parse the slave_activate_time\n");
+       DbgPrint("Slave relaunch time: %lf\n", g_conf.slave_relaunch_time);
+}
+
+static void slave_relaunch_count_handler(char *buffer)
+{
+       if (sscanf(buffer, "%d", &g_conf.slave_relaunch_count) != 1)
+               ErrPrint("Failed to parse the max_log_line\n");
+}
+
 static void max_log_line_handler(char *buffer)
 {
        if (sscanf(buffer, "%d", &g_conf.max_log_line) != 1)
@@ -391,6 +406,14 @@ HAPI int conf_loader(void)
                        .handler = slave_activate_time_handler,
                },
                {
+                       .name = "slave_relaunch_time",
+                       .handler = slave_relaunch_time_handler,
+               },
+               {
+                       .name = "slave_relaunch_count",
+                       .handler = slave_relaunch_count_handler,
+               },
+               {
                        .name = "max_log_line",
                        .handler = max_log_line_handler,
                },
index 75a9796..9d3eb39 100644 (file)
@@ -86,14 +86,11 @@ HAPI int critical_log(const char *func, int line, const char *fmt, ...)
 {
        va_list ap;
        int ret;
-       int status;
 
        if (!s_info.fp)
                return LB_STATUS_ERROR_IO;
 
-       status = pthread_mutex_lock(&s_info.cri_lock);
-       if (status != 0)
-               ErrPrint("lock: %s\n", strerror(status));
+       CRITICAL_SECTION_BEGIN(&s_info.cri_lock);
 
        fprintf(s_info.fp, "%lf [%s:%d] ", util_timestamp(), util_basename((char *)func), line);
 
@@ -106,10 +103,7 @@ HAPI int critical_log(const char *func, int line, const char *fmt, ...)
        s_info.nr_of_lines++;
        rotate_log();
 
-       status = pthread_mutex_unlock(&s_info.cri_lock);
-       if (status != 0)
-               ErrPrint("unlock: %s\n", strerror(status));
-
+       CRITICAL_SECTION_END(&s_info.cri_lock);
        return ret;
 }
 
diff --git a/src/file_service.c b/src/file_service.c
new file mode 100644 (file)
index 0000000..15c2304
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <Eina.h>
+
+#include <dlog.h>
+
+#include <livebox-errno.h>
+#include <packet.h>
+#include <com-core.h>
+
+#include "file_service.h"
+#include "service_common.h"
+#include "debug.h"
+#include "util.h"
+#include "conf.h"
+#include "buffer_handler.h"
+
+#define FILE_SERVICE_ADDR      "remote://:8209"
+#define FILE_PUSH_ADDR         "remote://:8210"
+
+#define PUSH_EXIT      'e'
+#define PUSH_ITEM      'i'
+
+#define PKT_CHUNKSZ    4096
+
+static struct info {
+       struct service_context *svc_ctx;
+
+       pthread_t push_thid;
+
+       Eina_List *request_list;
+       pthread_mutex_t request_list_lock;
+
+       int request_pipe[PIPE_MAX];
+} s_info = {
+       .svc_ctx = NULL,
+       .request_list = NULL,
+       .request_list_lock = PTHREAD_MUTEX_INITIALIZER,
+       .request_pipe = { 0, },
+};
+
+struct request_item {
+       enum {
+               REQUEST_TYPE_FILE = 0x00,
+               REQUEST_TYPE_SHM = 0x01,
+               REQUEST_TYPE_PIXMAP = 0x02,
+               REQUEST_TYPE_MAX = 0x02,
+       } type;
+       union {
+               char *filename;
+               int shm;
+               unsigned int pixmap;
+       } data;
+       struct tcb *tcb;
+};
+
+typedef int (*send_data_func_t)(int fd, const struct request_item *item);
+
+/*!
+ * File transfer header.
+ * This must should be shared with client.
+ */
+struct burst_head {
+       off_t size;
+       int flen;
+       char fname[];
+};
+
+struct burst_data {
+       int size;
+       char data[];
+};
+
+static inline struct request_item *create_request_item(struct tcb *tcb, int type, void *data)
+{
+       struct request_item *item;
+
+       item = malloc(sizeof(*item));
+       if (!item) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       switch (type) {
+       case REQUEST_TYPE_FILE:
+               item->data.filename = strdup(data);
+               if (!item->data.filename) {
+                       ErrPrint("Heap: %s\n", strerror(errno));
+                       free(item);
+                       return NULL;
+               }
+               break;
+       case REQUEST_TYPE_PIXMAP:
+               item->data.pixmap = (unsigned int)data;
+               break;
+       case REQUEST_TYPE_SHM:
+               item->data.shm = (int)data;
+               break;
+       default:
+               return NULL;
+       }
+
+       item->type = type;
+       item->tcb = tcb;
+       return item;
+}
+
+static inline int destroy_request_item(struct request_item *item)
+{
+       switch (item->type) {
+       case REQUEST_TYPE_FILE:
+               free(item->data.filename);
+               break;
+       case REQUEST_TYPE_SHM:
+       case REQUEST_TYPE_PIXMAP:
+               break;
+       default:
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       free(item);
+       return LB_STATUS_SUCCESS;
+}
+
+static int request_file_handler(struct tcb *tcb, struct packet *packet, struct request_item **item)
+{
+       const char *filename;
+
+       if (packet_get(packet, "s", &filename) != 1) {
+               ErrPrint("Invalid packet\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       *item = create_request_item(tcb, REQUEST_TYPE_FILE, (void *)filename);
+       return *item ? LB_STATUS_SUCCESS : LB_STATUS_ERROR_MEMORY;
+}
+
+static int request_pixmap_handler(struct tcb *tcb, struct packet *packet, struct request_item **item)
+{
+       unsigned int pixmap;
+
+       if (packet_get(packet, "i", &pixmap) != 1) {
+               ErrPrint("Invalid packet\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       if (pixmap == 0) {
+               ErrPrint("pixmap is not valid\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       /*!
+        * \TODO
+        * Attach to pixmap and copy its data to the client
+        */
+       *item = create_request_item(tcb, REQUEST_TYPE_PIXMAP, (void *)pixmap);
+       return *item ? LB_STATUS_SUCCESS : LB_STATUS_ERROR_MEMORY;
+}
+
+static int request_shm_handler(struct tcb *tcb, struct packet *packet, struct request_item **item)
+{
+       int shm;
+
+       if (packet_get(packet, "i", &shm) != 1) {
+               ErrPrint("Invalid packet\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       if (shm < 0) {
+               ErrPrint("shm is not valid: %d\n", shm);
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       /*!
+        * \TODO
+        * Attach to SHM and copy its buffer to the client
+        */
+       *item = create_request_item(tcb, REQUEST_TYPE_SHM, (void *)shm);
+       return *item ? LB_STATUS_SUCCESS : LB_STATUS_ERROR_MEMORY;
+}
+
+/* SERVER THREAD */
+static int service_thread_main(struct tcb *tcb, struct packet *packet, void *data)
+{
+       const char *cmd;
+       char ch = PUSH_ITEM;
+       int ret;
+       int i;
+       struct request_item *item;
+       struct packet *reply;
+       struct {
+               const char *cmd;
+               int (*request_handler)(struct tcb *tcb, struct packet *packet, struct request_item **item);
+       } cmd_table[] = {
+               {
+                       .cmd = "request,file",
+                       .request_handler = request_file_handler,
+               },
+               {
+                       .cmd = "request,pixmap",
+                       .request_handler = request_pixmap_handler,
+               },
+               {
+                       .cmd = "request,shm",
+                       .request_handler = request_shm_handler,
+               },
+               {
+                       .cmd = NULL,
+                       .request_handler = NULL,
+               },
+       };
+
+       if (!packet) {
+               DbgPrint("TCB %p is disconnected\n", tcb);
+               return LB_STATUS_SUCCESS;
+       }
+
+       cmd = packet_command(packet);
+       if (!cmd) {
+               ErrPrint("Invalid packet. cmd is not valid\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       switch (packet_type(packet)) {
+       case PACKET_REQ:
+               for (i = 0; cmd_table[i].cmd; i++) {
+                       /*!
+                        * Protocol sequence
+                        * FILE REQUEST COMMAND (Client -> Server)
+                        * REPLY FOR REQUEST (Client <- Server)
+                        * PUSH FILE (Client <- Server)
+                        *
+                        * Client & Server must has to keep this communication sequence.
+                        */
+                       if (strcmp(cmd, cmd_table[i].cmd))
+                               continue;
+
+                       item = NULL;
+                       ret = cmd_table[i].request_handler(tcb, packet, &item);
+
+                       reply = packet_create_reply(packet, "i", ret);
+                       if (!reply) {
+                               ErrPrint("Failed to create a reply packet\n");
+                               break;
+                       }
+
+                       if (service_common_unicast_packet(tcb, reply) < 0)
+                               ErrPrint("Unable to send reply packet\n");
+
+                       packet_destroy(reply);
+
+                       /*!
+                        * \note
+                        * After send the reply packet, file push thread can sending a file
+                        */
+                       if (ret != LB_STATUS_SUCCESS || !item)
+                               break;
+
+                       CRITICAL_SECTION_BEGIN(&s_info.request_list_lock);
+                       s_info.request_list = eina_list_append(s_info.request_list, item);
+                       CRITICAL_SECTION_END(&s_info.request_list_lock);
+
+                       ret = write(s_info.request_pipe[PIPE_WRITE], &ch, sizeof(ch));
+                       if (ret < 0) {
+                               ErrPrint("write: %s\n", strerror(errno));
+
+                               CRITICAL_SECTION_BEGIN(&s_info.request_list_lock);
+                               s_info.request_list = eina_list_remove(s_info.request_list, item);
+                               CRITICAL_SECTION_END(&s_info.request_list_lock);
+
+                               destroy_request_item(item);
+                               /*!
+                                * \note for the client
+                                * In this case, the client can waiting files forever.
+                                * So the client must has to wait only a few seconds.
+                                * If the client could not get the any data in that time,
+                                * it should cancel the waiting.
+                                */
+                       }
+               }
+
+               break;
+       case PACKET_REQ_NOACK:
+       case PACKET_ACK:
+               /* File service has no this case, it is passive service type */
+               ErrPrint("Invalid packet.\n");
+               break;
+       default:
+               break;
+       }
+
+       return LB_STATUS_SUCCESS;
+}
+
+static int send_file(int handle, const struct request_item *item)
+{
+       struct burst_head *head;
+       struct burst_data *body;
+       int pktsz;
+       int flen;
+       off_t fsize;
+       int fd;
+       int ret = 0;
+
+       /* TODO: push a file to the client */
+       fd = open(item->data.filename, O_RDONLY);
+       if (fd < 0) {
+               ErrPrint("open: %s\n", strerror(errno));
+               return -EIO;
+       }
+
+       flen = strlen(item->data.filename);
+       if (flen == 0) {
+               ret = -EINVAL;
+               goto errout;
+       }
+
+       pktsz = sizeof(*head) + flen + 1;
+
+       head = malloc(pktsz);
+       if (!head) {
+               ErrPrint("heap: %s\n", strerror(errno));
+               ret = -ENOMEM;
+               goto errout;
+       }
+
+       fsize = lseek(fd, 0L, SEEK_END);
+       if (fsize == (off_t)-1) {
+               ErrPrint("heap: %s\n", strerror(errno));
+               free(head);
+               ret = -EIO;
+               goto errout;
+       }
+
+       head->flen = flen;
+       head->size = fsize;
+       strcpy(head->fname, item->data.filename);
+
+       /* Anytime we can fail to send packet */
+       ret = com_core_send(handle, (void *)head, pktsz, 2.0f);
+       free(head);
+       if (ret < 0) {
+               ret = -EFAULT;
+               goto errout;
+       }
+
+       if (lseek(fd, 0L, SEEK_SET) == (off_t)-1) {
+               ErrPrint("seek: %s\n", strerror(errno));
+
+               body = malloc(sizeof(*body));
+               if (!body) {
+                       ErrPrint("Heap: %s\n", strerror(errno));
+                       return -ENOMEM;
+               }
+
+               body->size = -1;
+               ret = com_core_send(handle, (void *)body, sizeof(*body), 2.0f);
+               free(body);
+
+               if (ret < 0)
+                       ret = -EFAULT;
+               else
+                       ret = -EIO;
+
+               goto errout;
+       }
+
+       body = malloc(PKT_CHUNKSZ + sizeof(*body));
+       if (!body) {
+               ErrPrint("heap: %s\n", strerror(errno));
+               goto errout;
+       }
+
+       /* Burst pushing. */
+       while (fsize > 0) {
+               if (fsize > PKT_CHUNKSZ) {
+                       body->size = PKT_CHUNKSZ;
+                       fsize -= PKT_CHUNKSZ;
+               } else {
+                       body->size = fsize;
+                       fsize = 0;
+               }
+
+               pktsz = sizeof(*body) + body->size;
+
+               ret = read(fd, body->data, body->size); 
+               if (ret < 0) {
+                       ErrPrint("read: %s\n", strerror(errno));
+                       ret = -EIO;
+                       break;
+               }
+
+               /* Send BODY */
+               ret = com_core_send(handle, (void *)body, pktsz, 2.0f);
+               if (ret != pktsz) {
+                       ret = -EFAULT;
+                       break;
+               }
+       }
+
+       /* Send EOF */
+       body->size = -1;
+       ret = com_core_send(handle, (void *)body, sizeof(*body), 2.0f);
+       if (ret < 0)
+               ret = -EFAULT;
+
+       free(body);
+
+errout:
+       if (close(fd) < 0)
+               ErrPrint("close: %s\n", strerror(errno));
+
+       return ret;
+}
+
+static int send_buffer(int handle, const struct request_item *item)
+{
+       struct buffer *buffer;
+       struct burst_head *head;
+       struct burst_data *body;
+       char *data;
+       int pktsz;
+       int ret;
+       int size;
+       int offset;
+       int type;
+
+       if (item->type == REQUEST_TYPE_SHM)
+               type = BUFFER_TYPE_SHM;
+       else
+               type = BUFFER_TYPE_PIXMAP;
+
+       buffer = buffer_handler_raw_open(type, (void *)item->data.shm);
+       if (!buffer)
+               return -EINVAL;
+
+       pktsz = sizeof(*head);
+
+       head = malloc(pktsz);
+       if (!head) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               (void)buffer_handler_raw_close(buffer);
+               return -ENOMEM;
+       }
+
+       size = head->size = buffer_handler_raw_size(buffer);
+       head->flen = 0;
+
+       /* Anytime we can fail to send packet */
+       ret = com_core_send(handle, (void *)head, pktsz, 2.0f);
+       free(head);
+       if (ret < 0) {
+               ret = -EFAULT;
+               goto errout;
+       }
+
+       body = malloc(sizeof(*body) + PKT_CHUNKSZ);
+       if (!body) {
+               ret = -ENOMEM;
+               goto errout;
+       }
+
+       data = (char *)buffer_handler_raw_data(buffer);
+       offset = 0;
+       while (offset < size) {
+               body->size = size - offset;
+
+               if (body->size > PKT_CHUNKSZ)
+                       body->size = PKT_CHUNKSZ;
+
+               memcpy(body->data, data, body->size);
+               pktsz = sizeof(*body) + body->size;
+
+               ret = com_core_send(handle, (void *)body, pktsz, 2.0f);
+               if (ret < 0) {
+                       ret = -EFAULT;
+                       break;
+               }
+
+               offset += body->size;
+       }
+
+       free(body);
+
+errout:
+       (void)buffer_handler_raw_close(buffer);
+       return ret;
+}
+
+static void *push_main(void *data)
+{
+       fd_set set;
+       int ret;
+       char ch;
+       struct request_item *item;
+       int conn_fd;
+       send_data_func_t send_data[] = {
+               send_file,
+               send_buffer,
+               send_buffer,
+       };
+
+       while (1) {
+               FD_ZERO(&set);
+               FD_SET(s_info.request_pipe[PIPE_READ], &set);
+
+               ret = select(s_info.request_pipe[PIPE_READ] + 1, &set, NULL, NULL, NULL);
+               if (ret < 0) {
+                       ret = -errno;
+                       if (errno == EINTR) {
+                               ErrPrint("INTERRUPTED\n");
+                               ret = 0;
+                               continue;
+                       }
+                       ErrPrint("Error: %s\n", strerror(errno));
+                       break;
+               } else if (ret == 0) {
+                       ErrPrint("Timeout\n");
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+
+               if (!FD_ISSET(s_info.request_pipe[PIPE_READ], &set)) {
+                       DbgPrint("Unknown data\n");
+                       ret = -EINVAL;
+                       break;
+               }
+
+               ret = read(s_info.request_pipe[PIPE_READ], &ch, sizeof(ch));
+               if (ret != sizeof(ch)) {
+                       ErrPrint("read: %s\n", strerror(errno));
+                       ret = -EFAULT;
+                       break;
+               }
+
+               if (ch == PUSH_EXIT) {
+                       DbgPrint("Thread is terminating\n");
+                       ret = -ECANCELED;
+                       break;
+               }
+
+               CRITICAL_SECTION_BEGIN(&s_info.request_list_lock);
+               item = eina_list_nth(s_info.request_list, 0);
+               s_info.request_list = eina_list_remove(s_info.request_list, item);
+               CRITICAL_SECTION_END(&s_info.request_list_lock);
+
+               if (!item) {
+                       ErrPrint("Request item is not valid\n");
+                       continue;
+               }
+
+               /* Validate the TCB? */
+               conn_fd = tcb_is_valid(s_info.svc_ctx, item->tcb);
+               if (conn_fd < 0) {
+                       ErrPrint("TCB is not valid\n");
+                       destroy_request_item(item);
+                       continue;
+               }
+
+               /*
+                * \note
+                * From now, we cannot believe the conn_fd.
+                * It can be closed any time.
+                * Even though we using it.
+                */
+               if (item->type < REQUEST_TYPE_MAX && item->type >= 0)
+                       (void)send_data[item->type](conn_fd, item);
+               else
+                       ErrPrint("Invalid type\n");
+
+               destroy_request_item(item);
+       }
+
+       return (void *)ret;
+}
+
+/* MAIN THREAD */
+int file_service_init(void)
+{
+       int status;
+
+       if (s_info.svc_ctx) {
+               ErrPrint("Already initialized\n");
+               return LB_STATUS_ERROR_ALREADY;
+       }
+
+       if (pipe2(s_info.request_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {
+               ErrPrint("pipe: %s\n", strerror(errno));
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       status = pthread_mutex_init(&s_info.request_list_lock, NULL);
+       if (status != 0) {
+               ErrPrint("Failed to create lock: %s\n", strerror(status));
+               CLOSE_PIPE(s_info.request_pipe);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       s_info.svc_ctx = service_common_create(FILE_SERVICE_ADDR, service_thread_main, NULL);
+       if (!s_info.svc_ctx) {
+               ErrPrint("Unable to activate service thread\n");
+
+               status = pthread_mutex_destroy(&s_info.request_list_lock);
+               if (status != 0)
+                       ErrPrint("Destroy lock: %s\n", strerror(status));
+
+               CLOSE_PIPE(s_info.request_pipe);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       status = pthread_create(&s_info.push_thid, NULL, push_main, NULL);
+       if (status != 0) {
+               ErrPrint("Failed to create a push service: %s\n", strerror(status));
+
+               service_common_destroy(s_info.svc_ctx);
+               s_info.svc_ctx = NULL;
+
+               status = pthread_mutex_destroy(&s_info.request_list_lock);
+               if (status != 0)
+                       ErrPrint("Destroy lock: %s\n", strerror(status));
+
+               CLOSE_PIPE(s_info.request_pipe);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       /*!
+        * \note
+        * Remote service doesn't need to set the additional SMAK label.
+        */
+
+       DbgPrint("Successfully initiated\n");
+       return LB_STATUS_SUCCESS;
+}
+
+/* MAIN THREAD */
+int file_service_fini(void)
+{
+       struct request_item *item;
+       int status;
+       char ch;
+       void *retval;
+
+       if (!s_info.svc_ctx)
+               return LB_STATUS_ERROR_INVALID;
+
+       ch = PUSH_EXIT;
+       status = write(s_info.request_pipe[PIPE_WRITE], &ch, sizeof(ch));
+       if (status != sizeof(ch)) {
+               ErrPrint("write: %s\n", strerror(errno));
+               /* Forcely terminate the thread */
+               status = pthread_cancel(s_info.push_thid);
+               if (status != 0)
+                       ErrPrint("cancel: %s\n", strerror(status));
+       }
+
+       status = pthread_join(s_info.push_thid, &retval);
+       if (status != 0)
+               ErrPrint("join: %s\n", strerror(status));
+
+       CRITICAL_SECTION_BEGIN(&s_info.request_list_lock);
+       EINA_LIST_FREE(s_info.request_list, item) {
+               destroy_request_item(item);
+       }
+       CRITICAL_SECTION_END(&s_info.request_list_lock);
+
+       service_common_destroy(s_info.svc_ctx);
+       s_info.svc_ctx = NULL;
+
+       status = pthread_mutex_destroy(&s_info.request_list_lock);
+       if (status != 0)
+               ErrPrint("destroy mutex: %s\n", strerror(status));
+
+       CLOSE_PIPE(s_info.request_pipe);
+
+       DbgPrint("Successfully Finalized\n");
+       return LB_STATUS_SUCCESS;
+}
+
+/* End of a file */
index b8441bf..b806925 100644 (file)
@@ -56,6 +56,7 @@
 #include "notification_service.h"
 #include "utility_service.h"
 #include "badge_service.h"
+#include "file_service.h"
 
 #if defined(FLOG)
 FILE *__file_log_fp;
@@ -125,6 +126,8 @@ static inline int app_create(void)
        utility_service_init();
        script_init();
 
+       file_service_init();
+
        return 0;
 }
 
@@ -132,6 +135,9 @@ static inline int app_terminate(void)
 {
        int ret;
 
+       ret = file_service_fini();
+       DbgPrint("Finalize the file service: %d\n", ret);
+
        ret = server_fini();
        DbgPrint("Finalize server: %d\n", ret);
 
index f8404fd..365d06b 100644 (file)
@@ -57,11 +57,13 @@ static struct info {
        int client_fd;
        int service_fd;
        int slave_fd;
+       int remote_client_fd;
 } s_info = {
        .info_fd = -1,
        .client_fd = -1,
        .service_fd = -1,
        .slave_fd = -1,
+       .remote_client_fd = -1,
 };
 
 /* Share this with provider */
@@ -460,7 +462,7 @@ static struct packet *client_acquire(pid_t pid, int handle, const struct packet
        double timestamp;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (client) {
                ErrPrint("Client is already exists %d\n", pid);
                ret = LB_STATUS_ERROR_EXIST;
@@ -498,7 +500,7 @@ static struct packet *cilent_release(pid_t pid, int handle, const struct packet
        struct packet *result;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -560,7 +562,7 @@ static struct packet *client_clicked(pid_t pid, int handle, const struct packet
        int ret;
        struct inst_info *inst;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                goto out;
@@ -596,7 +598,7 @@ static struct packet *client_update_mode(pid_t pid, int handle, const struct pac
        int ret;
        struct inst_info *inst;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_INVALID;
@@ -643,7 +645,7 @@ static struct packet *client_text_signal(pid_t pid, int handle, const struct pac
        struct inst_info *inst;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -702,7 +704,7 @@ static struct packet *client_delete(pid_t pid, int handle, const struct packet *
        struct inst_info *inst;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -783,7 +785,7 @@ static struct packet *client_resize(pid_t pid, int handle, const struct packet *
        struct inst_info *inst;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -838,7 +840,7 @@ static struct packet *client_new(pid_t pid, int handle, const struct packet *pac
        char *lb_pkgname;
        char *mainappid;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -915,7 +917,7 @@ static struct packet *client_change_visibility(pid_t pid, int handle, const stru
        int ret;
        struct inst_info *inst;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -958,7 +960,7 @@ static struct packet *client_set_period(pid_t pid, int handle, const struct pack
        int ret;
        struct inst_info *inst;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1007,7 +1009,7 @@ static struct packet *client_change_group(pid_t pid, int handle, const struct pa
        struct inst_info *inst;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1057,7 +1059,7 @@ static struct packet *client_pd_mouse_enter(pid_t pid, int handle, const struct
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1118,7 +1120,7 @@ static struct packet *client_pd_mouse_leave(pid_t pid, int handle, const struct
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1179,7 +1181,7 @@ static struct packet *client_pd_mouse_down(pid_t pid, int handle, const struct p
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1240,7 +1242,7 @@ static struct packet *client_pd_mouse_up(pid_t pid, int handle, const struct pac
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1301,7 +1303,7 @@ static struct packet *client_pd_mouse_move(pid_t pid, int handle, const struct p
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1362,7 +1364,7 @@ static struct packet *client_lb_mouse_move(pid_t pid, int handle, const struct p
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1429,7 +1431,7 @@ static struct packet *client_lb_mouse_set(pid_t pid, int handle, const struct pa
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1485,7 +1487,7 @@ static struct packet *client_lb_mouse_unset(pid_t pid, int handle, const struct
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1531,7 +1533,7 @@ static struct packet *client_pd_mouse_set(pid_t pid, int handle, const struct pa
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1588,7 +1590,7 @@ static struct packet *client_pd_mouse_unset(pid_t pid, int handle, const struct
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1634,7 +1636,7 @@ static struct packet *client_lb_mouse_enter(pid_t pid, int handle, const struct
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1695,7 +1697,7 @@ static struct packet *client_lb_mouse_leave(pid_t pid, int handle, const struct
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1756,7 +1758,7 @@ static struct packet *client_lb_mouse_down(pid_t pid, int handle, const struct p
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1817,7 +1819,7 @@ static struct packet *client_lb_mouse_up(pid_t pid, int handle, const struct pac
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1879,7 +1881,7 @@ static struct packet *client_pd_access_action_up(pid_t pid, int handle, const st
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -1962,7 +1964,7 @@ static struct packet *client_pd_access_action_down(pid_t pid, int handle, const
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2045,7 +2047,7 @@ static struct packet *client_pd_access_scroll_down(pid_t pid, int handle, const
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2128,7 +2130,7 @@ static struct packet *client_pd_access_scroll_move(pid_t pid, int handle, const
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2211,7 +2213,7 @@ static struct packet *client_pd_access_scroll_up(pid_t pid, int handle, const st
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2294,7 +2296,7 @@ static struct packet *client_pd_access_unhighlight(pid_t pid, int handle, const
        int ret;
        double timestamp;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2376,7 +2378,7 @@ static struct packet *client_pd_access_hl(pid_t pid, int handle, const struct pa
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2459,7 +2461,7 @@ static struct packet *client_pd_access_hl_prev(pid_t pid, int handle, const stru
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2542,7 +2544,7 @@ static struct packet *client_pd_access_hl_next(pid_t pid, int handle, const stru
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2631,7 +2633,7 @@ static struct packet *client_pd_access_activate(pid_t pid, int handle, const str
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2713,7 +2715,7 @@ static struct packet *client_pd_key_down(pid_t pid, int handle, const struct pac
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2770,7 +2772,7 @@ static struct packet *client_pause_request(pid_t pid, int handle, const struct p
        double timestamp;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is paused - manually reported\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2799,7 +2801,7 @@ static struct packet *client_resume_request(pid_t pid, int handle, const struct
        double timestamp;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                goto out;
@@ -2832,7 +2834,7 @@ static struct packet *client_pd_key_up(pid_t pid, int handle, const struct packe
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2896,7 +2898,7 @@ static struct packet *client_lb_access_hl(pid_t pid, int handle, const struct pa
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -2979,7 +2981,7 @@ static struct packet *client_lb_access_hl_prev(pid_t pid, int handle, const stru
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3062,7 +3064,7 @@ static struct packet *client_lb_access_hl_next(pid_t pid, int handle, const stru
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3145,7 +3147,7 @@ static struct packet *client_lb_access_action_up(pid_t pid, int handle, const st
        int x;
        int y;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exist\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3235,7 +3237,7 @@ static struct packet *client_lb_access_action_down(pid_t pid, int handle, const
        int x;
        int y;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exist\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3325,7 +3327,7 @@ static struct packet *client_lb_access_unhighlight(pid_t pid, int handle, const
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3408,7 +3410,7 @@ static struct packet *client_lb_access_scroll_down(pid_t pid, int handle, const
        int x;
        int y;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exist\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3498,7 +3500,7 @@ static struct packet *client_lb_access_scroll_move(pid_t pid, int handle, const
        int x;
        int y;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exist\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3588,7 +3590,7 @@ static struct packet *client_lb_access_scroll_up(pid_t pid, int handle, const st
        int x;
        int y;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exist\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3678,7 +3680,7 @@ static struct packet *client_lb_access_activate(pid_t pid, int handle, const str
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3762,7 +3764,7 @@ static struct packet *client_lb_key_down(pid_t pid, int handle, const struct pac
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3826,7 +3828,7 @@ static struct packet *client_lb_key_up(pid_t pid, int handle, const struct packe
        struct inst_info *inst;
        const struct pkg_info *pkg;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -3897,7 +3899,7 @@ static struct packet *client_lb_acquire_pixmap(pid_t pid, int handle, const stru
        void *buf_ptr;
        struct buffer_info *buffer;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                goto out;
@@ -3969,7 +3971,7 @@ static struct packet *client_lb_release_pixmap(pid_t pid, int handle, const stru
        void *buf_ptr;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                goto out;
@@ -4011,7 +4013,7 @@ static struct packet *client_pd_acquire_pixmap(pid_t pid, int handle, const stru
        void *buf_ptr;
        struct buffer_info *buffer;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                goto out;
@@ -4079,7 +4081,7 @@ static struct packet *client_pd_release_pixmap(pid_t pid, int handle, const stru
        void *buf_ptr;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                goto out;
@@ -4119,7 +4121,7 @@ static struct packet *client_pinup_changed(pid_t pid, int handle, const struct p
        int ret;
        struct inst_info *inst;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4221,7 +4223,7 @@ static struct packet *client_pd_move(pid_t pid, int handle, const struct packet
        double y = 0.0f;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4342,7 +4344,7 @@ static struct packet *client_create_pd(pid_t pid, int handle, const struct packe
 
        DbgPrint("PERF_DBOX\n");
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4556,7 +4558,7 @@ static struct packet *client_destroy_pd(pid_t pid, int handle, const struct pack
 
        DbgPrint("PERF_DBOX\n");
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4742,7 +4744,7 @@ static struct packet *client_activate_package(pid_t pid, int handle, const struc
        int ret;
        struct pkg_info *info;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4792,7 +4794,7 @@ static struct packet *client_subscribed(pid_t pid, int handle, const struct pack
        struct client_node *client;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4832,7 +4834,7 @@ static struct packet *client_delete_cluster(pid_t pid, int handle, const struct
        struct packet *result;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -4911,7 +4913,7 @@ static struct packet *client_update(pid_t pid, int handle, const struct packet *
        const char *id;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Cilent %d is not exists\n", pid);
                goto out;
@@ -4951,7 +4953,7 @@ static struct packet *client_refresh_group(pid_t pid, int handle, const struct p
        Eina_List *info_list;
        Eina_List *l;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Cilent %d is not exists\n", pid);
                goto out;
@@ -5000,7 +5002,7 @@ static struct packet *client_delete_category(pid_t pid, int handle, const struct
        struct packet *result;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -5040,7 +5042,7 @@ static struct packet *client_unsubscribed(pid_t pid, int handle, const struct pa
        struct client_node *client;
        int ret;
 
-       client = client_find_by_pid(pid);
+       client = client_find_by_rpc_handle(handle);
        if (!client) {
                ErrPrint("Client %d is not exists\n", pid);
                ret = LB_STATUS_ERROR_NOT_EXIST;
@@ -6892,6 +6894,15 @@ HAPI int server_init(void)
        if (s_info.client_fd < 0)
                ErrPrint("Failed to create a client socket\n");
 
+       /*!
+        * \note
+        * remote://:8208
+        * Skip address to use the NULL.
+        */
+       s_info.remote_client_fd = com_core_packet_server_init("remote://:"CLIENT_PORT, s_client_table);
+       if (s_info.client_fd < 0)
+               ErrPrint("Failed to create a remote client socket\n");
+
        s_info.service_fd = com_core_packet_server_init(SERVICE_SOCKET, s_service_table);
        if (s_info.service_fd < 0)
                ErrPrint("Faild to create a service socket\n");
@@ -6928,6 +6939,11 @@ HAPI int server_fini(void)
                s_info.client_fd = -1;
        }
 
+       if (s_info.remote_client_fd > 0) {
+               com_core_packet_server_fini(s_info.remote_client_fd);
+               s_info.remote_client_fd = -1;
+       }
+
        if (s_info.service_fd > 0) {
                com_core_packet_server_fini(s_info.service_fd);
                s_info.service_fd = -1;
index d240bed..ea62e33 100644 (file)
@@ -64,6 +64,7 @@ struct service_context {
        int fd; /*!< Server socket handle */
 
        Eina_List *tcb_list; /*!< TCB list, list of every thread for client connections */
+       pthread_mutex_t tcb_list_lock;
 
        Eina_List *packet_list;
        pthread_mutex_t packet_list_lock;
@@ -357,7 +358,9 @@ static inline struct tcb *tcb_create(struct service_context *svc_ctx, int fd)
                return NULL;
        }
 
+       CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
        svc_ctx->tcb_list = eina_list_append(svc_ctx->tcb_list, tcb);
+       CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
        return tcb;
 }
 
@@ -407,7 +410,9 @@ static inline void tcb_destroy(struct service_context *svc_ctx, struct tcb *tcb)
        int status;
        char ch = EVT_END_CH;
 
+       CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
        svc_ctx->tcb_list = eina_list_remove(svc_ctx->tcb_list, tcb);
+       CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
        /*!
         * ASSERT(tcb->fd >= 0);
         * Close the connection, and then collecting the return value of thread
@@ -555,32 +560,6 @@ static void *server_main(void *data)
                        }
                } 
 
-               if (FD_ISSET(svc_ctx->tcb_pipe[PIPE_READ], &set)) {
-                       if (read(svc_ctx->tcb_pipe[PIPE_READ], &tcb, sizeof(tcb)) != sizeof(tcb)) {
-                               ErrPrint("Unable to read pipe: %s\n", strerror(errno));
-                               ret = -EFAULT;
-                               break;
-                       }
-
-                       if (!tcb) {
-                               ErrPrint("Terminate service thread\n");
-                               ret = -ECANCELED;
-                               break;
-                       }
-
-                       /*!
-                        * \note
-                        * Invoke the service thread main, to notify the termination of a TCB
-                        */
-                       ret = svc_ctx->service_thread_main(tcb, NULL, svc_ctx->service_thread_data);
-
-                       /*!
-                        * at this time, the client thread can access this tcb.
-                        * how can I protect this TCB from deletion without disturbing the server thread?
-                        */
-                       tcb_destroy(svc_ctx, tcb);
-               } 
-
                if (FD_ISSET(svc_ctx->evt_pipe[PIPE_READ], &set)) {
                        if (read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) {
                                ErrPrint("Unable to read pipe: %s\n", strerror(errno));
@@ -612,6 +591,62 @@ static void *server_main(void *data)
                }
 
                processing_timer_event(svc_ctx, &set);
+
+               /*!
+                * \note
+                * Destroying TCB should be processed at last.
+                */
+               if (FD_ISSET(svc_ctx->tcb_pipe[PIPE_READ], &set)) {
+                       Eina_List *lockfree_packet_list;
+                       Eina_List *l;
+                       Eina_List *n;
+
+                       if (read(svc_ctx->tcb_pipe[PIPE_READ], &tcb, sizeof(tcb)) != sizeof(tcb)) {
+                               ErrPrint("Unable to read pipe: %s\n", strerror(errno));
+                               ret = -EFAULT;
+                               break;
+                       }
+
+                       if (!tcb) {
+                               ErrPrint("Terminate service thread\n");
+                               ret = -ECANCELED;
+                               break;
+                       }
+
+                       lockfree_packet_list = NULL;
+                       CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
+                       EINA_LIST_FOREACH_SAFE(svc_ctx->packet_list, l, n, packet_info) {
+                               if (packet_info->tcb != tcb)
+                                       continue;
+
+                               svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
+                               lockfree_packet_list = eina_list_append(lockfree_packet_list, packet_info);
+                       }
+                       CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
+
+                       EINA_LIST_FREE(lockfree_packet_list, packet_info) {
+                               ret = read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch));
+                               DbgPrint("Flushing filtered pipe: %d (%c)\n", ret, evt_ch);
+                               ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
+                               if (ret < 0)
+                                       ErrPrint("Service thread returns: %d\n", ret);
+                               packet_destroy(packet_info->packet);
+                               free(packet_info);
+                       }
+
+                       /*!
+                        * \note
+                        * Invoke the service thread main, to notify the termination of a TCB
+                        */
+                       ret = svc_ctx->service_thread_main(tcb, NULL, svc_ctx->service_thread_data);
+
+                       /*!
+                        * at this time, the client thread can access this tcb.
+                        * how can I protect this TCB from deletion without disturbing the server thread?
+                        */
+                       tcb_destroy(svc_ctx, tcb);
+               } 
+
                /* If there is no such triggered FD? */
        }
 
@@ -767,6 +802,28 @@ HAPI int service_common_destroy(struct service_context *svc_ctx)
 
 /*!
  * \note
+ * SERVER THREAD or OTHER THREAD (not main)
+ */
+HAPI int tcb_is_valid(struct service_context *svc_ctx, struct tcb *tcb)
+{
+       Eina_List *l;
+       struct tcb *tmp;
+       int ret = 0;
+
+       CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
+       EINA_LIST_FOREACH(svc_ctx->tcb_list, l, tmp) {
+               if (tmp == tcb /* && tcb->svc_ctx == svc_ctx */) {
+                       ret = tcb->fd;
+                       break;
+               }
+       }
+       CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
+
+       return ret;
+}
+
+/*!
+ * \note
  * SERVER THREAD
  */
 HAPI int tcb_fd(struct tcb *tcb)
@@ -849,6 +906,11 @@ HAPI int service_common_multicast_packet(struct tcb *tcb, struct packet *packet,
        svc_ctx = tcb->svc_ctx;
 
        DbgPrint("Multicasting packets\n");
+
+       /*!
+        * \note
+        * Does not need to make a critical section from here.
+        */
        EINA_LIST_FOREACH(svc_ctx->tcb_list, l, target) {
                if (target == tcb || target->type != type) {
                        DbgPrint("Skip target: %p(%d) == %p/%d\n", target, target->type, tcb, type);
index 82408a3..edebb38 100644 (file)
@@ -171,6 +171,11 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
                        break;
                }
 
+               if (tcb_is_valid(s_info.svc_ctx, tcb) < 0) {
+                       ErrPrint("TCB is not valid (already disconnected?)\n");
+                       break;
+               }
+
                if (service_common_unicast_packet(tcb, packet) < 0)
                        ErrPrint("Unable to send reply packet\n");
                break;
index 8d36a27..335b193 100644 (file)
@@ -77,6 +77,8 @@ struct slave_node {
 
        Ecore_Timer *ttl_timer; /* Time to live */
        Ecore_Timer *activate_timer; /* Waiting hello packet for this time */
+       Ecore_Timer *relaunch_timer; /* Try to relaunch service app */
+       int relaunch_count;
 
        struct timeval activated_at;
 };
@@ -170,6 +172,7 @@ static inline struct slave_node *create_slave_node(const char *name, int is_secu
        slave->pid = (pid_t)-1;
        slave->state = SLAVE_TERMINATED;
        slave->network = network;
+       slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
 
        xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
        xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
@@ -241,6 +244,9 @@ static inline void destroy_slave_node(struct slave_node *slave)
        if (slave->activate_timer)
                ecore_timer_del(slave->activate_timer);
 
+       if (slave->relaunch_timer)
+               ecore_timer_del(slave->relaunch_timer);
+
        DbgFree(slave->abi);
        DbgFree(slave->name);
        DbgFree(slave->pkgname);
@@ -376,6 +382,11 @@ static Eina_Bool activate_timer_cb(void *data)
 {
        struct slave_node *slave = data;
 
+       if (slave->relaunch_timer) {
+               ecore_timer_del(slave->relaunch_timer);
+               slave->relaunch_timer = NULL;
+       }
+
        slave->fault_count++;
        invoke_fault_cb(slave);
 
@@ -396,6 +407,106 @@ static Eina_Bool activate_timer_cb(void *data)
        return ECORE_CALLBACK_CANCEL;
 }
 
+static inline void invoke_slave_fault_handler(struct slave_node *slave)
+{
+       slave->fault_count++;
+       invoke_fault_cb(slave);
+
+       slave_set_reactivation(slave, 0);
+       slave_set_reactivate_instances(slave, 0);
+
+       if (slave_pid(slave) > 0) {
+               int ret;
+               DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
+               ret = aul_terminate_pid(slave_pid(slave));
+               if (ret < 0)
+                       ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
+       }
+}
+
+static Eina_Bool relaunch_timer_cb(void *data)
+{
+       struct slave_node *slave = data;
+       int ret = ECORE_CALLBACK_CANCEL;
+
+       if (!slave->activate_timer) {
+               ErrPrint("Activate timer is not valid\n");
+               slave->relaunch_timer = NULL;
+
+               invoke_slave_fault_handler(slave);
+       } else if (!slave->relaunch_count) {
+               ErrPrint("Relaunch count is exhahausted\n");
+               ecore_timer_del(slave->activate_timer);
+               slave->activate_timer = NULL;
+
+               slave->relaunch_timer = NULL;
+               invoke_slave_fault_handler(slave);
+       } else {
+               bundle *param;
+
+               param = bundle_create();
+               if (!param) {
+                       ErrPrint("Failed to create a bundle\n");
+
+                       ecore_timer_del(slave->activate_timer);
+                       slave->activate_timer = NULL;
+
+                       slave->relaunch_timer = NULL;
+
+                       invoke_slave_fault_handler(slave);
+               } else {
+                       bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
+                       bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
+                       bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
+
+                       slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
+
+                       bundle_free(param);
+
+                       switch (slave->pid) {
+                       case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
+                       case AUL_R_EILLACC:             /**< Illegal Access */
+                       case AUL_R_LOCAL:               /**< Launch by himself */
+                       case AUL_R_ETIMEOUT:            /**< Timeout */
+                       case AUL_R_EINVAL:              /**< Invalid argument */
+                       case AUL_R_OK:                  /**< General success */
+                       case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
+                       case AUL_R_ERROR:               /**< General error */
+                               CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
+                               slave->pid = (pid_t)-1;
+                               ecore_timer_del(slave->activate_timer);
+                               slave->activate_timer = NULL;
+
+                               slave->relaunch_timer = NULL;
+
+                               invoke_slave_fault_handler(slave);
+                               /* Waiting app-launch result */
+                               break;
+                       case AUL_R_ECOMM:               /**< Comunication Error */
+                       case AUL_R_ETERMINATING:        /**< application terminating */
+                       case AUL_R_ECANCELED:           /**< Operation canceled */
+                               slave->relaunch_count--;
+
+                               CRITICAL_LOG("Try relaunch again %s (%d), %d\n", slave_name(slave), slave->pid, slave->relaunch_count);
+                               slave->pid = (pid_t)-1;
+                               ret = ECORE_CALLBACK_RENEW;
+                               ecore_timer_reset(slave->activate_timer);
+                               /* Try again after a few secs later */
+                               break;
+                       default:
+                               DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
+                               slave->relaunch_timer = NULL;
+                               ecore_timer_reset(slave->activate_timer);
+                               break;
+                       }
+               }
+
+       }
+
+       return ret;
+}
+
+
 HAPI int slave_activate(struct slave_node *slave)
 {
        /*!
@@ -421,6 +532,8 @@ HAPI int slave_activate(struct slave_node *slave)
        } else {
                bundle *param;
 
+               slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
+
                param = bundle_create();
                if (!param) {
                        ErrPrint("Failed to create a bundle\n");
@@ -435,18 +548,35 @@ HAPI int slave_activate(struct slave_node *slave)
 
                bundle_free(param);
 
-               if (slave->pid < 0) {
+               switch (slave->pid) {
+               case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
+               case AUL_R_EILLACC:             /**< Illegal Access */
+               case AUL_R_LOCAL:               /**< Launch by himself */
+               case AUL_R_ETIMEOUT:            /**< Timeout */
+               case AUL_R_EINVAL:              /**< Invalid argument */
+               case AUL_R_OK:                  /**< General success */
+               case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
+               case AUL_R_ERROR:               /**< General error */
                        CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
-                       if (slave->pid != AUL_R_ETIMEOUT && slave->pid != AUL_R_ECOMM) {
-                               ErrPrint("failed, because of %d\n", slave->pid);
+                       slave->pid = (pid_t)-1;
+                       /* Waiting app-launch result */
+                       break;
+               case AUL_R_ECOMM:               /**< Comunication Error */
+               case AUL_R_ETERMINATING:        /**< application terminating */
+               case AUL_R_ECANCELED:           /**< Operation canceled */
+                       CRITICAL_LOG("Try relaunch this soon %s (%d)\n", slave_name(slave), slave->pid);
+                       slave->relaunch_timer = ecore_timer_add(SLAVE_RELAUNCH_TIME, relaunch_timer_cb, slave);
+                       if (!slave->relaunch_timer) {
+                               CRITICAL_LOG("Failed to register a relaunch timer (%s)\n", slave_name(slave));
                                slave->pid = (pid_t)-1;
                                return LB_STATUS_ERROR_FAULT;
-                       } else {
-                               ErrPrint("But waiting \"hello\"\n");
-                               slave->pid = (pid_t)-1;
                        }
+                       /* Try again after a few secs later */
+                       break;
+               default:
+                       DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
+                       break;
                }
-               DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
 
                slave->activate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
                if (!slave->activate_timer)
@@ -529,6 +659,11 @@ HAPI int slave_activated(struct slave_node *slave)
                slave->activate_timer = NULL;
        }
 
+       if (slave->relaunch_timer) {
+               ecore_timer_del(slave->relaunch_timer);
+               slave->relaunch_timer = NULL;
+       }
+
        return LB_STATUS_SUCCESS;
 }
 
@@ -607,6 +742,11 @@ HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
                slave->activate_timer = NULL;
        }
 
+       if (slave->relaunch_timer) {
+               ecore_timer_del(slave->relaunch_timer);
+               slave->relaunch_timer = NULL;
+       }
+
        reactivate = invoke_deactivate_cb(slave);
 
        slave = slave_unref(slave);
index 0b01608..723d22a 100644 (file)
@@ -33,7 +33,7 @@
 #include "conf.h"
 
 #ifndef SVC_PKG
-#define SVC_PKG                "org.tizen.data-provider-slave.icon"
+#define SVC_PKG                "com.samsung.data-provider-slave.icon"
 #endif
 
 #ifndef LAUNCH_TIMEOUT
@@ -242,7 +242,7 @@ static int service_thread_main(struct tcb *tcb, struct packet *packet, void *dat
                        s_info.svc_daemon_is_launched = 0;
                }
 
-               return 0;
+               return LB_STATUS_SUCCESS;
        }
 
        cmd = packet_command(packet);
index e8870df..e986215 100644 (file)
@@ -164,7 +164,7 @@ HAPI int xmonitor_update_state(int target_pid)
        struct client_node *client;
        int pid;
 
-       if (!USE_XMONITOR)
+       if (!USE_XMONITOR || target_pid < 0)
                return LB_STATUS_SUCCESS;
 
        win = ecore_x_window_focus_get();